前言:
理论(文字)知识很枯燥,但是如果读者真正想把一个问题搞明白,搞清楚,光靠成天撸代码是不行的,而需要理解其中的思想本质,否则只能是知其然而不知其所以然,我之前常说:“话不多说,直接上代码”希望不要误导读者。SO,请耐心的看下去,平常心,借用金庸老先生的一句话:“他强由他强,清风拂山岗;他横由他横,明月照大江.他自狠来他自恶,我自一口真气足。”
最后,希望各位同行者可以提出问题,我们共同进步。
博客地址;https://blog.csdn.net/y_16041527点击打开链接
今天我们来讲一讲堆排序,介绍堆排序之前请大家先回想一下直接选择排序,其采用的是直接从剩余记录中线性查找最大记录的方法,没有充分的利用前一轮查找所能得到的information。所以,我们今天用堆数据结构来保持剩余记录相对大小的信息,因而是更有效的选择排序。
涉及到的知识点:
1. 堆排序主要包括两个步骤:(1)对所有记录建立最大堆。(2)取出堆顶的最大记录与数组末端的记录交换,最大记录放在下标n-1的位置,原数组末端元素临时处于根节点;将根元素向下调整到合适的位置,即剩余的n-1个记录重新调整为堆,再取新堆顶最大记录,与数组n-2位交换;.......;不断重复这一操作,直到堆为空。这时数组正好是按从大到小排序。
完整代码如下:(基于最大堆的排序算法 - 元素从下标为0的位置开始存放)
下面....
上代码
// 排序问题总结.cpp: 定义控制台应用程序的入口点。 //排序顺序:从小到大 //堆元素从下标为0的地方开始存放 #include "stdafx.h" #include <iostream> using namespace std; template <class T> class Heap { private: T * A; //存放堆元素的数组 int size; //堆中的元素个数 public: Heap(int InputSize); //构造函数 ~Heap() { delete[] A; cout << "析构函数执行成功" << endl; } //析构函数 void HeapSort(); //堆排序 void PercDown(int p,int N); //将N个元素的数组中以A[p]为根的子堆调整为最大堆 void PrintHeap(); //输出堆中的元素 friend void Swap(T* a, T* b); //交换堆顶和堆末尾的元素 - 友元函数类似于全局函数 }; //Heap类的实现 //Heap(int InputSize) - 构造函数 template <class T> Heap<T>::Heap(int InputSize) { this->size = InputSize; //this指当前对象 this->A = new T[size]; //为数组分配空间 for (int i = 0; i < size; ++i) cin >> A[i]; } //Swap(T,T) - 交换堆顶和堆末尾的元素 template <class T> void Swap(T* a, T* b) { int tmp; tmp = *a; *a = *b; *b = tmp; } //堆排序 - HeapSort() template <class T> void Heap<T>::HeapSort() { int i; //for循环中的语句是针对从下标为0的位置开始存放的情况 //该最大堆的建立是从完全二叉树的倒数第二层开始的 for (i = size / 2 - 1; i >= 0; i--) //建立最大堆 PercDown(i,size); for (i = size - 1; i > 0; i--) { //删除最大堆顶 Swap(&A[0], &A[i]); //将堆顶元素放到堆末尾,并且堆的规模减1 PercDown(0,i); //将规模减小的堆再一次调整为最大堆 } } //将N个元素的数组中以A[p]为根的子堆调整为最大堆 //最大堆的建立不是一步到位的 //先调整其左、右子树,一步一步上滤 template <class T> void Heap<T>::PercDown(int p,int N) { int parent, child; int x; x = A[p]; //取出根节点存放的值 for (parent = p; (parent * 2 + 1) < N; parent = child) { child = parent * 2 + 1; if ((child != N - 1) && (A[child] < A[child + 1])) child++; //child指向左右子节点的最大值 if (x > A[child]) break; //找到了合适的位置 else //下滤x A[parent] = A[child]; } A[parent] = x; } //PrintHeap() template <class T> void Heap<T>::PrintHeap() { for (int i = 0; i < size; ++i) cout << A[i] << " "; } int main() { int size; cin >> size; Heap<int> h(size); h.HeapSort(); h.PrintHeap(); cout << endl; return 0; }
运行结果:
第一行为待排元素个数
第二行为初始序列
第三行为结果