#include <iostream> using namespace std; void Swap(int & left_data, int & right_data) { int auxiliary = left_data; left_data = right_data; right_data = auxiliary; } //---------------------------------------------------------------------------------- // 小頂堆 // 從i開始,到其父節點,父節點的父節點...,依次檢查、調整以符合“小頂堆”的性質 void MinHeapAdjustUp(int data[], int i) { if (i <= 0) return; int j, auxiliary; auxiliary = data[i]; j = (i - 1) / 2; // 父結點 while (j >= 0 && i != 0) { if (data[j] <= auxiliary) break; data[i] = data[j]; // 較大結點下移,替換它的子結點 i = j; j = (i - 1) / 2; } data[i] = auxiliary; } // 向“小頂堆”中添加新的數據 // 每次插入都是將新數據放在數組最后,然后從新插入數據開始, // 到其父節點,父節點的父節點...,依次檢查、調整以符合“小頂堆”的性質 void MinHeapAddData(int data[], int count, int new_data) { data[count] = new_data; MinHeapAdjustUp(data, count); } // 從i節點開始,進行一次從上向下的“小頂堆”調整 // count為節點總數,i節點的左右孩子節點依次為 2*i+1, 2*i+2 void MinHeapAdjustDown(int data[], int i, int count) { int j, auxiliary; auxiliary = data[i]; j = 2 * i + 1; // 左孩子結點 while (j < count) { if (j + 1 < count && data[j + 1] < data[j]) // 在左右孩子中找最小的 j++; if (data[j] >= auxiliary) break; data[i] = data[j]; // 把較小的子結點往上移動,替換它的父結點 i = j; j = 2 * i + 1; } data[i] = auxiliary; } // 從“小頂堆”中刪除數據 // 堆中每次都只能刪除第0個數據。為便於重建堆,將最后一個數據的值賦給根結點 // 然后再從根結點開始進行一次從上向下的調整 void MinHeapDeleteData(int data[], int count) { Swap(data[0], data[count - 1]); MinHeapAdjustDown(data, 0, count - 1); } // 建立“小頂堆” // 因為對葉子結點來說,它已經是一個合法的“小頂堆” // 所以這里只需要,從下往上,從右到左,將每個“非葉結點”當作根結點,將其與其子樹調整成“小頂堆” void MakeMinHeap(int data[], int count) { for (int i = count / 2 - 1; i >= 0; i--) MinHeapAdjustDown(data, i, count); } // 堆排序(利用小頂堆,進行降序排序) void MinHeapSortDesc(int data[], int count) { for (int i = count - 1; i >= 1; i--) { Swap(data[i], data[0]); MinHeapAdjustDown(data, 0, i); } } //---------------------------------------------------------------------------------- // 大頂堆 // 從i開始,到其父節點,父節點的父節點...,依次檢查、調整以符合“大頂堆”的性質 void MaxHeapAdjustUp(int data[], int i) { if (i <= 0) return; int j, auxiliary; auxiliary = data[i]; j = (i - 1) / 2; // 父結點 while (j >= 0 && i != 0) { if (data[j] >= auxiliary) break; data[i] = data[j]; // 較小結點下移,替換它的子結點 i = j; j = (i - 1) / 2; } data[i] = auxiliary; } // 向“大頂堆”中添加新的數據 // 每次插入都是將新數據放在數組最后,然后從新插入數據開始, // 到其父節點,父節點的父節點...,依次檢查、調整以符合“大頂堆”的性質 void MaxHeapAddData(int data[], int count, int new_data) { data[count] = new_data; MaxHeapAdjustUp(data, count); } // 從i節點開始,進行一次從上向下的“大頂堆”調整 // count為節點總數,i節點的左右孩子節點依次為 2*i+1, 2*i+2 void MaxHeapAdjustDown(int data[], int i, int count) { int j, auxiliary; auxiliary = data[i]; j = 2 * i + 1; // 左孩子結點 while (j < count) { if (j + 1 < count && data[j + 1] > data[j]) // 在左右孩子中找最大的 j++; if (data[j] <= auxiliary) break; data[i] = data[j]; // 把較大的子結點往上移動,替換它的父結點 i = j; j = 2 * i + 1; } data[i] = auxiliary; } // 從“大頂堆”中刪除數據 // 堆中每次都只能刪除第0個數據。為便於重建堆,將最后一個數據的值賦給根結點 // 然后再從根結點開始進行一次從上向下的調整 void MaxHeapDeleteData(int data[], int count) { Swap(data[0], data[count - 1]); MaxHeapAdjustDown(data, 0, count - 1); } // 建立“大頂堆” // 因為對葉子結點來說,它已經是一個合法的“大頂堆” // 所以這里只需要,從下往上,從右到左,將每個“非葉結點”當作根結點,將其與其子樹調整成“大頂堆” void MakeMaxHeap(int data[], int count) { for (int i = count / 2 - 1; i >= 0; i--) MaxHeapAdjustDown(data, i, count); } // 堆排序(利用小頂堆,進行降序排序) void MaxHeapSortAsc(int data[], int count) { for (int i = count - 1; i >= 1; i--) { Swap(data[i], data[0]); MaxHeapAdjustDown(data, 0, i); } } int main() { int array[] = {9, 6, 3, 8, 7, 1, 5, 2, 4}; MakeMinHeap(array, 9); MinHeapSortDesc(array, 9); for(int i = 0; i < 9; ++i) cout << array[i] << " "; cout << endl; MakeMaxHeap(array, 9); MaxHeapSortAsc(array, 9); for(int i = 0; i < 9; ++i) cout << array[i] << " "; cout << endl; return 0; }