大小堆之堆排序

本文详细介绍了堆排序算法,包括堆的概念、二叉树的基础知识、大根堆与小根堆的构造及调整过程,并提供了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前已经说过了好些排序了,今天就说一下最后一个排序,那就是堆排序,但是我们这个堆和内存中的堆还不是一个堆,我们现在所说的大小堆其实是一个树。接下来详细的说一说

先要说堆,那我们还是先说说一些最基础关于树的一些概念,就先说说二叉树好了,因为我们今天用到的就是二叉树,首先二叉树也是一种数据结构,它有父节点和子节点,在二叉树中有2个叶子节点,父节点和第一个子节点的关系一般是2倍的关系;然而堆排序就是用到这一点

接下来说一下大根堆,数组中元素先排成一个二叉树,然后我们要求把越大的数放得越高,那么最大的数就放在根节点,那么调整阶段就完成了,然后我们把根节点和最后的尾节点交换,然后调整除了最后一个数之外的其他数,因为刚才交换一遍肯定大小顺序会发生改变。

掏出代码:

void  Adjust(int *arr, int start, int end)
{
int tmp = arr[start];//保存根的值
int i;
for (i = 2 * start + 1; i <= end; i = 2 * i + 1)
{
if ((i<end) && arr[i]<arr[i + 1])//保证有右孩子,并且右边比左边大,i++;
{
i++;//保证找到最大值
}
if (arr[i]>tmp)//儿子大于父亲,就得赶紧换
{
arr[start] = arr[i];
start = i;
}
if (arr[i] < tmp)//儿子小于父亲,没事
{
break;
}
}
arr[start] = tmp;//循坏退出后,将值放入start
}


void HeapSort(int *arr, int len)
{
int tmp;
int i;
//建立大根堆,一次调整之后,上面的都是最大值,最后排好序后,是按小到大的顺序
for (i = (len - 1 -1) / 2; i >= 0; i--)//各个分支调整,开始是最后一个非叶子节点【(len-1-1)/2  子推父】。
{
Adjust(arr, i, len - 1);//结尾是len-1,原因是,比len-1大,访问不到那个大的值
}
//交换
for (i = 0; i<len - 1; i++)//调整一次交换一次,总共调整len-1次,调整完之后,根和最后一个进行交换
{
tmp = arr[0];
arr[0] = arr[len - 1 - i];//len-1-i的值是当前待排序的最后一个值
arr[len - 1 - i] = tmp;


Adjust(arr, 0, len - 1 - i - 1);
}
}

大根堆都会了,小根堆也就出来了,就是把小的数放在最上面,其他的都和大根堆是一样的,那我在这就直接演示代码了:

void MinAdjust(int a[], int i, int n)
{
int j, temp;
temp = a[i];
j = 2 * i + 1;
while (j < n)
{
if (j + 1 < n && a[j + 1] < a[j]) //在左右孩子中找最小的
j++;
if (a[j] >= temp)
break;
a[i] = a[j]; //把较小的子结点往上移动,替换它的父结点
i = j;
j = 2 * i + 1;
}
a[i] = temp;
}


void HeapSort(int *arr, int len)
{
int tmp;
int i;
//建立大根堆,一次调整之后,上面的都是最大值,最后排好序后,是按小到大的顺序
for (i = (len - 1 -1) / 2; i >= 0; i--)//各个分支调整,开始是最后一个非叶子节点【(len-1-1)/2  子推父】。
{
Adjust(arr, i, len - 1);//结尾是len-1,原因是,比len-1大,访问不到那个大的值
}
//交换
for (i = 0; i<len - 1; i++)//调整一次交换一次,总共调整len-1次,调整完之后,根和最后一个进行交换
{
tmp = arr[0];
arr[0] = arr[len - 1 - i];//len-1-i的值是当前待排序的最后一个值
arr[len - 1 - i] = tmp;


Adjust(arr, 0, len - 1 - i - 1);
}
}

最后再说两句,就是关于她的时间复杂度O(nlog2(n)),并且这还是一个不稳定排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值