维护堆的性质

MAX-HEAPIFY是用于维护最大堆性质的重要过程。输入为待维护的数组,与待维护的节点i。时间复杂度为O(lgn),即树的高度h

MAX_HEAPIFY(A,i)
    l=LEFT(i)
    r=RIGHT(i)
    if l<=A.heapSize and A[l]>A[i]
        largest=l
    else largest=i
    if r<=A.heapSize and A[r]>A[largest]
        largest=r
    if largest!=i
        exchange A[i] with A[largest]
        MAX-HEAPIFY(A,largest)

建堆

利用自底向上的方法利用过程MAX-HEAPIFY把一个大小为n=A.lenght的数组转换为最大堆。因为数组中A([n/2]+1..n)中的元素都是叶子节点。每个叶子节点可看成只含有一个元素的堆。因此建堆过程BUILD-MAX-HEAP过程只需调用n/2次 MAX-HEAPIFY即可。

BUILD-MAX-HEAP(A)
    A.heap-size=A.length
    for i=[A.length/2] downto 1
        MAX-HEAPIFY(A,i)

一个c++的最大堆类

#include <iostream>
#include <vector>

using namespace std;
class UnderflowException{ };

template<typename Comparable>
class BinaryHeap
{
public:
    explicit BinaryHeap(int capacity=100)
    :array(capacity+1),currentSize(0){}

    explicit BinaryHeap(const vector<Comparable> &items)
    :array(items.size()+10),currentSize(items.size()){
        for(int i=0;i<items.size();++i)
            //为方便操作,堆从下标1开始存储
            array[i+1]=items[i];
        buildMaxHeap();
    }

    bool isEmpty()const{
        return currentSize==0;
    }

    int currSize()const{
        return currentSize;
    }

    void print(){
        for(int i=1;i<=currentSize;++i){
            cout<<array[i]<<" ";
        }
        cout<<endl;
    }

    Comparable& findMax() const{
        if (isEmpty())
            throw UnderflowException();
        return array[1];
    }

    //Increase the value in position i to key
    int increaseKey(int i,const Comparable &key){
        if (key<array[i]){
            cout<<"new key is smaller than current,can not change"<<endl;
            return -1;
        }
        array[i]=key;
        while(i>1 && array[i/2]<array[i]){
            std::swap(array[i/2],array[i]);
            i=i/2;
        }
        return 0;
    }

    //Insert the x into the heap
    void insert(const Comparable &x){
        if(currentSize==array.size()-1)
            array.resize(array.size()*2);

        int hole=++currentSize;
        array[hole]=INT_MIN;
        increaseKey(hole,x);
    }

    /**
     * Remove the maximum item and return it
     * Throw Underflow if empty
     */
     Comparable deleteMax(){
        if(isEmpty())
            throw UnderflowException{};
        Comparable tmp=array[1];
        std::swap(array[1],array[currentSize--]);
        maxHeapIfy(1);
        return tmp;
     }

    //heapsort
    void heapSort(vector<Comparable> &vec){
        while(currentSize){
            Comparable tmp=deleteMax();
            vec.push_back(tmp);
        }
    }

private:
    int currentSize; //number of elements in heap
    vector<Comparable> array;

    /**
     * Establish heap order property from an arbitraty
     * arrangement of items.Runs in nlgn times.
     */
     void buildMaxHeap(){
        for(int i=currentSize/2;i>0;--i)
            maxHeapIfy(i);
     }

    /**
     * 保持最大堆的性质,使得根节点大于子节点
     */
     void maxHeapIfy(int hole){
        int child;
        Comparable tmp=std::move(array[hole]);
        for(;hole*2<=currentSize;hole=child){

            child=hole*2;//the left child
            //if the right child exist,choose the max child
            if(child!=currentSize && array[child+1]>array[child])
                ++child;//child is the right child
            //if the max child greater than the father,exchange
            if (array[child]>tmp)
                array[hole]=std::move(array[child]);
            else
                break;
        }
        array[hole]=std::move(tmp);
     }
};

int main()  
{  

    vector<int> vec{4,1,3,2,16,9,10,14,8,7};  
    BinaryHeap<int> heap{vec};  
    heap.print();  
    heap.increaseKey(9,15);  
    heap.print();  
    heap.insert(10);  
    heap.print();  
    vector<int> vecsort;  
    heap.heapSort(vecsort);  
    for(auto v:vecsort)  
        cout<<v<<" ";  
    cout<<endl;  

}  

c++11中的堆操作

see reference

#include <iostream>     // std::cout
#include <algorithm>    // std::make_heap, std::pop_heap, std::push_heap, std::sort_heap
#include <vector>       // std::vector

using namespace std;

auto comp=[](int v1,int v2){return v1>v2;};//升序

int main () {
  int myints[] = {10,20,30,5,15};
  std::vector<int> v(myints,myints+5);

  //建立一个最小堆
  std::make_heap (v.begin(),v.end(),comp);
  for(auto val:v)
    cout<<val<<" ";
  cout<<endl;


  /**
   * 将最小堆的最小元素放到数组末尾
   * 因为实现方式,就是首元素与末尾元素交换后,再执行一次维护最小堆的操作
   * 类似于上面自己写的类中的delete
   */

  std::pop_heap (v.begin(),v.end(),comp);
  for(auto val:v)
    cout<<val<<" ";
  cout<<endl;

  v.pop_back();
  for(auto val:v)
    cout<<val<<" ";
  cout<<endl;


  v.push_back(99); 
  for(auto val:v)
    cout<<val<<" ";
  cout<<endl;

  /**
   * 再插入一个元素后执行一次维护最小堆的操作
   * 类似于上面自己写的堆中的insert
   */
  std::push_heap (v.begin(),v.end(),comp);
  for(auto val:v)
    cout<<val<<" ";
  cout<<endl;

  std::sort_heap (v.begin(),v.end(),comp);
  for(auto val:v)
    cout<<val<<" ";
  cout<<endl;

  return 0;
}

堆的相关算法题

1.Merge k Sorted Lists

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

解题思路:vector中元素为每个列表的头部指针,vector维护一个最小堆的性质,然后不断pop出第一个元素即最小值。因为维护最小堆的复杂度为lgn,总共有K个列表,则复杂度为Klgn。

解题技巧:与其自己写一个最小堆,不如用好c++11中的make_heap,pop_heap,push_heap等,因为自己写一个最小堆,index要从1开始,所以可能要copy一遍元素。用c++中的alrogithm会比较简单。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};

class Solution {

public:
    ListNode* mergeKLists(vector<ListNode*>& lists){
        ListNode fake_head(0);
        if(lists.empty()){
            return NULL;
        }

        for(auto itr=lists.begin();itr!=lists.end();){
           if(*itr==NULL){
               itr=lists.erase(itr);
           }
           else{
               itr++;
           }

        }
        auto cmp=[](ListNode *l,ListNode *r){return l->val>r->val;};

        make_heap(lists.begin(),lists.end(),cmp);

        ListNode* ll=&fake_head;
        while(!lists.empty()){
            ll->next=lists.front();
            ll=ll->next;
            pop_heap(lists.begin(),lists.end(),cmp);
            if(lists.back()->next==NULL)
                lists.pop_back();
            else{
                lists.back()=lists.back()->next;
                push_heap(lists.begin(),lists.end(),cmp);
            }
        }
        return fake_head.next;
    }
};

2.POJ1442 Black Box

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值