数据结构与算法——堆

在《算法设计技巧与分析》这本书的第四章,介绍了堆。于是按照上面的伪代码实现了一下。

数据结构定义maxHeap.hpp如下,

 1 #ifndef MAX_HEAP_HPP_
2 #define MAX_HEAP_HPP_
3
4 #include <vector>
5 using std::vector;
6
7 class MaxHeap
8 {
9 public:
10 MaxHeap(vector<int>& A);
11 void Insert(int x);
12 int DeleteMax();
13 void Sort();
14 void Print();
15 private:
16 void SiftUp(int i);
17 void SiftDown(int i);
18 void Delete(int i);
19
20 private:
21 vector<int> array;
22 };
23
24 #endif

实现maxHeap.cpp如下

  1 #include "maxHeap.hpp"
2
3 #include <vector>
4 #include <iostream>
5 using std::vector;
6 using std::cout;
7 using std::endl;
8
9 MaxHeap::MaxHeap(vector<int>& A)
10 {
11 int i = 0;
12 array = vector<int>(A.size()+1);
13 for(i=1;i<A.size()+1;i++)
14 array[i] = A[i-1];
15 int n = array.size()-1;
16 for(i=n>>1;i>0;i--)
17 {
18 // cout << "i:" << i << "\t array[i]:" << array[i] << endl;
19 SiftDown(i);
20 // Print();
21 }
22 }
23
24 void MaxHeap::SiftUp(int i)
25 {
26 if(i==1)
27 return;
28 int tmp = 0;
29 while(true)
30 {
31 if(array[i]>array[i>>1])
32 {
33 tmp = array[i];
34 array[i] = array[i>>1];
35 array[i>>1] = tmp;
36 }
37 else
38 break;
39 i = i>>1;
40 if(i==1)
41 break;
42 }
43 }
44
45 void MaxHeap::SiftDown(int i)
46 {
47 if((i<<1)>array.size()-1)
48 return;
49 int tmp = 0;
50 while(true)
51 {
52 i = i<<1;
53 if(i+1<=array.size()-1 && array[i+1]>array[i])
54 i = i+1;
55 if(array[i>>1]<array[i])
56 {
57 tmp = array[i];
58 array[i] = array[i>>1];
59 array[i>>1] = tmp;
60 }
61 else
62 break;
63 if((i<<1)>array.size()-1)
64 break;
65 }
66 }
67
68 void MaxHeap::Insert(int x)
69 {
70 array.push_back(x);
71 SiftUp(array.size()-1);
72 }
73
74 void MaxHeap::Delete(int i)
75 {
76 int x = array[i];
77 int y = array[array.size()-1];
78 array.pop_back();
79 if(i==array.size())
80 return;
81 array[i] = y;
82 if(y>=x)
83 SiftUp(i);
84 else
85 SiftDown(i);
86 }
87
88 int MaxHeap::DeleteMax()
89 {
90 int x = array[1];
91 Delete(1);
92 return x;
93 }
94
95 void MaxHeap::Sort()
96 {
97 int i = 0;
98 int n = array.size();
99 vector<int> sortedArray(n,0);
100 for(i=1;i<n;i++)
101 {
102 sortedArray[i] = DeleteMax();
103 Print();
104 }
105 array = sortedArray;
106 }
107
108 void MaxHeap::Print()
109 {
110 cout << "Heap Array:" << endl;
111 int i = 0;
112 for(i=1;i<array.size();i++)
113 cout << "\t" << array[i] ;
114 cout << endl;
115 }

最后的测试主程序main.cpp如下:

 1 #include "maxHeap.hpp"
2
3 #include <vector>
4 #include <iostream>
5 using std::vector;
6 using std::cout;
7 using std::endl;
8
9 int main()
10 {
11 //int D[]= {1, 6, 7, 10, 9, 3, 5, 8};
12 int D[] = { 5, 7, 3, 6, 4, 11, 10, 9, 17, 20};
13 cout << "original array:" << endl;
14 for(int i=0;i<10;i++)
15 cout << "\t" << D[i];
16 cout << endl;
17 vector<int> A(D,D+sizeof(D)/sizeof(int));
18 MaxHeap B(A);
19 B.Print();
20
21 B.Sort();
22 cout << "sorted array:" << endl;
23 B.Print();
24
25 return 0;
26 }

最后的测试结果实现了降序排序。

其实网上已经有很多实现的代码了,自己实现一下,锻炼一下。

比较自己的代码和网上已经实现的代码(如http://www.cppblog.com/Darren/archive/2009/05/17/80169.html),自己在MaxHeap里面用了一个vector,网上一般是用一个数组指针结合size实现。

在堆排序的实现中,调用SiftDown(H[1..j-1],1),如果数据结构里面用的是数组指针,那么是很好传递参数的,SiftDown(array_start,array_length,down_index)三个参数,分别是数组起始位置(这里是位置,不是地址,因为数组指针已经在数据结构里面了),数组长度,和要调整的元素位置。而我在数据结构里面使用的vector,这里就不是很好办了,如果要指定只取前j-1个元素,或许需要借助另外一个vector,进行两次复制,这就太浪费了。最后勉强使用DeleteMax,每次把最大的元素挑出来,然后实现排序,效率肯定没有直接调用SiftDown(H[1..j-1],1)好了。

数据结构的定义相当关键,会影响到函数的实现和调用方式,影响到程序的效率。

vector虽然很好用,但是也不能滥用。

网上经典的数据结构和算法的实现,应该多学习学习。



原文地址:https://www.cnblogs.com/Frandy/p/heap_max_sort.html