堆排序
按照书上的定义:堆是一个完全二叉树,且二叉树中的任意一个非叶子结点值都大于(小于)左右孩子结点值。利用这个原理可确定堆中的根节点为最大(小)值。
堆排序的思想:堆采用顺序存放。当用数组建立一个堆后,将堆中的根节点与堆的最后一个元素互换位置,即将最大(小)值输出,然后把除了最后一个元素以外的数组再构建成堆,再把此时堆中根节点与堆的最后一个元素互换位置(是堆,不是数组)。再不断循环此步骤即可实现有序。
思路中提到两个步骤:把数组构建成堆,将堆中的根节点与堆的最后一个元素互换位置。用代码实现这两个步骤即可实现堆排序。
先给出堆的示例图:
下图为构建堆的图解:
以上图为例,把97和38互换位置后,就要对除了97以外的数重新构建成堆。然后不断循环此步骤。
1 void run(vector<int>& arr, int root, int curr) {//root是当前子树的根节点,curr是当前范围,因为最后面的是已经排好序的了。 2 int i = root, j = i * 2; // j是左孩子 3 while (j <= curr) { //子结点必须在当前范围 4 if (j < curr && arr[j] < arr[j + 1]) 5 j++; //选出左右孩子结点中较大的 6 if (arr[i] < arr[j]) { //如果父节点小于孩子结点 7 swap(arr[i], arr[j]); //就互换 8 i = j; //向下循环 9 j = i * 2; //进入孩子结点的孩子结点 10 } 11 else //如果父节点大于子节点就结束循环 12 break; 13 } 14 } 15 16 void CreateHeap(vector<int>& arr, int curr) { 17 for (int i = curr / 2; i > 0; i--) 18 run(arr, i, curr); 19 } 20 21 void HeapSort(vector<int>& arr) { 22 for (int i = arr.size()-1; i>=1; i--) { 23 CreateHeap(arr, i); 24 swap(arr[1], arr[i]); //使根节点与堆中最后一个元素互换 25 } 26 }