堆排序(Heap Sort)
- 堆排序是一种树形选择排序,在排序过程中将待排记录r[1…n]看成是一颗完全二叉树的顺序结构存储,利用完全二叉树中双亲结点和孩子结点之间的关系,在当前无序的序列中选择关键字最大或者最小的记录。是不稳定排序。
- 堆排序是使用的完全二叉树中大根堆(小根堆)的堆顶记录最大(最小)的性质进行排序的。
- 算法步骤:
- 1.按定义将待排记录r[0…n]调整为大根堆,交换r[0]与r[n],则r[n]为关键字最大的记录。
- 2.将r[0…n-1]从新调整为大根堆,交换记录r[0]与r[n-1],则r[n-1]为关键字次大的记录。
- 3.循环n-1次,直到交换了r[0]和r[1]为止。
- 示例过程:
初始序列[49,38,65,97,76,13,27,49]
第一次调整序列[49,97,65,49,76,13,27,38]
第二次调整序列[97,76,65,49,49,13,27,38],成功找出最大值97
首尾交换,将最大值交换到末尾
一趟排序结果[38,76,65,49,49,13,27,97]
开始第二趟筛选[38,76,65,49,49,13,27,97]
成功找出最大值76:[76,49,65,38,49,13,27,97]
进行首尾交换[27,49,65,38,49,13,76,97],第二趟排序完成
继续进行建堆交换操作……
- 代码实现:
#include<iostream>
using namespace std;
void adjust_heap(int *array, int s, int m){
int j, key=array[s]; //取处结点s处的值
for(j=2*s+1; j<=m; j*=2){
if(j<m&&array[j]<array[j+1]) //找出值大的孩子结点
j++;
if(key>array[j]) //s为值较大的结点,退出循环
break;
array[s]=array[j]; //否则将值较大的结点调整到s
s=j; //继续对子节点j进行调整
}
array[s]=key; //将原来结点值插入
}
void creat_heap(int *array, int n){
int i;
for(i=n/2; i>=0; i--) //i=n/2是从末尾结点的双亲结点开始调整
adjust_heap(array, i, n);
}
int main(){
int data[]={49,38,65,97,76,13,27,49};
int i=0;
creat_heap(data, 7);
for(i=7; i>0; i--){
int temp;
temp=data[0];
data[0]=data[i];
data[i]=temp;
adjust_heap(data, 0, i-1);
}
for(i=0; i<8; i++){
cout<<data[i]<<" ";
}
return 0;
}
Output:13 27 38 49 49 65 76 97
- 时间复杂度:
推导过程移步 堆排序时间复杂度 - 空间复杂度:
仅需要一个供交换的辅助存储空间,故空间复杂度为O(1)