8.堆排序
在介绍堆排序之前先介绍一下什么叫做堆?
学过数据结构的同学应该知道什么叫做树!
堆就是一颗特殊的树,总是一颗完全二叉树!
堆中某个节点的值总是不大于或不小于其父节点的值;
小顶堆:根结点最小的堆。
大顶堆:根结点最大的堆。
堆的操作:
最大堆调整:将堆的末端子节点作调整,使得子节点永远小于父节点
创建大顶堆:将堆中的所有数据重新排序
上述介绍了一下堆的基础知识,接下来聊聊堆和堆排序之间的关联!
堆排序:移除位在第一个数据的根节点,并做大顶堆调整的递归运算;
一句话概括是不是有点草率!先上代码:
void minheeps(int a[max],int n);
void minheep(int a[max],int i,int n);
void minheepssort(int a[max],int n){//n属于需要堆化的范围,进行堆排序
minheeps(a,n);
int i;
for(i=max-1;i>=0;i--){
swap(a,0,i);//把根结点值取出来放到序列最后面
minheeps(a,i);//堆化范围减小
}
}
void minheeps(int a[max],int n){//整体大顶堆堆化
int i;
for(i=n/2-1;i>=0;i--){//把结点放到最后一个根结点上面
minheep(a,i,n);//局部大顶堆调整
}
}
void minheep(int a[max],int i,int n){//大顶堆调整
int left;
int right;
int min;
left=2*i+1;//左孩子
right=2*i+2;//右孩子
min=left;//最大孩子
if(left>=n){//左孩子没有
return;
}else if(right>=n){//右孩子没有
min=left;//最大孩子就是左孩子
}else{
if(a[right]>a[left]){//右边比左左边大
min=right;//最大孩子就是右边
}
//否则最大孩子就是左孩子
}
if(a[i]>=a[min]){//父节点孩子大于最大孩子
return;//不用调整
}else{
swap(a,i,min);//把父节点和最大孩子交换
minheep(a,min,n);//再看被交换了的孩子作为父节点的时候是否是符合大顶堆,递归
}
}
具体过程在代码注释中,接下来简单的介绍一下具体过程。
把根结点的值和最后面叶子结点值交换,再把叶子砍掉,剩下部分进行大顶堆堆化,再把根结点的值和最后面叶子结点的值交换,不断执行上述的操作。最终序列有序。
需要注意的地方:当每次把父节点和最大孩子交换之后,那个孩子结点作为父节点的时候相对于左右孩子来说可能不是最大的,所以我们需要把它变成最大的接下来的操作又是(最大堆调整)的操作(递归).
当上述一切结束后,最终序列就是有序的啦!