想要彻底掌握堆排序,你就一定要彻底理解堆排序的过程,原理并进行实践 ,因为我就已经看了很多遍了,还是每记住怎么搞的。
原理:(小顶堆为例子)
小二叉树:即最小二叉树(带两个结点或一个结点)
一颗二叉树父节点总比子节点小(子节点之间没有规定)即(小顶堆二叉树),这样从下看到上,最上面的结点是这棵树里最小的数。(很简单的道理,不懂得话可以试着画一画)
过程
假如现在有一颗这样的二叉树,整个排序的过程是这样的,最上面肯定是最小的,把它和最后一个数字交换位置,代表这个数已经找到了自己在整个数组中的位置,然后把这个数代表的结点给隔离开,剩下的二叉树就再次进行一个建立小顶堆二叉树的过程,找到次小的数字,这样循环往复就可以找到所有数字的位置。那这就涉及到两个大的方面:一是我要先建立一个这样的二叉树,二我要如何将一个交换数字之后的二叉树给恢复到小顶堆二叉树。
整个程序流程:
- 建立小顶堆二叉树
- 开始循环N-1次,将 N-1个数字放到其位置
2.1.将根节点和末尾结点交换;
2.2 .剩下子树重新建立小顶堆二叉树
3.循环结束 排序完成
如何建立小顶堆二叉树
我们先将整个数组无序建立一颗二叉树,然后从最后一棵小子树n=length/2结点树(length/2结点一定含有一个或者两个子结点)把最小的结点推出去,{靠,说不清了} 就这样从n=length/2结点到n=1结点,将n结点为父节点的简单二叉树都变成小顶堆二叉树。
如何恢复小顶堆二叉树
交换之后的二叉树就只有一个根节点不符合小顶堆,就是把这个根节点放到合适的位置上:
1.将n=1结点代表的小二叉树调换成小顶堆
2.这样做可能会破坏左节点或右节点代表的小二叉树,那就继续调整,直到调整到所有的小二叉树都是小顶堆
我去:::对不住各位,语言实在描述太抽象了,还是看代码吧!!少不了的
#include<stdio.h>
/*
调整函数,将begin位置到数组最后的树调整为小顶堆
begin+1到length已经是小顶堆
*/
void ad_heap(int a[],int length,int begin)
{
int b=a[begin-1];
int s =begin;
for(int j=begin*2;j<=length;j*=2)
{
if(j<length&&a[j-1]>a[j])//这一步是看看子节点是否是最后一个元素,若不是则肯定有兄弟结点,再从兄弟结点中找到最小那个,三者比较,先从兄弟中找到最小的
j++;
if(a[j-1]>=b)
break;
a[s-1]=a[j-1];
s=j;
}
a[s-1]=b;
}
int main()
{
int a[7]={49,38,65,97,76,13,27};
for(int i =0;i<7;i++)
printf("%d\n",a[i]);
int length = 7;
//这个是难点,length/2在二叉树中表示最后一个基本二叉树 ,
for(int i =length/2;i>0;i--)
{
ad_heap(a,length,i);//调用恢复函数来从底部建立一个完整的小顶堆二叉树
}
for(int j= 1;j<length;j++)
{
int value = a[0];
a[0]=a[length-j];
a[length-j]=value;
ad_heap(a,length-j,1);
}
for(int i =0;i<7;i++)
printf("%d ",a[i]);
}
我尽力了,兄弟们,最好还是自己写一写,不然你是掌握不了的。。。。。。