您的位置:首页 > 理论基础 > 数据结构算法

堆排序--数据结构排序1

2017-12-04 20:48 232 查看
堆排序

堆排序是选择排序的一种,是利用堆的性质进行排序,如果需要升序排序,选择大顶堆。如果是降序排序,选择小顶堆。

堆排序思想

堆排序的思想就是堆的性质进行排序。分为无序区和有序区,将堆顶元素与最后一个一个元素进行兑换,扩大有序区,减少无序区。另外,注意堆是完全二叉树,因此如果是数组的话,数组元素对应的就是完全二叉树的层次遍历。

堆排序的性能

时间复杂度:O(nlogn)

空间复杂度:O(1)

不稳定排序

时间复杂度解析。我们在每次重新调整堆时,都要将父节点与孩子节点比较,这样,每次重新调整堆的时间复杂度变为O(logn),而堆排序时有n-1次重新调整堆的操作,建堆时有((len-1)/2+1)次重新调整堆的操作,因此堆排序的平均时间复杂度为O(n*logn)。由于我们这里没有借用辅助存储空间,因此空间复杂度为O(1)。

堆排序在排序元素较少时有点大才小用,待排序列元素较多时,堆排序还是很有效的。另外,堆排序在最坏情况下,时间复杂度也为O(n*logn)。相对于快速排序(平均时间复杂度为O(n*logn),最坏情况下为O(n*n)),这是堆排序的最大优点。

堆排序步骤

1.初始化堆。

2.交换堆中第一个元素和最后一个元素,然后对无序区进行调整,即调整堆。

大顶堆

对于根节点,num[i],如果num[i]>num[2*1+1] 并且 num[i]>num[2*1+2],则为大顶堆,即堆顶元素大于任何一个孩子节点。

小顶堆

与大顶堆相反。

堆排序代码C++

#include <iostream>

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;
/**
HeapAdjust是对堆进行调整
parent是堆的顶点,
num是需要排序的数组,
len是待排序的数组长度
*/
void HeapAdjust(int num[],int parent,int len){
int temp = num[parent];//临时记录堆顶元素
int child = parent*2+1;//二叉树的性质,根节点为i,左孩子节点为2*i+1,有孩子节点为2*i+2
while(child<len){//孩子节点不能超过长度
//判断左孩子大还是右孩子大
if(child+1<len && num[child]<num[child+1]){
child++;//变成右孩子
}
//如果不需要更换parent对应的值,直接结束循环,此步骤一定不能省略
if(num[child]<temp){
break;
}
//把根节点的数数值变成孩子中较大的
num[parent]=num[child];
//循环找出temp需要放的位置
parent = child;
child = child*2 +1;
} //循环结束就是找到了temp需要放的位置
num[parent]=temp;
}
void HeapSort(int num[],int len){
//初始化建立堆,i是第一个非叶子节点的编号
//第一个非叶子节点的位置序号为(len-1)/2
for<
4000
/span>(int i=(len-1)/2;i>=0;i--){
HeapAdjust(num,i,len);//i为parent
}
for(int i=len-1;i>=0;i--){//第一个与最后一个交换,所以i为len-1更简单
int temp = num[i];
num[i]=num[0];
num[0]=temp;
HeapAdjust(num,0,i);//从0-i需要调整,剩下的都已经是有序的啦
//堆排序的输出
cout<<"第"<<len-i<<"趟排序结果如下"<<endl;
for(int i=0;i<len;i++){
cout<<num[i]<<" ";
}
cout<<endl;
}
}
int main(int argc, char *argv[]) {
int len;//输入需要排序的数组的长度
cin>>len;
int num[len];
for(int i=0;i<len;i++){//输入排序数组
cin>>num[i];
}
HeapSort(num,len);//堆排序
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: