排序算法——堆排序

堆排序

1.基础概念
  • 二叉树的概念:
    二叉树(binary tree)是指树中节点的 度 不大于2的有序树. 在二叉树中除了根节点的每一个节点都仅有一个父节点,所有的节点最多只能有两个
    孩子节点。

  • 满二叉树的概念:
    除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树。
    国内教材定义:
    一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是(2^k) -1 ,则它就是满二叉树。
    国外(国际)定义:
    a binary tree T is full if each node is either a leaf or possesses exactly two childnodes.
    在这里插入图片描述

  • 完全二叉树:
    对满二叉树的结点进行编号, 约定编号从根结点起, 自上而下, 自左而右。则深度为k的, 有n个结点的二叉树, 当且仅当其每一个结点都与深度为k的满二叉树中编号从1至n的结点一一对应时 。
    在这里插入图片描述

  • 堆的概念:
    堆通常是一个可以被看做一棵完全二叉树。

  1. 大根堆, 就是说这个完全二叉树中每一棵子树的根节点都大于他的左右孩子(如果有的话)
  2. 小根堆,就是说这个完全二叉树中每一棵子树的根节点都小于他的左右孩子(如果有的话)
  • 二叉树的存储方式
  1. 顺序存储
    (1) 按照完全二叉树(无论是那种二叉树)的形式,将二叉树的数据全部存储在数组中.
    (2) 顺序表中的每个元素除了存储data,leftchild , rightchild
  2. 链式存储 每个节点都有至少三个域(data,* leftchild,* rightchild)
  • 堆仅仅将数据存储在数组中
  1. 如果父节点的下标为i,则左孩子的下标为 2 * i + 1,右孩子的下标为 2 * i + 2
  2. 如果孩子的下标为j, 则父节点的下标是: ( j - 1 ) / 2
    在这里插入图片描述
2.堆的建立过程
  • 将数组中的数据调整成堆时,从最后一棵子树开始,向根节点一颗颗调整
    每棵子树的调整都是从其根节点开始向下调整的
  • 一棵子树的调整过程:
    先用i指向子树的根节点,j为根节点的左孩子。将i位置的值保存到tmp中, 然后在左右孩子中找到较大的哪一个,j指向较大值,(1)如果较大的哪一个比临时变量中的值小,则直接退出;(2)如果较大的哪一个比临时变量中的值大,则将较大的值保存到i位置上,然后i=j,j=2*i+1,直到j越界则退出。退出以后,还需要将tmp的值保存到退出时的i位置上。

代码实现

void OneAdjust(int *arr, int len, int root)
{
	int tmp = arr[root];
	int i = root;
	int j = 2 * i + 1;
	while (j < len)
	{
		// j+1 < len 成立 则有右孩子
		// arr[j] < arr[j+1] 左孩子的值小于右孩子
		if (j + 1 < len && arr[j] < arr[j + 1]) j++;
		
		if (arr[j] < tmp) break;
		
		arr[i] = arr[j];
		i = j;
		j = 2 * i + 1;
	}
	
	arr[i] = tmp;
}
  • 将数组调整成堆的过程
    先找到最后一棵子树的根节点,向根节点递减,循环调用上面的调整方法。

代码实现

void CreateHeap(int *arr, int len)
{
	int lastRoot = (len - 2) / 2; // lastRoot就是最后一棵子树的根节点下标
	
	for (int i = lastRoot; i >= 0; --i) // 从lastRoot开始,循环到整颗数的根节点,调整
	{
		OneAdjust(arr, len, i);
	}
}
3.堆排序
  • 先将数组中的数据调整成一棵最大堆, 然后将根节点的数据和最后位置的节点交换, 接着除过最后一个位置的数据外,在将剩余的数据调整成
    最大堆。
  • 重复上述过程,直到只剩下一个数据没有交换。就完成了堆排序。
// 时间复杂度: O(nlog(n))
// 空间复杂度: O(1)
// 稳定性: 不稳定
void HeapSort(int *arr, int len)
{
	CreateHeap(arr, len);
	
	for (int i = 0; i < len - 1; ++i)
	{
		Swap(&arr[0], &arr[len - 1 - i]);
		OneAdjust(arr, len - i - 1, 0);
	}
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值