基本排序方法之六——堆排序

堆排序(heap sort)是J.Willionms在1964年提出的一种选择类排序方法,是在简单选择排序方法的基础上借助与完全二叉树的结构而形成的一种排序方法,是完全二叉树顺序存储结构的应用。

堆排序的基本思想:根据原始记录的关键字序列建立初始堆,使得堆顶元素是关键字最大(最小)的记录,然后删除堆顶元素并将其保存到数组中。继续调整剩余的关键字序列使之重新构成一个新堆,再删除关键字次大(次小)的记录并将其保存到数组中;如此反复,直到堆中只有一个记录为止。此时,数组中所有元素是一个按关键大小顺序进行排列的有序序列。

堆排序的C语言实现如下:

/*************************************************************
函数名称:static void sift(int a[], int k, int n)
参    数:int a[]---待排序的数据
		  int k-----待调整点的下标(待调整为堆的节点)
		  int n-----数组a中元素个数
功    能:对以a[k]为根节点的完全二叉树进行大根堆筛选算法,
		  完成一次筛选
返 回 值:无
说    明:static关键字指明了该函数只能在本文件中使用
**************************************************************/
static void sift(int a[], int k, int n)
{
	int temp, i, j;
	i = k;  // i表示调整点的位置,即父节点下标
	j = 2*i+1; // a[j]为父节点a[i]的左孩子
	temp = a[i]; // 保存父节点
	while(j<n)
	{
		if(j+1<n && a[j]<a[j+1])
			j++; // j为i的孩子节点中关键字较大的记录的下标
		if(temp<a[j])  // 如果孩子节点的关键字大于父结点
		{
			a[i] = a[j]; // 将a[j]调整到父结点位置
			i = j;  // 更新父结点下标
			j = 2*i+1; // 更新父结点的左孩子结点下标
		}
		else   // 如果孩子节点的关键字小于或等于父结点,则筛选结束
			break;
	}
	a[i] = temp;  // 被筛选节点的值放入正确的位置,完成建堆的一次筛选
}

/*************************************************************
函数名称:void HeapSort(int a[], int n)
参    数:int a[]---待排序的数据		  
		  int n-----数组a中元素个数
功    能:对待排序数据进行堆排序		  
返 回 值:无
说    明:无
**************************************************************/
void HeapSort(int a[], int n)
{
	int tp, i;
	// 根据初始关键字,建立初始堆
	for(i=n/2; i>=0; i--)
		sift(a, i, n);
	// 进行n-1趟筛选,调整,完成堆排序
	for(i=n-1; i>0; i--)
	{
		// 将堆顶元素a[0]与最后一个元素交换位置,将最大(最小)数据移动到最后
		tp = a[i];
		a[i] = a[0];
		a[0] = tp;
		// 将去掉堆顶元素后的序列,重新调整为一个新堆
		sift(a, 0, i);
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值