排序之堆排序

这次我来介绍排序算法中的堆排序。

说到堆排序我就想多说几句,在我认为堆排序在所有排序算法中是比较复杂·的一种排序算法,所以我推荐一般情况下不要用这种排序算法。

废话不多说,下面我就来说一下堆排序。

堆排序是一种树形选择排序,在排序过程中,将待排序的记录看成 一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲节点和孩子节点之间的内在关系,在当前无序的序列中选择关键字最大(或最小)的记录。

提到堆了,我再来介绍一下什么是堆。

二叉树中双亲节点永远大于孩子节点(或双亲节点永远小于孩子节点)就被成为堆。

堆排序的步骤大致是先把待排序序列构建成二叉树,然后再把该二叉树经过排序变成堆,然后再把堆顶的元素与堆的最后位置的元素进行交换,重复上述过程直至最后一个元素。

 

下面我就以序列(49,38,65,97,76,13,27,49)为例来详细介绍一下堆排序

588066ea34194b96830697b0c78a960f.jpeg

888c914816f04cdfaca4e262c5090f5e.jpeg 

实现堆排序需要解决两个问题堆排序算法才能算完成,问题如下

1、建初堆:将一个无序序列建成一个有序序列

2、调整堆:将堆顶元素与堆底元素进行交换,在堆顶元素改变后,调整剩余元素成为一个新的堆。 

对以上两个问题的代码如下

//建初堆
void CreatHeap(int *str){//把无序列建成大根堆 
	int n;//记录待排序序列的长度
	n=sizeof(str)/4; //纪录序列的长度 
	for(int i=n/2-1;i>=0;i--){ //把子树变成大根堆 
		HeapAdjust(str,i,n-1);
	}
} 
//调整堆
void HeapAdjust(int *str,int t,int n){ //把二叉树变成大根堆 
	int fa,son,x;//fa表示双亲节点,son表示儿子节点
	fa=t;
	son=2*fa+1;
	while(son<=n){ //把子树的值进行位置调换变成大根堆 
		if(son+1<=n&&str[son]<str[son+1])
		son++;
		if(str[fa]<str[son]){
			x=str[fa];
			str[fa]=str[son];
			str[son]=x;
		}
		else
		break;
		fa=son; //进行下一个子树变成大根堆的过程 
		son=2*fa+1;
	} 
}
void HeapSort(int *str){ //对序列进行排队 
	int n,x;
	n=sizeof(str)/4;
	for(int i=n-1;i>=0;i--){ //交换堆顶与堆底的值进行排序 
		x=str[0];
		str[0]=str[i];
		str[i]=x;
		HeapAdjust(str,0,i)
	}
}

堆排序算法的特点

1、不稳定排序

2、只能用于顺序结构,不能用于链式结构

3、初始建堆所需的比较次数较多,因此记录数较少时不宜采用。堆排序在最坏情况下时间复杂度为O(nlog2n),相对于快速排序最坏情况下的O(n^2)而言更有优势,当记录较多时较为高效。

堆排序虽然比较复杂,但是多看看和练习一下就没什么问题了,希望大家多多指教。

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值