二叉树--堆排序

我们之前学过冒泡排序算法,还有其他的排序算法之类的,我们今天来讲堆排序算法;

假设我们现在有一个数组,我们想要对其进行排序,我们可以使用冒泡排序来进行排序;我们也可以使用堆排序来进行排序;

我们之前说过堆的数据结构;当我们拥有堆的数据结构的时候,我们可以使用我们的数组,在我们的堆在进行初始化的时候,我们可以把我们的数组里面的数据传进去,把数据导入到我们的堆里面,然后使用我们的堆的数据结构,我们不断的取堆顶的数据,然后向下排序,把堆顶的数据放到最后面,然后向下排序,这样不断地进行,直到我们的堆变成顺序的了;然后我们把它打印出来。

但是这样的话,我们其实没有改变数组,我们的数组还是原来的数据;我们就可以不断地取堆顶,然后把堆顶的数据销毁,然后,因为我们的出堆函数里面是含有把堆二叉树重新的向下调整的,所以,下次他就还是一个新的完好的堆二叉树;我们可以把输出的数据保存下来,保存到数组里面去

我们只是把数组里面的数据导入到我们的堆里面,然后使用堆的数据结构来进行操作,因为我们把数据插入到我们的堆二叉树里面的时候,我们的堆里面他就含有着向上调整的方法;所以我们把数据插入完后他就是一个堆二叉树;但是其实,当我们想要完成堆排序的时候,我们其实是不需要这个堆的数据结构的,这样未免太麻烦了;

这时候我们就开始我们的真正的堆排序;

我们所说的堆排序其实是使用堆的思想,并不调用堆的结构;堆的底层就是数组,我们把我们要改变的数组拿过来在使用向下调整的方式把他改变为堆的形式;然后把

1.构建堆。

我们从非叶子节点的最后一个结点开始,我们对其进行向下调整,一直到根节点,这样最后就成功地构建了一个堆结构; 至于是大根堆还是小根堆的话,我们就看向下调整里面的了

2.排序。

构建好堆以后我们把堆的第一个元素和最后一个元素进行交换;,然后我们把堆的有效的数据-1;然后,就和出堆一样,我们进行向下调整;我们不断的重复这个操作,直到最后,我们的最里面的有效数据只有一个了;

我们来实现一下堆排序:

//在我们开始堆排序的学习之前,我们要先说明:

//那就是我们的堆排序其实是不能使用堆的数据结构的,我们使用的是堆的思想;

//我们选择不调用堆的结构;

//堆的底层就是数组,我们就把传过来的数组,变成堆得形式;

void swap(int* x, int* y)

{

int tmp = *x;

*x = *y;

*y = tmp;

}

//向上调整(入堆)

void Adjustup(int* arr, int child)

{

//我们要进行向上调整,我们可以根据孩子把父亲求出来

int parent = (child - 1) / 2;

//向上调整既可以是大堆,也可以是小堆;

while (child > 0)

{

//如果要求是小堆的时候,我们看谁小,我们就把谁往上放,

//所以小堆:<

//如果孩子比父亲小我们就交换

//大堆:>

//如果孩子比父亲大我们就交换

if (arrchild < arrparent)

{

swap(&arrchild, &arrparent);

}

else

{

break;

}

child = parent;

parent = (child - 1) / 2;

}

}

//向下调整法(出堆)

void AdjustDown(int* arr, int parent, int n)

{

int child = 2 * parent + 1;//左孩子;

while (child < n)

{

//大堆:<

//大堆的话我们找到大孩子

//小堆:>

//小堆我们就找小孩子

if (child + 1 < n && arrchild < arrchild + 1)

{

child++;

}

//大堆 >

//我们找到大的放上去

//小堆 <

//我们找到小的放上去

if (arrchild > arrparent)

{

swap(&arrchild, &arrparent);

parent = child;

child = 2 * parent + 1;

}

else

{

break;

}

}

}

//我们的向上和向下调整法的参数都不是我们的堆,这样就很好,所以我们就不需要建堆;可以拿来直接使用

void HeapSort(int* arr, int n)

{

for (int i = (n - 2) / 2; i >= 0; i--)

{

//从这个第一个子树的根节点开始,我们从右往左的依次进行;对其进行向下调整

AdjustDown(arr, i, n);//n就是表示有效的的数据个数;

}

//这样建堆就完成了

//堆排序---现在的堆还是乱序的,我们来对其进行排列;

int end = n - 1;

//我们让end为最后一个结点的下标;

while (end > 0)

{

swap(&arr0, &arrend);

//让开始和最后的进行了交换,然后我们进行向下调整;这就和出堆一样,

//我们把堆顶的数据和最后一个结点的数据进行交换,然后再进行向下调整;//这时候除了堆顶的数据是乱的,其他的都是

//正常的堆,所以这时候我们就可以进行向下调整;

AdjustDown(arr, 0, end);

//这里我们的父节点一直都是0,这个可以不用改变,最后的参数end表示的是有效的数据的个数;

//我们开始直接吧end传过去,这就是较少了一个有效的数据的个数;

end--;

}

}

#include<stdio.h>

int main()

{

//我们的方法是,找寻最后一个子树的根节点;这就是我们的初始的值

//我们就是先把一边的子树进行向下调整,然后对另一边的子树也进行向下的调整

//然后我们对整体的根节点进行向下调整;这就可以求出来;

int arr\[\] = {12,24,434,54,65,76,76,34};

int a = sizeof(arr) / sizeof(int);

HeapSort(arr, a);

for (int i = 0; i < a; i++)

{

printf("%d ", arri);

}

return 0;

}

相关推荐
怕浪猫4 小时前
GEO 优化到底是什么?AI时代内容创作者必须懂的新技能
算法·面试·github
朝朝辞暮i5 小时前
C++ 第 23 课:class —— 开始真正进入面向对象
开发语言·c++·算法
7yewh5 小时前
SLAM 三维空间刚体运动(2)
数据结构·人工智能·机器人·嵌入式·slam
Evand J5 小时前
【MATLAB例程】三维RRT+APF避障路径规划与到达角(AOA)定位算法|三维路径优化与定位仿真例程
算法·matlab·路径规划·代码·定位·rrt·aoa
leikooo6 小时前
用餐厅和盘子理解栈和堆
java·数据结构·链表·rust
weixin_307779137 小时前
有限产能智能排产与动态重排智能体:从需求解构到技术实现
开发语言·人工智能·算法·架构
朝朝辞暮i7 小时前
C++ 第 27 课:智能指针 shared_ptr
开发语言·c++·算法
朝朝辞暮i7 小时前
C++ 第 29 课:回调函数 Callback
开发语言·c++·算法
Godspeed Zhao8 小时前
现代智能雷达技术14——算法(0)
线性代数·算法·雷达
可乐ea8 小时前
Agent 模型分级升级路由:用置信度阈值把贵模型省下来
人工智能·算法·机器学习·结构化输出·置信度路由·模型升级路由·大模型成本优化