排序算法三之堆排序

   这次介绍堆排序,堆排序分为2步,1.建堆  2.排序 但是建堆的过程是对堆进行调整,而排序的过程实际上也是对堆调整,堆排序,是基于完全二叉树的,凡是和树和图相关的,总是需要多花点时间弄懂,哎,基础太差。

    所以关键是对堆的调整,下面的代码和图用的是大顶堆,代码是参考大话数据结构,理解了之后自己动手敲的。

   调整的过程如下图所示,但是为了显示一个过程,图7、图8最后的虚线是visio一页不足所致,红色为每次要调整的非叶子结点

排序算法三之堆排序_第1张图片

排序的过程就是,每次拆掉最后一个结点,然后重新调整堆,见下图

排序算法三之堆排序_第2张图片

另外需要注意的地方都在代码注释中

void heapAdjust(int a[],int n,int s){
	int tmp=a[s],i;
	for(i=2*s;i<=n;i*=2){          //1.i=2*s,是因为当前节点是s,那么左孩子一定是2*s      2.为什么是i*=2,也是完全二叉树的性质,每次都是往下比较孩子结点的值
		if(i=a[i])  break;         
		a[s]=a[i];              //调整比父节点大的值,赋值的过程如上图
		s=i;             
	}
	a[s]=tmp;         //最后调整原来的值应该所在的位置
}

void heapSort(int a[],int n){
	int i;
	for(i=n/2;i>=1;i--){           //建堆
		heapAdjust(a,n,i);
	}
	for(i=n;i>1;i--){              //排序
		swap(&a[1],&a[i]);
		heapAdjust(a,i-1,1); 
	}
} 
堆排序总结:

1.堆排序,下标是从1开始的,以前的六种排序可以从0开始也可以从1开始,因为按照完全二叉树的性质,如果1是父节点,那么2和3是他的子节点,如果从0开始的话,那么就是1和2是他的父节点,不满足2*i和2*i+1,反映在代码上就是heapAdjust函数中的for循环的第一个if语句中,i会变成0或者1,而不是预想的1和2,所以堆排序全部是从1到n,a[0]舍弃不用

2.建堆的过程中应该注意,如果有n个数,只需要<=n/2遍即可,因为<=n/2的节点都是非叶子结点,比如完全二叉树,当n=7,那么这个树的叶子结点是4,5,6,7,非叶子结点也就是1,2,3,把1,2,3的节点调整完毕,则整棵树也就满足大顶堆的定义:每个结点的值都大于等于其左右孩子叶子结点的值,反映在代码上就是heapSort函数中的第一个循环
初值是n/2,循环条件是i>=1

3.写代码过程中出错的地方,感觉堆排序过程中,一定要注意各个for循环和if判断中对于边界的判断,for循环还需注意初始值

   heapAdjust函数中的第一for循环中是i<=n,而第一个else循环中是i

    heapSort函数中的第二个for循环,最后一个数是a[n],故i=n,只剩一个数时无需调整,所以i>1,始终和第一个结点交换,然后堆调整的heapAdjust(a,i-1,1),第一个参数不解释,第三个参数因为每次都和第一个结点交换,所以每次都调整从1开始调整堆,第二个参数原来是i=n个,交换了一个,得到了一个最大值,然后下一次调整的时候边界就是i-1了。


总的代码如下:

#include 
#include 
#include 
#define MAXN 15

void display(int a[],int n){
	int i;
	for(i=1;i<=n;i++){
		printf("%d ",a[i]);
	}
	printf("\n");
}

void swap(int *s,int *t){
	int temp=*s;
	*s=*t;
	*t=temp;
}

void heapAdjust(int a[],int n,int s){
	int tmp=a[s],i;
	for(i=2*s;i<=n;i*=2){          
		if(i=a[i])  break;         
		a[s]=a[i];              
		s=i;             
	}
	a[s]=tmp;        
}

void heapSort(int a[],int n){
	int i;
	for(i=n/2;i>=1;i--){
		heapAdjust(a,n,i);
	}
	for(i=n;i>1;i--){
		swap(&a[1],&a[i]);
		heapAdjust(a,i-1,1); 
	}
} 
 
int main(int argc, char *argv[]) {
	unsigned int seed;
     seed = time(0);
     srand(seed);
	int i,a[MAXN];
	for(i=1;i

未完待续,还有排序算法的总结

如需参考排序算法总结排序算法四总结


如果文章有什么错误或者有什么建议,欢迎提出,大家共同交流,一起进步

文章转载请注明出处,请尊重知识产权

你可能感兴趣的:(数据结构,排序算法,算法,c语言,堆排序)