堆排序
什么是堆
如何构造堆
功能:将一段数据转换为max-heap.(父节点不小于子节点的完全二叉树。)
基本步骤:
从某一子树开始进行下溯操作。
开始的子树:Distance parent = (len - 2)/2; 最后的叶节点不必执行下溯。
该子树执行完下溯后parent—;
下溯:将空洞节点(这里是parent,即开始执行下溯的节点)与较大子节点对调,并持续下放,
直到叶节点为止。
如何进行堆排序
关键是取走根节点后的重新构造!
方法:
堆排序算法实现
/*堆排序*/ #include <iostream> #include <vector> using namespace std; template<typename Comparable> void heapSort(vector<Comparable> &a) { /*构造堆,因为叶节点无需下溯,所以从a.size()/2开始下溯*/ for (int i = a.size()/2; i >= 0; i--) { percDown(a, i, a.size()); } /*堆排序:删除根节点形成空洞,最后编号叶节点与空洞节点对调,然后从根节点处下溯*/ for (int j = a.size() - 1; j > 0; j--) { swap(a[0], a[j]); percDown(a, 0, j); } } /*返回节点i的左孩子编号2i*/ inline int leftChild(int i) { return (2 * i); } /** * i是开始下溯的编号; * n是堆的最大长度。 */ template<typename Comparable> void percDown(vector<Comparable> &a, int i, int n) { int child; //当前与节点i比较的孩子编号。 Comparable tmp; for (tmp = a[i]; leftChild(i) < n; i = child) { child = leftChild(i); /*比较左右孩子,找出孩子值最大的孩子编号*/ if (child != n-1 && a[child] < a[child + 1]) { child++; } /*节点与最大孩子比较*/ if (tmp < a[child]) { a[i] = a[child]; } else { break; } } a[i] = tmp; } int main() { int array[9] = {50, 10, 90, 30, 70, 40, 80, 60, 20}; vector<int> intVec(array, array + 9); heapSort(intVec); for (vector<int>::iterator iter = intVec.begin(); iter != intVec.end(); iter++) { cout << *iter << endl; } }