排序算法|数据结构|堆排序

堆排序(大根堆)

初始化过程

按照数组下标的规律,先建立一个初始堆。

这个初始堆只需要将整个堆中所有元素的最大值放在堆顶
(这就是Adjust函数要做的,就是把所有元素中最大的那一个放在堆顶);

遍历的主过程

之后依次,从堆的最后一个元素开始,与堆顶元素交换。之后对剩余的元素再次进行Adjust。

这样的效果是,每次Adjust之后,堆的最后一个元素都是所有数据中最大的。

(注意Adjust中传入的总元素个数每次都减一,保证堆的最后一个元素每次都往前移动一位。)
这样的操作从后往前除了第一个结点都要做一遍。

void Adjust(int arr[],int parent,int length)
//arr[]是存放数据的数组
//parent是堆顶元素的下标(堆顶元素就是堆中最大的元素)
//length是要操作的堆的元素个数
{
	int tmp=arr[parent];
	//记录最大元素的值
	int child=parent*2;
	//child:根据二叉树的规律,下标为i的节点的左孩子下标为i*2
	while(child<=length){
	///因为要找到所有元素中最大的那一个,所以要遍历所有的节点
		if(child+1<=length&&arr[child]<arr[child+1]){
			child++;
			//如果这个节点的还有右结点,并且这个右结点比左结点还要大。那么就对右结点进行操作
		}
		if(tmp>arr[child])break;
		//如果父节点已经大于最大的孩子节点了,就说明现在的child对应的parent可以存放tmp
		//这一点卡了很久。要注意这里循环的目的是一直把最大的child放在他的parent中,child变成下一次循环的parent,每次循环的时候其实只有parent在变化
		//比方说,如果tmp一开始就是所有数据中的最大的,那么parent不会被改变,arr[parent]还是原来的值
		else{
		//如果孩子节点的确要比之前的最大值大,说明这个堆顶元素不应该放在这里
		//这里卡了很久。初始化的时候是从整个堆的非叶子节点的最后一个自底向上遍历的,所以每一步都可以保证如果child比堆顶元素大,这个child已经是剩下所有中最大的了,就可以放在堆顶!
			arr[parent]=arr[child];
			//当前的孩子节点比堆顶的元素还要大,那么孩子节点才应该是堆顶的。此时把child的值给parent,此时tmp就是之前的堆顶还不知道放在哪,现在要找能让之前堆顶大的两个孩子节点,把他放到这两个孩子节点的parent中(这个parent是上一轮换过的child,这个child已经在上一轮赋值给了他的parent,所以其中的数据已经没有意义了,可以被覆盖)
			parent=child;
			child=parenr*2
		};
	}
	arr[parent]=tmp;
	//找到了parent,这个parent的特征是两个孩子节点都要比之前的堆顶元素要小,即找到了之前堆顶元素正确的位置
}
void HeapSort(int arr[],int n)//注意这个数组的有效下标的首位是1
{
	for(int i=n/2;i>0;i--)
	{   //初始化一个大根堆,符合完全二叉树的定义,所有的父节点都比他的子节点大
		Adjust(arr,i,n);
	{
	for(int i=n;i>1;i--)
	{
	//从n开始一直到1,arr逐渐变成从小到大的顺序
		int tmp=arr[i];
		arr[i]=arr[1];
		arr[i]=tmp;
		//交换最后一个数字和堆顶的顺序,这样树的倒序就是从大到小了
		Adjust(arr,1,i-1);	
	}
}

真的太难理解了 淦

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Annaisavailable

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值