美文网首页二叉树之下
数据结构:经典二叉堆

数据结构:经典二叉堆

作者: 小伟_be27 | 来源:发表于2019-05-02 15:50 被阅读6次

    堆的性质:

    1.根节点比左右叶子节点大(小)
    2.完全二叉树,最后一层都在左侧

    堆的存储

    堆可以用数组存储

    c++实现一个大顶堆

    #include <algorithm>
    #include <cassert>
    
    using namespace std;
    
    
    template<typename Item>
    class MaxHeap{
    
    private:
        Item *data;
        int count;
        int capacity;
        
    
        void shiftUp(int k){
            while( k > 1 && data[k/2] < data[k] ){
                swap( data[k/2], data[k] );
                k /= 2;
            }
        }
    
        void shiftDown(int k){
            while( 2*k <= count ){
                int j = 2*k;
                if( j+1 <= count && data[j+1] > data[j] ) j ++;
                if( data[k] >= data[j] ) break;
                swap( data[k] , data[j] );
                k = j;
            }
        }
    
    public:
    
        MaxHeap(int capacity){
            data = new Item[capacity+1];
            count = 0;
            this->capacity = capacity;
        }
    
        MaxHeap(Item arr[], int n){
            data = new Item[n+1];
            capacity = n;
    
            for( int i = 0 ; i < n ; i ++ )
                data[i+1] = arr[i];
            count = n;
    
            for( int i = count/2 ; i >= 1 ; i -- )
                shiftDown(i);
        }
    
        ~MaxHeap(){
            delete[] data;
        }
    
        int size(){
            return count;
        }
    
        bool isEmpty(){
            return count == 0;
        }
    
        void insert(Item item){
            assert( count + 1 <= capacity );
            data[count+1] = item;
            shiftUp(count+1);
            count ++;
        }
    
        Item extractMax(){
            assert( count > 0 );
            Item ret = data[1];
            swap( data[1] , data[count] );
            count --;
            shiftDown(1);
            return ret;
        }
    
        Item getMax(){
            assert( count > 0 );
            return data[1];
        }
    };
    

    构建最大堆的方法:

    1.将n个元素逐个插入到一个空堆中,算法复杂度是O(nlogn)
    每次插入都要构建一次最大堆,
    每次和父节点比较,若大于父节点,交换位置,还要防止下标越界
    也就是 "shift up"
    2.heapify的过程,算法复杂度为O(n)
    从最后一个非叶子节点的父节点开始,
    相当于减少了一半的元素
    也就是 "shift down"

    堆应用

    1.优先级队列
    普通队列一般都是先进先出,优先级队列后进,但有可能先出
    比如说,医院里排队看病,如果遇到有急诊病人的话,可以在队列的前面优先看病。还有机场排队过安检,如果有乘客飞机即将起飞了,一般机场会有紧急安检通道,可以让比较着急的乘客优先过安检。
    优先队列可以构造一个大顶堆,新插入的元素来维持这个大顶堆,每次从根节点取出元素。
    2.从10亿个数中取出前100个最大的数
    若是这10亿个数,用快速排序,nlogn的时间复杂的,
    可是10亿个数,如果一个数占4byte的话,10亿个数大约快4G,
    如果计算机内存2G的话,一次读取时放不下的。
    可以在内存中维护100个数的小顶堆,若是新来的元素比对顶元素小,直接放弃继续从剩余元素中查找,如果比对堆顶大,则替换堆顶元素,可以用shift down方法在构建一个小顶堆。
    此时算法的时间复杂度是nlog(m),也就是 10亿*log(100)
    3.多路归并排序
    一般归并排序,将数组分为两份,多路含义可以将数组分为多份,d份,
    d越大,归并的层级也就越低,到时每次比较d个数,时间复杂的是O(d),
    如果这个d个数构造一个小顶堆来比较,将堆顶元素取出后,在相应的路上,后移动取出下一个元素,再构造一个小顶堆,这个时间复杂度就是O(dlog(d))

    相关文章

      网友评论

        本文标题:数据结构:经典二叉堆

        本文链接:https://www.haomeiwen.com/subject/fsvinqtx.html