堆(heap)——C++實現


   優先隊列從名字我們就可以猜到,其與隊列之間存在一定的練習,優先隊列與隊列一樣主要是入隊和出隊兩個操作。但是優先隊列與隊列的不同之處在於,優先隊列會將優先級高的先出隊,這在很多情況下非常有用。例如,Windows的MFC是基於消息的響應的機制,內部管理着一個消息隊列,計算機不斷從消息隊列中抓取消息進行響應,那么系統的消息和應用軟件的消息優先級必然不同,我們需要優先響應系統的消息,那么優先隊列就顯示它強大的功能。

  堆的實現我們可以通過一個表,或者一個二叉樹都可以實現。如果通過一個表實現,入隊很方便,但是出隊,必須遍歷一遍表找到優先級最高的那個,需要花費O(N)的時間,效率太低。對於二叉樹來說入隊和出隊都是O(logN)的時間復雜度,但是二叉樹的頻繁刪除會導致樹向右邊傾斜,當然我們可以通過平衡樹來解決這個問題,但是對於優先隊列來說最簡單的方式是通過二叉堆實現。

  二叉堆的實質是一個數組,只是我們用完全二叉樹的形式將其表述出來,完全二叉樹與不完全二叉樹的區別如下圖:

 

  數組的第一位我們空出來是為了去滿足二叉堆的性質:設某元素所處於數組中的位置為i,那么他的左兒子的位置使2*i,他的父元素的位置在i/2;

  因為對於堆來說插入比刪除要頻繁,因此將優先級最高的放在第一個,因為刪除比插入麻煩的多。

  以下是例程,用vector實現:

 1 /************************************************************************/
 2 /* 堆的實現                                                                     */
 3 /************************************************************************/
 4 #include<vector>
 5 namespace stl
 6 {
 7     template<typename T>
 8     class Heap
 9     {
10     public:
11         /************************************************************************/
12         /*構造函數*/
13         Heap(int capacity = 100)
14             :size(0)   //堆中包含數據個數
15         {
16             H.resize(capacity);
17         }
18 
19         ~Heap()
20         {
21         }
22 
23         bool isEmpty()
24         {
25             return size == 0;
26         }
27 
28         void makeEmpty()
29         {
30             size = 0;
31             for (auto it = H.begin(); it != H.end(); it++)
32             {
33                 H.erase(it);
34             }
35         }
36         /************************************************************************/
37         /*插入函數 */
38         void insert(const T & x)
39         {
40             //如果vector中已經存滿了,重新分為大小,數組首地址不存數據
41             if (size == H.size() -1)
42             {
43                 H.resize(2*size);
44             }
45             //size大小加一
46             for (int current = ++size; current > 1 && H[current/2] > x; current /= 2)
47             {
48                  H[current] = H[current/2];
49             }
50             //找到空位將x插入
51             H[current] = x;
52         }
53 
54         /*刪除函數*/
55         T deleteMin()
56         {
57             if (isEmpty())
58             {
59                 throw();
60             }
61             int current, child;
62             T returnVal = H[1];
63             T lastElement = H[size--];   //將最后一個值保存下來,刪除一個元素所以自減運算
64             for (current = 1; 2 * current > size; current = child)
65             {
66                 child = 2 * current;
67                 //防止訪問越界
68                 if (child != size && H[2 * current] > H[2 * current + 1])  
69                 {
70                     ++child;
71                 }
72                 //比較子較小的兒子與最后一個值的大小,如果兒子較小用兒子上濾,否則跳出循環
73                 if (H[child] < lastElement)
74                 {
75                     H[current] = H[child];
76                 }
77                 else
78                 {
79                     break;
80                 }
81             }
82             H[current] = lastElement;
83             return returnVal;
84         }
85 
86     private:
87         std::vector<T> H;
88         int size;
89     };
90 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM