3. 算法实现
根据2中的算法思想,编写代码实现以上四个函数。C++实现如下:
1 template<class T>
2
3 //首先调用makeHeap,将数据成员heap变成最大堆,才能接着使用popHeap,pushHeap
4 //sortHeap将输入的最大堆变成递增输出
5 class MaxHeap
6 {
7 public:
8 MaxHeap();
9 vector& getMaxHeap()
10 {
11 return heap;
12 }
13 void printHeap() //访问heap数据成员
14 {
15 if (heap.size() < 1) return;
16 for (int i = 1; i < heap.size(); i++)
17 cout << heap[i] << " ";
18 cout << endl;
19 }
20
21 void pushHeap(T value);
22 T popHeap(); //返回最大元素,并删除最大元素
23 void sortHeap(vector& oldHeap);
24 void makeHeap(vector vec);
25 private:
26 vector heap;
27 int maxIdx; //最后一个元素的下标
28 };
29
30 template<class T>
31 MaxHeap::MaxHeap()
32 {
33 }
34
35 template<class T>
36 void MaxHeap::makeHeap(vector vec)
37 {
38 int n = vec.size();
39 heap.resize(n + 1);
40 maxIdx = n;
41 for (int i = 1; i < n + 1; i++)
42 heap[i] = vec[i - 1];
43 for (int i = maxIdx / 2; i > 0; i--)
44 {
45 int parentIdx = i; //父节点下标
46 int childIdx = 2 * i; //孩子节点的下标
47 while (childIdx <= maxIdx) {
48 if (childIdx + 1 <= maxIdx && heap[childIdx + 1] >= heap[childIdx] && heap[childIdx + 1] > heap[parentIdx]) //右孩子最大
49 {
50 swap(heap[parentIdx], heap[childIdx + 1]);
51 parentIdx = childIdx + 1;
52 }
53 else if (heap[childIdx] > heap[parentIdx]) //左孩子最大
54 {
55 swap(heap[parentIdx], heap[childIdx]);
56 parentIdx = childIdx;
57 }
58 else
59 break;
60 childIdx = 2 * parentIdx;
61 }
62 }
63 }
64
65 template<class T>
66 void MaxHeap::pushHeap(T value)
67 {
68 heap.push_back(value); //先构造完全二叉树
69 maxIdx++;
70 int i = maxIdx;
71 while (i!=1 && heap[i] > heap[i / 2]) {
72 swap(heap[i], heap[i / 2]);
73 i = i / 2;
74 }
75 }
76
77 template<class T>
78 T MaxHeap::popHeap()
79 {
80 if (maxIdx == 0) {
81 cout << "empty MaxHeap" << endl;
82 }
83 swap(heap[1], heap[maxIdx]);
84 int i = 1;
85 int ci = 2 * i; //左孩子节点
86 while (ci<maxIdx) {
87 if (ci + 1 < maxIdx && heap[ci] < heap[ci + 1] && heap[i] < heap[ci + 1]) //右孩子最大
88 {
89 swap(heap[i], heap[ci + 1]);
90 i = ci + 1;
91 }
92 else if (heap[ci] > heap[i]) //左孩子最大
93 {
94 swap(heap[i], heap[ci]);
95 i = ci;
96 }
97 else
98 break;
99 ci = 2 * i;
100 }
101 T tmp = heap.back();
102 heap.pop_back();
103 maxIdx--;
104 return tmp;
105 }
106
107 template<class T>
108 void MaxHeap::sortHeap(vector& oldheap) //传入参数必须是maxHeap
109 {
110 oldheap.insert(oldheap.begin(), oldheap[0]); //0为填充
111 int n = size(oldheap)-1;
112 int endIdx = n;
113 for (int k = 1; k < n; k++)
114 {
115 //此段代码与pop_heap基本一致
116 swap(oldheap[1], oldheap[endIdx]);
117 int i = 1;
118 int ci = 2 * i; //左孩子节点
119 while (ci < endIdx) {
120 if (ci + 1 < endIdx && oldheap[ci] < oldheap[ci + 1] && oldheap[i] < oldheap[ci + 1]) //右孩子最大
121 {
122 swap(oldheap[i], oldheap[ci + 1]);
123 i = ci + 1;
124 }
125 else if (oldheap[ci] > oldheap[i]) //左孩子最大
126 {
127 swap(oldheap[i], oldheap[ci]);
128 i = ci;
129 }
130 else
131 break;
132 ci = 2 * i;
133 }
134 endIdx--; //每次排序后,最后一个元素就是最大,所以无序数组的下标要减少
135 }
136 oldheap.erase(oldheap.begin()); //去掉填充位
137 }
为了验证以上代码合理性,利用STL自带的make_heap,sort_heap,pop_heap,push_heap进行对照:
1 int main()
2 {
3 vector<int> heap1 = { 0,1,2,3,4,8,9,3,5 };
4 make_heap(heap1.begin(), heap1.end()); //STL自带的
5 for (int i = 0; i < size(heap1); i++)
6 cout << heap1[i] << " ";
7 cout << endl;
8
9 vector<int> vec = { 0,1,2,3,4,8,9,3,5 };
10 MaxHeap<int> heap2;
11 heap2.makeHeap(vec);
12 heap2.printHeap();
13
14
15 heap1.push_back(7);
16 push_heap(heap1.begin(), heap1.end());
17 for (int i = 0; i < size(heap1); i++)
18 cout << heap1[i] << " ";
19 cout << endl;
20
21 heap2.pushHeap(7);
22 heap2.printHeap();
23
24
25 pop_heap(heap1.begin(), heap1.end());
26 cout << heap1.back()<//自带的库函数不会删除最大的元素
27 heap1.pop_back();
28 for (int i = 0; i < size(heap1); i++)
29 cout << heap1[i] << " ";
30 cout << endl;
31
32 cout << heap2.popHeap() << endl;
33 heap2.printHeap();
34
35
36 vector<int> tmpheap = heap1;
37 sort_heap(heap1.begin(), heap1.end());
38 for (int i = 0; i < size(heap1); i++)
39 cout << heap1[i] << " ";
40 cout << endl;
41
42 heap2.sortHeap(tmpheap);
43 for (int i = 0; i < size(tmpheap); i++)
44 cout << tmpheap[i] << " ";
45 cout << endl;
46
47
48 system("pause");
49 }
PS: STL的最大堆函数需要包含头文件#include