九、堆与优先队列---(3)输出堆中元素并获取和删除堆顶元素

本文介绍了一个简单的堆数据结构实现,包括元素的插入、输出、获取堆顶元素及删除堆顶元素等功能。通过示例展示了如何使用这个堆类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
*将堆中元素存储在数组里,输出堆中元素也就是输出数组里的元素,并获取和删
*除堆顶元素
*/


#include<iostream>
using namespace std;
class Heap {
private:
    int *data, size;
public:
    Heap(int length_input) {
        data = new int[length_input];
        size = 0;
    }
    ~Heap() {
        delete[] data;
    }
    void push(int value) {
        data[size] = value;
        int current = size;
        int father = (current - 1) / 2;
        while (data[current] > data[father]) {
            swap(data[current], data[father]);
            current = father;
            father = (current - 1) / 2;
        }
        size++;
    }
    //输出堆中元素
    void output() {
        for (int i = 0; i < size; i++) {
            cout << data[i] << " ";
        }
        cout << endl;
    }
    //获取堆顶元素,即data[0]
    int top() {
        return data[0];
    }
    
    //下滤操作的调整策略:当前元素和左右两个孩子比较大小,如果两个孩子权值较大者,比当前元素权值大,
    //则将该孩子和当前元素进行交换,如果此时仍不满足堆序性,则调用update函数对该孩子继续进行堆调整
    //pos:当前调整位置, n:当前堆中元素个数
    void update(int pos, int n) {
        int lchild = 2 * pos + 1, rchild = 2 * pos + 2;//等于当前元素的左、右孩子位置
        int max_value = pos;
        if (lchild < n && data[lchild] > data[max_value]) {
            max_value = lchild;
        }
        if (rchild < n && data[rchild] > data[max_value]) {
            max_value = rchild;
        }
        if (max_value != pos) {
            swap(data[pos], data[max_value]);
            update(max_value, n);
        }
    }
    
    
    //删除堆顶元素
    //方法:将堆顶元素和对的最后一个元素进行交换, 然后对堆顶元素做一个自上而下的堆调整,即下滤操作。
    void pop() {
        swap(data[0], data[size - 1]);
        size--;
        update(0, size);
    }
    
};
int main() {
    int arr[10] = { 12, 9, 30, 24, 30, 4, 55, 64, 22, 37 };
    Heap heap(100);
    for (int i = 0; i < 10; i++) {
        heap.push(arr[i]);
    }
    heap.output();
    cout << heap.top() << endl;
    heap.pop();
    heap.output();
    return 0;
}
<think>好的,我现在需要回答用户关于、大根优先队列以及在JavaScript中实现它们的问题。首先,我需要回忆这些概念的定义原理,确保自己理解正确。然后,考虑如何用JavaScript实现,解释每一步的原理。同时,要注意用户可能需要的是清晰的解释实用的代码示例。 首先,是一种特殊的完全二叉树,分为大根小根。大根的特点是父节点的值大于或等于子节点的值。优先队列通常使用来实现,因为可以高效地获取删除最大或最小元素。 接下来,我需要确定如何在JavaScript中实现。由于JS没有内置的结构,通常用数组来模拟。数组中的元素按层次顺序存储,父节点子节点的索引可以通过公式计算。例如,父节点索引为(i-1)/2,左子节点为2i+1,右子节点为2i+2。 然后,实现大根的关键操作:插入元素提取最大值。插入时,将元素添加到数组末尾,然后上浮到合适的位置。提取最大值时,交换堆顶末尾元素删除末尾,然后调整堆顶下沉。 优先队列基于实现,主要操作是入队出队,分别对应的插入提取。需要确保每次操作后的性质保持不变。 在编写代码时,需要注意边界条件,比如为空时的处理。同时,要解释每个方法的作用实现原理,例如上浮下沉的过程。 现在,检查是否有遗漏的部分。例如,是否需要处理的构建过程?用户可能想知道如何将一个无序数组转化为,但可能优先队列的实现更关注插入提取。因此,可能不需要详细解释构建的算法,除非用户特别提到。 另外,考虑代码的可读性效率。例如,在比较子节点时,需要确保不越界,选择较大的子节点进行交换。在上浮下沉的过程中,循环条件是否正确,避免死循环。 最后,总结这些概念之间的关系,帮助用户理解优先队列为什么常用来实现,以及大根在其中的作用。确保示例代码清晰,注释详细,方便用户理解每一步的操作。</think>以下是对、大根优先队列的解释及JavaScript实现: --- ### 一、核心概念解析 **1. Heap)** - 完全二叉树结构 - 满足性质:任意节点的值总 ≥(大根)或 ≤(小根)子节点的值 - 物理存储通常使用数组实现 - 时间复杂度:插入/删除 $O(\log n)$,获取极值 $O(1)$ **2. 大根(Max Heap)** - 父节点值 ≥ 子节点值 - 根节点是整个的最大值 - 典型应用场景:优先队列 **3. 优先队列(Priority Queue)** - 抽象数据结构 - 元素带有优先级,按优先级出队 - 常用大根实现(高优先级=大数值) --- ### 二、JavaScript实现代码 ```javascript class MaxHeap { constructor() { this.heap = []; } // 获取父节点索引(公式推导) parentIndex(i) { return Math.floor((i - 1) / 2); } // 插入元素(上浮操作) insert(val) { this.heap.push(val); let i = this.heap.length - 1; while (i > 0 && this.heap[i] > this.heap[this.parentIndex(i)]) { const p = this.parentIndex(i); [this.heap[i], this.heap[p]] = [this.heap[p], this.heap[i]]; // ES6解构交换 i = p; } } // 调整堆顶元素(下沉操作) heapify(i) { const n = this.heap.length; let max = i; const l = 2 * i + 1; // 左子节点索引 const r = 2 * i + 2; // 右子节点索引 if (l < n && this.heap[l] > this.heap[max]) max = l; if (r < n && this.heap[r] > this.heap[max]) max = r; if (max !== i) { [this.heap[i], this.heap[max]] = [this.heap[max], this.heap[i]]; this.heapify(max); // 递归调整 } } // 提取最大值 extractMax() { if (this.heap.length === 0) return null; const max = this.heap[0]; this.heap[0] = this.heap.pop(); // 用最后一个元素替换堆顶 this.heapify(0); // 从堆顶开始调整 return max; } } // 优先队列实现 class PriorityQueue { constructor() { this.heap = new MaxHeap(); } enqueue(val) { this.heap.insert(val); } dequeue() { return this.heap.extractMax(); } peek() { return this.heap.heap[0] || null; } } ``` --- ### 三、关键操作原理 **插入元素(上浮)**: 1. 将新元素添加到数组末尾 2. 循环比较父节点的大小 3. 若大于父节点则交换位置 4. 时间复杂度:$O(\log n)$ **提取最大值(下沉)**: 1. 取出堆顶元素(最大值) 2. 将最后一个元素移到堆顶 3. 循环比较子节点的大小 4. 较大的子节点交换位置 5. 时间复杂度:$O(\log n)$ --- ### 四、使用示例 ```javascript const pq = new PriorityQueue(); pq.enqueue(3); // 队列:3 pq.enqueue(5); // 队列:5,3 pq.enqueue(1); // 队列:5,3,1 console.log(pq.dequeue()); // 输出5(当前队列:3,1) console.log(pq.peek()); // 输出3 ``` --- ### 五、应用场景 - 任务调度系统(高优先级任务优先执行) - 图算法(Dijkstra最短路径算法) -K个有序链表 - 数据流中实时获取Top K元素 通过结构实现的优先队列,能够在$O(1)$时间复杂度获取最大值,插入/删除操作只需$O(\log n)$时间复杂度,比普通数组实现效率更高。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值