堆的思想及实现

来源:互联网 发布:淘宝网钓鱼灯,感应头灯 编辑:程序博客网 时间:2024/06/06 14:23


1.任意节点小于(或大于)它的所有后裔,最小元(或最大元)在堆的根上(堆序性)。
2.堆总是一棵完全树

完全树:即除了最底层,其他层的节点都被元素填满,且最底层尽可能地从左到右填入。

将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。

支持的基本操作

操作 描述 时间复杂度 build 创建一个空堆 O(n) insert 向堆中插入一个新元素 O(logn) update 将新元素提升使其匹配堆的性质 get 获取当前堆顶元素的值 O(1) delete 删除堆顶元素 O(logn) heapify 使删除堆顶元素的堆再次成为堆

二叉堆的数组实现:给每个节点编号,使得每个父节点的左节点序列号为父节点的二倍,右节点的序列号为父节点序列号的二倍加1

parent(i) = i/2
left child(i) = 2*i
right child(i) = 2*i + 1
堆的基础实现:

#include<iostream>#include<cstring>#include<algorithm>#include<ctime>#include<cmath>#include<cmath>using namespace std;template<typename Item>class MaxHeap{private:    Item* data;    int count;public:    MaxHeap(int capacity){        data=new Item[capacity+1];   //从索引1开始存储         count=0;    }    ~MaxHeap(){        delete [] data;    }     int size(){        return count;    }    bool isEmpty(){        return count==0;    }};int main(){    MaxHeap<int> maxHeap = MaxHeap<int>(100);    cout<<maxHeap.size()<<endl;    return 0;}

堆的基本操作:
1.ShiftUp:先将元素写入数组最后一个位置,然后不断和父节点比较大小,如果该元素大于父节点,则进行交换,直到找到合适的位置。
实现:

void ShiftUp(int k){        while(k>1&&data[k]>data[k/2]){            swap(data[k],data[k/2]);            k/=2;        }    }

插入一个数组元素:

void insert(Item item){        data[count+1]=item;        count++;        ShiftUp(count);    }

2.ShiftDown:从堆中取出一个元素(优先级最高的元素),然后把最后一个元素移动到第一个元素的位置。不断与两个子节点中较大的进行交换,直到找到合适的位置。
实现:

void shiftDown(int k){        //k必须有孩子,只要满足有左孩子即可         while(2*k<=count){            int j=2*k;  //在此轮循环中,data[k]和data[j]交换位置            if(j+1<=count&&data[j+1]>=data[j])                j+=1;            if(data[k]>=data[j])                break;            swap(data[k],data[j]);            k=j;        }    }

取出一个元素:

Item extractMax(){        assert(count>0);        Item ret=data[1];        swap(data[1],data[count]);        count--;        shiftDown(1);        return ret;    } 
原创粉丝点击