【内部排序】七:堆排序(Heap Sort)详解与代码(超详细注释版)
2015-04-22 22:03
309 查看
堆排序是选择排序的一种,每一趟从待排序的记录中选出关键字最小的记录,顺序放在有序的子表中,直到全部记录排序完毕。
二叉堆: 二叉堆其实是一棵有着特殊性质的完全二叉树,父节点的值总是大于等于(或小于等于)其左右孩子的值;每个节点的左右子树都是一棵这样的二叉堆。
大根堆和小根堆:如果一个二叉堆的父节点的值总是大于其左右孩子的值,那么该二叉堆为大根堆,反之为小根堆。
堆排序: 输出堆顶元素后,将剩余的元素再调整为二叉堆,继而再次输出堆顶元素,再将剩余的元素调整为二叉堆,反复执行该过程,这样便可输出一个有序序列,这个过程叫做堆排序。
实现堆排序的三个步骤如下:
1、如何将一个无序序列建成一个二叉堆(构造初始堆);
叶子节点可以认为是一个堆(因为堆的定义中并没有对左右孩子间的关系有任何要求,所以可以将这几个叶子节点看做是一个堆),然后从第一个非叶子节点向前直到第一个节点,插入堆中,构成新堆。可利用下面的调整堆实现。
2、在去掉堆顶元素后,如何将剩余的元素调整为一个二叉堆(调整堆);
3、最后完成堆排序。
堆顶元素(a[0])和最后一个元素(a[i])交换位置,最大元素归位。
算法分析
堆排序的最坏时间复杂度为O(nlgn)。堆排序的平均性能较接近于最坏性能。
由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。
堆排序是就地排序,辅助空间为O(1),
它是不稳定的排序方法。
最后给出超详细注释版的完整源码:
print()没有实现,很简单如下:
关于堆排序的讲解,兰亭风雨在/article/1337333.html里讲解的非常好,推荐大家看看。
我这里做个总结:二叉堆: 二叉堆其实是一棵有着特殊性质的完全二叉树,父节点的值总是大于等于(或小于等于)其左右孩子的值;每个节点的左右子树都是一棵这样的二叉堆。
大根堆和小根堆:如果一个二叉堆的父节点的值总是大于其左右孩子的值,那么该二叉堆为大根堆,反之为小根堆。
堆排序: 输出堆顶元素后,将剩余的元素再调整为二叉堆,继而再次输出堆顶元素,再将剩余的元素调整为二叉堆,反复执行该过程,这样便可输出一个有序序列,这个过程叫做堆排序。
实现堆排序的三个步骤如下:
1、如何将一个无序序列建成一个二叉堆(构造初始堆);
叶子节点可以认为是一个堆(因为堆的定义中并没有对左右孩子间的关系有任何要求,所以可以将这几个叶子节点看做是一个堆),然后从第一个非叶子节点向前直到第一个节点,插入堆中,构成新堆。可利用下面的调整堆实现。
//把数组建成为大根堆,循环建立初始堆(从第一个非叶子节点向前直到第一个节点) //第一个非叶子节点的位置序号为n/2-1 for (i=n/2-1;i>=0;i--) HeapSift(a,i,n-1);
2、在去掉堆顶元素后,如何将剩余的元素调整为一个二叉堆(调整堆);
//堆排序——调整堆 /* arr[low+1...high]满足大根堆的定义, 将arr[low]加入到最大堆arr[low+1...high]中, 调整arr[low]的位置,使arr[low...high]也成为大根堆 注:由于数组从0开始计算序号,也就是二叉堆的根节点序号为0, 因此序号为i的左右子节点的序号分别为2i+1和2i+2 */ void HeapSift(int a[],int low,int high) { int temp=a[low]; //保存堆中第一个节点(要调整) int i=2*low+1; //a[i]是a[low]的左孩子,i为该节点的左孩子在数组中的位置序号 while(i<high) { //比较左右孩子,找出左右孩子中最大的那个 if (i+1<=high&&a[i+1]>a[i]) i++; if (a[i]>temp) //如果子节点大于父节点 { a[low]=a[i]; //把最大的子节点赋值给父节点(比较后不用交换,子节点的值还是原来的值(可以理解为挖空)) low=i; //修改low(把i位置作为父节点),以便继续向下调整 i=2*low+1; //修改i(令i为low位置节点的左孩子序号),以便继续向下调整 } else //如果符合堆的定义,则不用调整位置 break; } a[low]=temp; //把堆中第一个节点放入最终位置(最后挖空的位置),调整完毕。 }
3、最后完成堆排序。
堆顶元素(a[0])和最后一个元素(a[i])交换位置,最大元素归位。
//进行堆排序 for (i=n-1;i>0;i--) //从后往前,保存最大的数 { //堆顶元素(a[0])和最后一个元素(a[i])交换位置, //这样最后的一个位置保存的是最大的数,最大元素归位 //每次循环依次将次大的数值在放进其前面一个位置, //这样得到的顺序就是从小到大 int temp =a[i]; a[i]=a[0]; a[0]=temp; HeapSift(a,0,i-1); //堆顶元素(a[0])保存最后一个位置的元素,导致不一定为堆,所以重新调整 }
算法分析
堆排序的最坏时间复杂度为O(nlgn)。堆排序的平均性能较接近于最坏性能。
由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。
堆排序是就地排序,辅助空间为O(1),
它是不稳定的排序方法。
最后给出超详细注释版的完整源码:
#include <iostream>
using namespace std;
//堆排序——调整堆 /* arr[low+1...high]满足大根堆的定义, 将arr[low]加入到最大堆arr[low+1...high]中, 调整arr[low]的位置,使arr[low...high]也成为大根堆 注:由于数组从0开始计算序号,也就是二叉堆的根节点序号为0, 因此序号为i的左右子节点的序号分别为2i+1和2i+2 */ void HeapSift(int a[],int low,int high) { int temp=a[low]; //保存堆中第一个节点(要调整) int i=2*low+1; //a[i]是a[low]的左孩子,i为该节点的左孩子在数组中的位置序号 while(i<high) { //比较左右孩子,找出左右孩子中最大的那个 if (i+1<=high&&a[i+1]>a[i]) i++; if (a[i]>temp) //如果子节点大于父节点 { a[low]=a[i]; //把最大的子节点赋值给父节点(比较后不用交换,子节点的值还是原来的值(可以理解为挖空)) low=i; //修改low(把i位置作为父节点),以便继续向下调整 i=2*low+1; //修改i(令i为low位置节点的左孩子序号),以便继续向下调整 } else //如果符合堆的定义,则不用调整位置 break; } a[low]=temp; //把堆中第一个节点放入最终位置(最后挖空的位置),调整完毕。 }
/*
堆排序(从小到大)
需要建立大根堆
*/
void Heap_Sort(int a[],int n)
{
int i;
//把数组建成为大根堆,循环建立初始堆(从第一个非叶子节点向前直到第一个节点)
//第一个非叶子节点的位置序号为len/2-1
for (i=n/2-1;i>=0;i--)
HeapSift(a,i,n-1);
//进行堆排序 for (i=n-1;i>0;i--) //从后往前,保存最大的数 { //堆顶元素(a[0])和最后一个元素(a[i])交换位置, //这样最后的一个位置保存的是最大的数,最大元素归位 //每次循环依次将次大的数值在放进其前面一个位置, //这样得到的顺序就是从小到大 int temp =a[i]; a[i]=a[0]; a[0]=temp; HeapSift(a,0,i-1); //堆顶元素(a[0])保存最后一个位置的元素,导致不一定为堆,所以重新调整 }
}
int main()
{
int a[8] = {3,1,5,7,2,4,9,6};
print(a,8);
//straight_insertion_sort4(a,8);
//binary_insertion_sort(a,8);
//shell_sort(a,8);
//Bubble_Sort(a,8);
//select_sort(a,8);
Heap_Sort(a,8);
print(a,8);
system("pause");
return 0;
}
print()没有实现,很简单如下:
void print(int a[],int n) { for (int j=0;j<n;j++) { cout<<a[j]<<" "; } cout<<endl; }
相关文章推荐
- HeapSort堆排序Java实现图文代码详解
- 数据结构 - 堆排序(heap sort) 详解 及 代码(C++)
- PHP排序算法之堆排序(Heap Sort)实例详解
- java 数据结构之堆排序(HeapSort)详解及实例
- 堆排序 HeapSort C语言实现 附严蔚敏数据结构P282 代码错误
- 图文详解Heap Sort堆排序算法及JavaScript的代码实现
- 【内部排序】八:归并排序(Merge Sort)详解与代码
- 数据结构 - 堆排序(heap sort) 具体解释 及 代码(C++)
- Java实现堆排序(Heapsort)实例代码
- 图文详解Heap Sort堆排序算法及JavaScript的代码实现
- 堆排序 (Heapsort)
- 排序1+4:归并排序(MergeSort)和堆排序(HeapSort)
- 一天一排序之“堆排序(heapsort)”
- 堆排序(heapsort)
- 堆(heap)、堆排序(heapSort)、优先级队列
- 堆排序heapsort
- C++ 堆排序 (HeapSort)
- 堆排序(HeapSort)
- 经典算法(9)- 堆排序(Heapsort)
- 排序1+4:归并排序(MergeSort)和堆排序(HeapSort)