堆排序
-
核心思想:
- 前提知识:
堆其实就是一种特殊的完全二叉树,分为大顶堆和小顶堆,大顶堆就是指父节点>=左右孩子结点,而左右孩子结点之间的大小关系随意,小顶堆反之 - 堆排序核心:就是先把序列构建成大顶堆序(
升序用大顶堆),然后大顶堆的根节点和最后一个结点交换位置,这样一来每交换一次就得到当前序列的最大值,并把它放在了最后面,接着把剩下的序列继续构建成大顶堆,重复上面动作,直到序列只剩一个 -
复杂度分析:
- 最好情况:
O(nlogn) - 最差情况:
O(nlogn) - 平均:
O(nlogn) - 辅助空间:
O(1)
- 最好情况:
-
稳定性:
不稳定
- 前提知识:
图解
- 注:大顶堆,小顶堆的左右孩子的大小随意

对应的在数组中的位置如下

- 第一步,给定无序序列如下

-
第二步,从最后一个非叶节点开始,从左至右,从上至下调整二叉树,形成大顶堆
(注:第一个非叶节点为length/2-1,这里为arr[1]=6)从arr[1]处开始构建堆

接着处理arr[0]

由于交换完后,arr[1]处又乱了,继续处理arr[1]

至此,大顶堆构建完成
- 第三步,得到大顶堆后,
让大顶堆首元素和末尾元素交换,如此让最大元素处于最末位置,由于交换会导致新二叉树不满足大顶堆性质,于是要进行调整,让它重新变成大顶堆,接着又是首元素和末尾元素交换,得到第二大的元素,并排放在倒数第二的位置,如此反复执行交换,调整,交换...
交换1

调整1

交换2

后续如下

代码如下
#include <iostream>
void swap(int *&arr,int i,int j){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
void buildHeap(int *&arr,int i,int n){//以arr[i]为根建立堆(升序大顶堆)
int temp=arr[i];
for(int k=2*i+1;k<n;k=2*k+1){
if(k+1<n&&arr[k]<arr[k+1]) {
k++;
}
if(temp<arr[k]){
arr[i]=arr[k];
i=k;
}else{
break;
}
}
arr[i]=temp;
}
void heapSort(int arr[],int n){
int i,j;
for(i=n/2-1;i>=0;i--){//建好了堆
buildHeap(arr,i,n);
}
for(j=n-1;j>=0;j--){
swap(arr,j,0);
buildHeap(arr,0,j);
}
}
int main(int argc, char** argv) {
int arr[]={4,12,35,98,4,44,58,13,15};
heapSort(arr,9);
for(int i=0;i<9;i++){
printf("%d ",arr[i]);
}
return 0;
}
注:本文所用图均来自dreamcatcher-cx大神的博客
转载自:https://blog.youkuaiyun.com/qq_37597859/article/details/80588110
31万+

被折叠的 条评论
为什么被折叠?



