数据结构(八)堆

堆–c++实现

堆的定义

一颗大根树(小跟树) 是这样一棵树,其中每个节点的值都大于(小于)或等于其子节点(如果有子节点的话)的值。

大根树:

14
12
7
10
8
6
9
6
5
30
25

小根数:

2
4
6
7
8
10
11
20
21
50
10

在以上树图中虽然都是二叉树,但在大根树和小根树中,这是不必要的,其节点的子节点个数可以任意。

一个大根堆(小根堆) 既是大根树(小跟树)也是完全二叉树

完全二叉树:一棵深度为k的有n个结点的 二叉树 ,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与 满二叉树 中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。

简而言之,完全二叉树是由满二叉树按照顺序删减节点得到的。

堆的应用

对于优先级队列如果使用链表描述,每次删除或者查找时都需要遍历全部链表元素去寻找优先级最高(最低)的元素,所需的实现复杂度是 O ( n ) O(n) O(n),而如果使用堆来实现优先级队列,每次查找和删除的时间复杂度是 O ( h e i g h t ) O(height) O(height), height为完全二叉树的高度,即所需时间复杂度为 O ( l o g n ) O(logn) O(logn)

堆的描述

在Heap.h文件中声明了堆的原型。

因为堆是完全二叉树,所以数组描述是较为方便的。

此处使用了vector(动态数组),其详细使用方法见:vector用法

#include<vector>

template<class T>
class Heap {
private:
    std::vector<T> heap;
    int heapSize;
public:
    Heap();
    ~Heap();
    const T& top() const;
    void push(const T& element);
    void pop();
    int size() const;
    bool isEmpty() const;
};

堆的实现

#include "Heap.h"
template<class T>
Heap<T>::Heap() {
    heap =  std::vector<T>(10);
    heapSize = 0;
}

template<class T>
Heap<T>::~Heap() {

}

template<class T>
const T& Heap<T>::top() const {
    return heap[1];
}

template<class T>
void Heap<T>::push(const T &element) {
    int current = ++heapSize;
    if (heapSize == 1){
        heap[1] = element;
        return;
    }
    if (heap[current/2] > element){
        heap[current] = element;
        return;
    }
    while (current != 1&&heap[current/2] < element){  //当插入的元素位置不是根节点时,让它与自己的双亲节点比较
        heap[current] = heap[current/2];              //如果双亲节点小于此元素,则交换。
        heap[current/2] = element;
        current /= 2;
    }
}

template<class T>
void Heap<T>::pop() {
    int i = 1;
    heapSize--;
    while (2 * i < heapSize){
        if (heap[2 * i] > heap[2*i +1]){
            heap[i] = heap[2 * i];
            i = 2*i;
        } else{
            heap[i] = heap[2*i +1];
            i = 2*i +1;
        }
    }
}

template<class T>
int Heap<T>::size() const {
    return heapSize;
}

template<class T>
bool Heap<T>::isEmpty() const {
    return heapSize == 0;
}

测试程序:

#include <iostream>
using namespace std;
int main(){
    Heap<int> heap;
    heap.push(12);
    heap.push(23);
    heap.push(14);
    heap.push(2);
    heap.push(4);
    heap.push(59);
    cout << "top = " << heap.top()<<endl;
    cout << "size = " << heap.size() << endl;
    heap.pop();
    cout << "after pop, top = " << heap.top() << endl;
    cout << "now size = " << heap.size();
    return 0;
}
5912232414
123456

数组描述如上表

2
4
12
14
23
59

二叉树描述如上图

测试结果:

top = 59
size = 6
after pop, top = 23
now size = 5
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值