【数据结构】堆 Heap
堆(Heap)的C++实现
1 #include <iostream>
2 using namespace std;
3
4 template <class T>
5 class Heap
6 {
7 private:
8 // hlist points at the array which can be allocated by
9 // the constructor (inArray == 0) or passed as a
10 // parameter (inArray == 1)
11 T *hlist;
12 int inArray;
13
14 // max number allowed and current size of heap
15 int maxheapsize;
16 int heapsize; // identifies end of list
17
18 // error message utility function
19 void error(char errmsg[]);
20
21 // utility functions for Delete/Insert to restore heap
22 void FilterDown(int i);
23 void FilterUp(int i);
24 public:
25 // constructors/destructor
26 Heap(int maxsize); // create empty heap
27 Heap(T arr[],int n); // "heapify" arr
28 Heap(const Heap<T>& H); // copy constructor
29 ~Heap(void); // destructor
30
31 // overloaded operators: "=", "[]", "T*"
32 Heap<T>& operator= (const Heap<T>& rhs);
33 const T& operator[](int i);
34
35 // list methods
36 int ListSize(void) const;
37 int ListEmpty(void) const;
38 int ListFull(void) const;
39 void Insert(const T& item);
40 T Delete(void);
41 void ClearList(void);
42
43 void show()
44 {
45 for(int i=0;i<heapsize;i++)
46 cout << hlist[i] << " ";
47 cout << endl;
48 }
49 };
50
51 // print error message and terminate the program
52 template <class T>
53 void Heap<T>::error(char errmsg[])
54 {
55 cerr << errmsg << endl;
56 exit(1);
57 }
58
59 // utility to restore the heap; starting at index i,
60 // exchange parent and child so that subtree from i is a heap
61 template <class T>
62 void Heap<T>::FilterDown (int i)
63 {
64 int currentpos, childpos;
65 T target;
66
67 // start at i and set its value as the target
68 currentpos = i;
69 target = hlist[i];
70
71 // compute the left child index and begin a scan down
72 // path of children, stopping at end of list (heapsize)
73 childpos = 2 * i + 1;
74 while (childpos < heapsize) // check for end of list
75 {
76 // Index of right child is childpos+1. Set childpos to
77 // index of the smaller of the two children
78 if ((childpos+1 < heapsize) &&
79 (hlist[childpos+1] <= hlist[childpos]))
80 childpos = childpos + 1;
81
82 // parent is less than children, heap ok. quit
83 if (target <= hlist[childpos])
84 break;
85 else
86 {
87 // move value of smaller child to the parent;
88 // position of smaller child is now vacated
89 hlist[currentpos] = hlist[childpos];
90
91 // update indices to continue the scan
92 currentpos = childpos;
93 childpos = 2 * currentpos + 1;
94 }
95 }
96 // assign target to the most recently vacated position
97 hlist[currentpos] = target;
98 }
99
100 // utility to restore the heap; starting at index i,
101 // move up tree from parent to parent. exchange elements if
102 // the child has a value less than the parent
103 template <class T>
104 void Heap<T>::FilterUp (int i)
105 {
106 int currentpos, parentpos;
107 T target;
108
109 // currentpos is an index that traverses path of parents.
110 // target is value hlist[i] and is repositioned in path
111 currentpos = i;
112 parentpos = (i-1)/2;
113 target = hlist[i];
114
115 // traverse path of parents up to the root
116 while (currentpos != 0)
117 {
118 // if parent <= target, heap condition is ok. break!
119 if (hlist[parentpos] <= target)
120 break;
121 else
122 // move child value to parent and update indices to
123 // look at the next parent.
124 {
125 // move data from parent position to current
126 // position. update current position to parent
127 // position. compute next parent
128 hlist[currentpos] = hlist[parentpos];
129 currentpos = parentpos;
130 parentpos = (currentpos-1)/2;
131 }
132 }
133 // the correct location has been discovered. assign target
134 hlist[currentpos] = target;
135 }
136
137 template <class T>
138 Heap<T>::Heap(int size)
139 {
140 if (size <= 0)
141 error("Bad list size.");
142 hlist = new T[size];
143 if (hlist == 0)
144 error("Memory allocation failure.");
145 maxheapsize = size;
146 heapsize = 0;
147 inArray = 0;
148 }
149
150 // constructor to convert an array to a heap.
151 // the array and its size are passed as parameters
152 template <class T>
153 Heap<T>::Heap(T arr[],int n)
154 {
155 int currentpos;
156
157 // n <= 0 is invalid array size; terminate program
158 if (n <= 0)
159 error("Bad list size.");
160
161 // use n to set heap size and maximum heap size; assign
162 // the arrary arr to the heap list
163 maxheapsize = n;
164 heapsize = n ;
165 hlist = new T[n];
166 memcpy(hlist,arr,sizeof(T)*n);
167
168 // set currentpos to last parent index; call FilterDown
169 // in a loop with index in the range currentpos down to 0;
170 currentpos = (heapsize - 2)/2;
171 while(currentpos >= 0)
172 {
173 // establish heap condition for subtree with root
174 // hlist[currentpos]
175 FilterDown(currentpos);
176 currentpos--;
177 }
178 // set inArray to True so Heap will not deallocate array
179 inArray = 1;
180 }
181
182 template <class T>
183 Heap<T>::Heap(const Heap<T>& A)
184 {
185 int n = A.heapsize;
186
187 heapsize = n;
188 maxheapsize = A.maxheapsize;
189 hlist = new T[maxheapsize];
190 if (hlist == 0)
191 error("Memory allocation failure.");
192 while (n--)
193 hlist[n] = A.hlist[n];
194 inArray = 0; // always build new heap in dynamic memory
195 }
196
197 template <class T>
198 Heap<T>::~Heap(void)
199 {
200 if (!inArray) // don't delete hlist unless allocated.
201 delete[] hlist;
202 }
203
204 template <class T>
205 Heap<T>& Heap<T>::operator=(const Heap<T>& rhs)
206 {
207 int n = rhs.heapsize;
208
209 heapsize = n;
210 if (maxheapsize != rhs.maxheapsize || inArray)
211 {
212 maxheapsize = rhs.maxheapsize;
213 // destroy the heap if not allocated in static array
214 if (!inArray)
215 delete [] hlist;
216 hlist = new T[maxheapsize]; // allocate a new array
217 if (hlist == NULL)
218 error("Memory allocation failure.");
219 }
220 while (n--) // do item by item copy
221 hlist[n] = rhs.hlist[n];
222 inArray = 0; // assignment puts heap in dynamic memory
223 return *this;
224 }
225
226 template <class T>
227 int Heap<T>::ListSize(void) const
228 {
229 return heapsize;
230 }
231
232 template <class T>
233 int Heap<T>::ListEmpty(void) const
234 {
235 return heapsize == 0;
236 }
237
238 template <class T>
239 int Heap<T>::ListFull(void) const
240 {
241 return heapsize == maxheapsize;
242 }
243
244 template <class T>
245 const T& Heap<T>::operator[](int i)
246 {
247 if (i < 0 || i >= heapsize)
248 error("Heap index out of range: ");
249 return hlist[i];
250 }
251
252 // insert a new item in the heap and update the structure
253 template <class T>
254 void Heap<T>::Insert(const T& item)
255 {
256 // check for a full heap and terminate if True
257 if (heapsize == maxheapsize)
258 error("Heap full");
259 // store the item at the end of the heap and increment
260 // heapsize; call FilterUp to restore the heap condition
261 hlist[heapsize] = item;
262 FilterUp(heapsize);
263 heapsize++;
264 }
265
266 // return the value of the first element and update the heap
267 // a deletion with an empty heap creates an error message and
268 // terminates the program
269 template <class T>
270 T Heap<T>::Delete(void)
271 {
272 T tempitem;
273
274 // check for an empty heap
275 if (heapsize == 0)
276 error("Heap empty");
277
278 // copy the root to tempitem; replace the root with the last
279 // value in the heap and decrement the heap size
280 tempitem = hlist[0];
281 hlist[0] = hlist[heapsize-1];
282 heapsize--;
283
284 // call FilterDown to position the new root value in heap
285 FilterDown(0);
286
287 // return the original root value
288 return tempitem;
289 }
290
291 template <class T>
292 void Heap<T>::ClearList(void)
293 {
294 heapsize = 0;
295 }
296
297
298 int main()
299 {
300
301 int x[] = {23,21,4,5,6,7};
302 Heap<int> h(x,6);
303 h.show();
304
305 system("pause");
306 return 0;
307 }
2 using namespace std;
3
4 template <class T>
5 class Heap
6 {
7 private:
8 // hlist points at the array which can be allocated by
9 // the constructor (inArray == 0) or passed as a
10 // parameter (inArray == 1)
11 T *hlist;
12 int inArray;
13
14 // max number allowed and current size of heap
15 int maxheapsize;
16 int heapsize; // identifies end of list
17
18 // error message utility function
19 void error(char errmsg[]);
20
21 // utility functions for Delete/Insert to restore heap
22 void FilterDown(int i);
23 void FilterUp(int i);
24 public:
25 // constructors/destructor
26 Heap(int maxsize); // create empty heap
27 Heap(T arr[],int n); // "heapify" arr
28 Heap(const Heap<T>& H); // copy constructor
29 ~Heap(void); // destructor
30
31 // overloaded operators: "=", "[]", "T*"
32 Heap<T>& operator= (const Heap<T>& rhs);
33 const T& operator[](int i);
34
35 // list methods
36 int ListSize(void) const;
37 int ListEmpty(void) const;
38 int ListFull(void) const;
39 void Insert(const T& item);
40 T Delete(void);
41 void ClearList(void);
42
43 void show()
44 {
45 for(int i=0;i<heapsize;i++)
46 cout << hlist[i] << " ";
47 cout << endl;
48 }
49 };
50
51 // print error message and terminate the program
52 template <class T>
53 void Heap<T>::error(char errmsg[])
54 {
55 cerr << errmsg << endl;
56 exit(1);
57 }
58
59 // utility to restore the heap; starting at index i,
60 // exchange parent and child so that subtree from i is a heap
61 template <class T>
62 void Heap<T>::FilterDown (int i)
63 {
64 int currentpos, childpos;
65 T target;
66
67 // start at i and set its value as the target
68 currentpos = i;
69 target = hlist[i];
70
71 // compute the left child index and begin a scan down
72 // path of children, stopping at end of list (heapsize)
73 childpos = 2 * i + 1;
74 while (childpos < heapsize) // check for end of list
75 {
76 // Index of right child is childpos+1. Set childpos to
77 // index of the smaller of the two children
78 if ((childpos+1 < heapsize) &&
79 (hlist[childpos+1] <= hlist[childpos]))
80 childpos = childpos + 1;
81
82 // parent is less than children, heap ok. quit
83 if (target <= hlist[childpos])
84 break;
85 else
86 {
87 // move value of smaller child to the parent;
88 // position of smaller child is now vacated
89 hlist[currentpos] = hlist[childpos];
90
91 // update indices to continue the scan
92 currentpos = childpos;
93 childpos = 2 * currentpos + 1;
94 }
95 }
96 // assign target to the most recently vacated position
97 hlist[currentpos] = target;
98 }
99
100 // utility to restore the heap; starting at index i,
101 // move up tree from parent to parent. exchange elements if
102 // the child has a value less than the parent
103 template <class T>
104 void Heap<T>::FilterUp (int i)
105 {
106 int currentpos, parentpos;
107 T target;
108
109 // currentpos is an index that traverses path of parents.
110 // target is value hlist[i] and is repositioned in path
111 currentpos = i;
112 parentpos = (i-1)/2;
113 target = hlist[i];
114
115 // traverse path of parents up to the root
116 while (currentpos != 0)
117 {
118 // if parent <= target, heap condition is ok. break!
119 if (hlist[parentpos] <= target)
120 break;
121 else
122 // move child value to parent and update indices to
123 // look at the next parent.
124 {
125 // move data from parent position to current
126 // position. update current position to parent
127 // position. compute next parent
128 hlist[currentpos] = hlist[parentpos];
129 currentpos = parentpos;
130 parentpos = (currentpos-1)/2;
131 }
132 }
133 // the correct location has been discovered. assign target
134 hlist[currentpos] = target;
135 }
136
137 template <class T>
138 Heap<T>::Heap(int size)
139 {
140 if (size <= 0)
141 error("Bad list size.");
142 hlist = new T[size];
143 if (hlist == 0)
144 error("Memory allocation failure.");
145 maxheapsize = size;
146 heapsize = 0;
147 inArray = 0;
148 }
149
150 // constructor to convert an array to a heap.
151 // the array and its size are passed as parameters
152 template <class T>
153 Heap<T>::Heap(T arr[],int n)
154 {
155 int currentpos;
156
157 // n <= 0 is invalid array size; terminate program
158 if (n <= 0)
159 error("Bad list size.");
160
161 // use n to set heap size and maximum heap size; assign
162 // the arrary arr to the heap list
163 maxheapsize = n;
164 heapsize = n ;
165 hlist = new T[n];
166 memcpy(hlist,arr,sizeof(T)*n);
167
168 // set currentpos to last parent index; call FilterDown
169 // in a loop with index in the range currentpos down to 0;
170 currentpos = (heapsize - 2)/2;
171 while(currentpos >= 0)
172 {
173 // establish heap condition for subtree with root
174 // hlist[currentpos]
175 FilterDown(currentpos);
176 currentpos--;
177 }
178 // set inArray to True so Heap will not deallocate array
179 inArray = 1;
180 }
181
182 template <class T>
183 Heap<T>::Heap(const Heap<T>& A)
184 {
185 int n = A.heapsize;
186
187 heapsize = n;
188 maxheapsize = A.maxheapsize;
189 hlist = new T[maxheapsize];
190 if (hlist == 0)
191 error("Memory allocation failure.");
192 while (n--)
193 hlist[n] = A.hlist[n];
194 inArray = 0; // always build new heap in dynamic memory
195 }
196
197 template <class T>
198 Heap<T>::~Heap(void)
199 {
200 if (!inArray) // don't delete hlist unless allocated.
201 delete[] hlist;
202 }
203
204 template <class T>
205 Heap<T>& Heap<T>::operator=(const Heap<T>& rhs)
206 {
207 int n = rhs.heapsize;
208
209 heapsize = n;
210 if (maxheapsize != rhs.maxheapsize || inArray)
211 {
212 maxheapsize = rhs.maxheapsize;
213 // destroy the heap if not allocated in static array
214 if (!inArray)
215 delete [] hlist;
216 hlist = new T[maxheapsize]; // allocate a new array
217 if (hlist == NULL)
218 error("Memory allocation failure.");
219 }
220 while (n--) // do item by item copy
221 hlist[n] = rhs.hlist[n];
222 inArray = 0; // assignment puts heap in dynamic memory
223 return *this;
224 }
225
226 template <class T>
227 int Heap<T>::ListSize(void) const
228 {
229 return heapsize;
230 }
231
232 template <class T>
233 int Heap<T>::ListEmpty(void) const
234 {
235 return heapsize == 0;
236 }
237
238 template <class T>
239 int Heap<T>::ListFull(void) const
240 {
241 return heapsize == maxheapsize;
242 }
243
244 template <class T>
245 const T& Heap<T>::operator[](int i)
246 {
247 if (i < 0 || i >= heapsize)
248 error("Heap index out of range: ");
249 return hlist[i];
250 }
251
252 // insert a new item in the heap and update the structure
253 template <class T>
254 void Heap<T>::Insert(const T& item)
255 {
256 // check for a full heap and terminate if True
257 if (heapsize == maxheapsize)
258 error("Heap full");
259 // store the item at the end of the heap and increment
260 // heapsize; call FilterUp to restore the heap condition
261 hlist[heapsize] = item;
262 FilterUp(heapsize);
263 heapsize++;
264 }
265
266 // return the value of the first element and update the heap
267 // a deletion with an empty heap creates an error message and
268 // terminates the program
269 template <class T>
270 T Heap<T>::Delete(void)
271 {
272 T tempitem;
273
274 // check for an empty heap
275 if (heapsize == 0)
276 error("Heap empty");
277
278 // copy the root to tempitem; replace the root with the last
279 // value in the heap and decrement the heap size
280 tempitem = hlist[0];
281 hlist[0] = hlist[heapsize-1];
282 heapsize--;
283
284 // call FilterDown to position the new root value in heap
285 FilterDown(0);
286
287 // return the original root value
288 return tempitem;
289 }
290
291 template <class T>
292 void Heap<T>::ClearList(void)
293 {
294 heapsize = 0;
295 }
296
297
298 int main()
299 {
300
301 int x[] = {23,21,4,5,6,7};
302 Heap<int> h(x,6);
303 h.show();
304
305 system("pause");
306 return 0;
307 }