#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; }