堆操作及应用

1. 堆是一个完全二叉树,堆主要设计到的操作有插入,删除,堆化。

2. 堆的主要应用有堆排序:从小到大排序,使用大顶堆;从大到小排序,使用小顶堆。

3. 下面以大顶堆为例,给出实现代码:

View Code
  1 #include <iostream>
  2 #include <cassert>
  3 
  4 using namespace std;
  5 
  6 //大顶堆的实现
  7 class Myheap
  8 {
  9 public:
 10     Myheap(int hSize=DefaultSize)
 11     {
 12         if (hSize>DefaultSize)
 13         {
 14             heapSize=hSize;
 15         }
 16         else
 17         {
 18             heapSize=DefaultSize;
 19         }
 20         data=new int[heapSize];
 21         currentSize=0;
 22     }
 23     int leftChild(int pos)
 24     {
 25         return 2*pos+1;
 26     }
 27     int rightChild(int pos)
 28     {
 29         return 2*pos+2;
 30     }
 31     int parent(int i)
 32     {
 33         return (i-1)>>1;
 34     }
 35 
 36     //递归的处理方式
 37     //void Max_Heapify(int pos)
 38     //{
 39     //    assert(pos<currentSize && pos>=0);
 40     //    int l=leftChild(pos);
 41     //    int r=rightChild(pos);
 42     //    int maxNumber=pos;
 43     //    if (l<currentSize)
 44     //    {
 45     //        maxNumber=data[l]>data[maxNumber] ? l:maxNumber;
 46     //    }
 47     //    if (r<currentSize)
 48     //    {
 49     //        maxNumber=data[r]>data[maxNumber] ? r:maxNumber;
 50     //    }
 51     //    if (maxNumber!=pos)
 52     //    {
 53     //        swap(data[pos],data[maxNumber]);
 54     //        Max_Heapify(maxNumber);
 55     //    }
 56     //}
 57 
 58     //使用循环替代尾递归
 59     void Max_Heapify(int pos)
 60     {
 61         assert(pos<currentSize && pos>=0);
 62         while (pos<currentSize)
 63         {
 64             int l=leftChild(pos);
 65             int r=rightChild(pos);
 66             int maxNumber=pos;
 67             if (l<currentSize)
 68             {
 69                 maxNumber=data[l]>data[maxNumber] ? l:maxNumber;
 70             }
 71             if (r<currentSize)
 72             {
 73                 maxNumber=data[r]>data[maxNumber] ? r:maxNumber;
 74             }
 75             if (maxNumber!=pos)
 76             {
 77                 swap(data[pos],data[maxNumber]);
 78             }
 79             else
 80             {
 81                 break;
 82             }
 83             pos=maxNumber;
 84         }
 85     }
 86     bool isFull()
 87     {
 88         return currentSize==heapSize;
 89     }
 90 
 91     //插入,将元素插入到末尾,然后将元素上浮到合适的位置
 92     void insert(int elem)
 93     {
 94         if (isFull())
 95         {
 96             cout<<"Heap is full!!!"<<endl;
 97             return ;
 98         }
 99         data[currentSize++]=elem;
100         int pa=parent(currentSize-1);
101         int cur=currentSize-1;
102         while ((pa>=0) && (data[pa]<data[cur]))
103         {
104             swap(data[pa],data[cur]);
105             cur=pa;
106             pa=parent(cur);
107         }
108     }
109 
110     //删除堆顶的元素
111     //将堆顶元素和最后一个元素交换,然后将堆顶元素下降
112     //到一个合适的位置
113     void deleteMax()
114     {
115         swap(data[currentSize-1],data[0]);
116         currentSize--;
117         Max_Heapify(0);
118     }
119 
120     //打印
121     void print()
122     {
123         for (int i=0;i<heapSize;i++)
124         {
125             cout<<data[i]<<"  ";
126         }
127         cout<<endl;
128     }
129 
130     //堆排序
131     void HeapSort()
132     {
133         int i=currentSize-1;
134         for (;i>=1;i--)
135         {
136             swap(data[i],data[0]);
137             currentSize--;
138             Max_Heapify(0);
139         }
140     }
141     ~Myheap()
142     {
143         delete data;
144     }
145 protected:
146 private:
147     enum {DefaultSize=10};
148     int heapSize;
149     int currentSize;
150     int *data;
151 };
152 
153 int main()
154 {
155     enum {length=11};
156     int number[length]={12,23,2,34,5,123,6,0,1,34,0};
157     Myheap myheap(length);
158     for(int i=0;i<length;i++)
159     {
160         myheap.insert(number[i]);
161     }
162     myheap.print();
163     //int pPos=myheap.parent(length-1);
164     //for (int i=pPos;i>=0;i--)
165     //{
166     //    myheap.Max_Heapify(i);
167     //}
168     myheap.HeapSort();
169     myheap.print();
170     //myheap.deleteMax();
171     //myheap.print();
172 }

4. 堆的应用:

  (1) 一个文件中包含了1亿个随机整数,如何快速的找到最大(小)的100万个数字?(时间复杂度:O(n lg k))。

  答:若要找出100万个最大的数,需要维护一个含有100万元素的小顶堆。遍历1亿个数,如果某个数比小顶堆最小元素大,则用这个数替代小顶堆中的最小数,之后使小顶堆最小堆化。遍历结束之后,堆中存储的就是最大的100万个数。遍历一次的时间复杂度O(n),最小堆化O(lgk)。总的时间复杂度O(n lg k)。

5.

堆是一种非常基础但很实用的数据结构,很多复杂算法或者数据结构的基础就是堆,因而,了解和掌握堆这种数据结构显得尤为重要。

 

参考资料:

http://dongxicheng.org/structure/bitmap/

算法导论

posted @ 2012-08-07 17:14  kasuosuo  阅读(238)  评论(0编辑  收藏  举报