堆排序算法解析

首先来引入一个例子:如何使用选择排序?

肯定是每一次遍历然后把大的放到最后面。(当然,前面也可以)

我感觉堆排序其实和选择差不多。

堆排序也是每次取出最大值,然后把最大值放后面

 

但是想学会堆排序,首先要知道什么是堆

#堆的定义

逻辑上:一个完全二叉树

物理上:借助向量实现

为什么能用一个向量来间接的弄一个完全二叉树呢?

(你自己试试把这个完全二叉树按层次遍历,是不是就是这个向量了)

如图,因为完全二叉树中间没有空缺,都是连续的,所以可以把完全二叉树存到数组中,这样就形为数组,神为完全二叉树。

#堆序性

就是说所有父亲的值大于孩子的值(等等你就知道为啥了,先记着:-D)

 

介绍一下下滤算法:

应该如何删除最上面的父亲?

对二叉树熟悉的你一定知道,如果要删除上面的,是先把最上面的和它右子树的最左边的那个叶子换位置,然后删除。

但是这样是不行的,首先:这个不是一个那样的树,不是都是顺序的。其次:这样做会破坏向量的有序性,导致后面都出错

应该把最后面的和最上面的交换,然后把新来的最上面的通过下滤操作重新变为堆就行了。

(j是你要让第几个下滤,n是总数(包括0))

void percolatedown(int *a,int j,int n)
{
	if(n == 0)
	return;
	while(j <= (n - 1) / 2)
	{
		if((j + 1) * 2 > n)
		{
			if(a[j] < a[j * 2 + 1])
			{
				int t = a[j];
				a[j] = a[j * 2 + 1];
				a[j * 2 + 1] = t;
			}
			return;
		}
		int maxs = max(a,j * 2 + 1);
		if(a[maxs] > a[j])
		{
			int t = a[j];
			a[j] = a[maxs];
			a[maxs] = t;
			j = maxs;
		}
		else
		{
			return;
		}
	}
}

(因为神为二叉树,所以时间为O(logn))

如何让父亲的值大于孩子的值呢?

利用下滤操作,自上到下的都有序就行了

(代码中的i是总数,算0的,这样写方便)

void heapify(int *a,int i)
{
		int j = 0;
		for(j = (i - 1) / 2;j >= 0;j--)
		{
			percolatedown(a,j,i);
		}
}

那么最重要的来了,如何进行堆排序呢?

每次把最大的值假装删除(实际是把最大的值移动到最后面),然后让总数-1就行了。

void sorts(int *a,int i)
{
	int j = i;
	int t = 0;
	while(j > 0)
	{
		int m = a[0];
		a[0] = a[j];
		a[j] = m;
		j--;
		percolatedown(a,0,j);

	}
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值