堆排序(Heap Sort)

堆的向下调整(sift函数)

void sift(int li[], int low, int high)
{
	/*
	* sift:堆的向下调整函数
	* li:列表
	* low:堆的根节点(堆顶)
	* high:堆的最后一个元素
	*/

	int i = low;//	i最开始指向的是根节点,i也是一层的父节点
	int j = 2 * i + 1;//	j开始是指向左孩子,注意左右孩子节点与父节点的关系
	int tmp = li[low];//	把堆顶元素存起来

	while (j <= high)//	只要j位置有数
	{
		if (j + 1 <= high && li[j + 1] > li[j])//	如果右孩子存在并且比左孩子大
		{
			j = j + 1;//	j指向右孩子
		}
		if (li[j] > tmp)
		{
			li[i] = li[j];
			i = j;//	往下看一层
			j = 2 * i + 1;
		}
		else//	tmp更大,把tmp放到i的位置(父节点)
		{
			li[i] = tmp;//	把tmp放到某一级领导位置上——while循环结束后也会执行这一条,可以省略掉,但不方便理解
			break;
		}
	}
	li[i] = tmp;//	存在一种情况,一直找到最后一个元素,把tmp放在叶子节点
}

堆排序过程

  • 1.建立堆。

  • 2.得到堆顶元素,为最大元素。

  • 3.去掉堆顶,将堆最后一个元素放到堆顶,此时可通过一次调整重新使堆有序。

  • 4.堆顶元素为第二大元素。

  • 5.重复步骤3,直到堆变空。​​​​​​​​​​​​​​


  • 时间复杂度:

    • sift函数:O(logn)
    • heap_sort函数:O(nlogn)
  • #include<stdio.h>
    
    void Print(int li[], int n)
    {
    	int i = 0;
    	for (i = 0; i < n; i++)
    	{
    		printf("%d ", li[i]);
    	}
    	printf("\n");
    }
    
    void sift(int li[], int low, int high)
    {
    	/*
    	* sift:堆的向下调整函数
    	* li:列表
    	* low:堆的根节点(堆顶)
    	* high:堆的最后一个元素,high的作用就是判断访问有没有越过边界
    	*/
    
    	int i = low;//	i最开始指向的是根节点,i也是一层的父节点
    	int j = 2 * i + 1;//	j开始是指向左孩子,注意左右孩子节点与父节点的关系
    	int tmp = li[low];//	把堆顶元素存起来
    
    	while (j <= high)//	只要j位置有数
    	{
    		if (j + 1 <= high && li[j + 1] > li[j])//	如果右孩子存在并且比左孩子大
    		{
    			j = j + 1;//	j指向右孩子
    		}
    		if (li[j] > tmp)
    		{
    			li[i] = li[j];
    			i = j;//	往下看一层
    			j = 2 * i + 1;
    		}
    		else//	tmp更大,把tmp放到i的位置(父节点)
    		{
    			li[i] = tmp;//	把tmp放到某一级领导位置上——while循环结束后也会执行这一条,可以省略掉,但不方便理解
    			break;
    		}
    	}
    	li[i] = tmp;//	存在一种情况,一直找到最后一个元素,把tmp放在叶子节点
    }
    
    void heap_sort(int li[], int n)
    {
    	/*
    	*n:列表长度,n-1可得到最后一个元素的访问下标
    	* 
    	*/
    	int i = 0;
    	//建堆
    	for (i = (n - 2) / 2; i >= 0; i--)//	(n-2)/2通过孩子节点找父节点
    	{
    		//i	代表建堆的时候调整的部分(子堆)的根的下标
    		sift(li, i, n - 1);//	传递给high的是n-1,high的作用只是判断访问不能越界即可
    	}
    	//建堆完成
    	Print(li, n);//验证
    	for (i = n - 1; i >= 0; i--)
    	{
    		//i	指向当前堆的最后一个元素
    		int tmp = li[0];
    		li[0] = li[i];
    		li[i] = tmp;
    		sift(li, 0, i - 1);//	i-1是新的high
    	}
    	Print(li, n);//验证
    }
    
    
    int main()
    {
    	int li[] = { 5,8,2,3,7,9,6,1,4,0 };
    	int n = sizeof(li) / sizeof(li[0]);
    
    	Print(li, n);//验证
    	heap_sort(li, n);
    	
    
    	return 0;
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

如何写出最优雅的代码

感谢支持,我将继续努力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值