算法-排序-堆排序
作者:互联网
算法-排序-堆排序
首先引入堆的数据结构的概念
堆是一个特殊的完全二叉树
1、其根结点的值小于两个子结点的值,其余任何一个结点的值都小于其子结点的值——小顶堆。
2、其根结点的值大于两个子结点的值,其余任何一个结点的值都大于其子结点的值——大顶堆
这就是他的特殊点,它不仅是一个完全二叉树还得有附带属性
还有就是因为它是一个完全二叉树,所以根节点的子节点也特殊,假设根节点下标为i,那么子节点的下标就为
2i和2i+1,一个是左节点一个是右节点
堆排序的大概流程
基本思想:将待排序的序列构成一个大顶堆。此时,整个序列的最大值就是堆顶的根节点。将它移走(即将其与堆数组的末尾元素交换,此时末尾元素就是最大值),然后将剩余的n-1个序列重新构造一个堆,这样就会得到n个元素中的次小值。如此反复执行,便能得到一个有序序列了,但是有问题是就是如何构造一个堆,和如何在输出了堆顶元素后重新构造堆,按照的顺序是从下到上从右到左
//大概逻辑伪代码
void HeadSort()
{
int len = 9;
int test[10] = {0,xxxxxxxxx,xx~xxxx};
HeadpCreate;
for(int i=0;i<9;i++)
{
Export();
HeadpCreate();
}
}
由无序序列构成一个堆
通过处理根节点和叶子节点的大小来,所有的根节点都比左子和右子数都大,如果相反就交换,而根节点的个数为len/2,也就是对节点个数对2整除这是完全二叉树的性质,然后只需要处理这len/2的节点就好
也就是说从最后一个根节点依次往上,每个根节点都选择为该根节点和两个子节点的最大值,这样就是一个大顶堆弄好了,而且这里的根节点肯定是从1-len/2顺着下来的
输出堆顶元素后,调整剩下元素为一个新堆
把堆顶的元素和最后的一个元素进行交换,然后再把除开被交换到后面的元素再构成大顶堆
代码实现
#include<iostream>
#include<stdio.h>
using namespace std;
void Swap(int a[],int b,int c)
{
a[b] = a[b] + a[c];
a[c] = a[b] - a[c];
a[b] = a[b] - a[c];
}
void HeapAdjust(int a[],int i,int len)//对处于i位置的节点进行调整
{
int temp = a[i];//定义一个变量来存放根节点的值
int s = i;
int j;
for (j = i * 2; j <= len; j =j* 2)//利用j来访问要调整的节点的叶子结点,
{ //移动后也必须满足大顶堆的要求,不然就继续移动
if (j + 1 > len)
{
if (temp > a[j])
{
//这里说明temp比两个叶子节点都大
break;
}
else
{
a[s] = a[j];//如果比j小,那么就和j交换值,用s来记录最后的位置的节点就好了
s = j;
continue;
}
}
if (a[j] < a[j + 1])
{
j++;//如果右节点比左节点大,就右移一下
}
if (temp > a[j])
{
//这里说明temp比两个叶子节点都大
break;
}
else
{
a[s] = a[j];//如果比j小,那么就和j交换值,用s来记录最后的位置的节点就好了
s = j;
}
}
//如果前面都没变直接退出for循环了表示没有子节点了,就没有必要改变
a[s] = temp;
}
void HeapSort(int a[],int len)
{
int i;
for (i = len / 2; i > 0; i--)//排列根节点和叶子节点的大小,也就是构成了一个大顶堆
{
HeapAdjust(a,i,len);
}
for (i = len; i > 1; i--)//开始利用大顶堆排序
{
Swap(a, 1, i);//把堆的第一个根节点和最后一个叶子结点交换,相当于把最大的移到最后面
HeapAdjust(a, 1, i - 1);//然后再把剩下的节点重新生成大顶堆
}
}
int main()
{
int a[] = { 0,13,97,58,111,395,4 };
int len = sizeof(a) / sizeof(int);
HeapSort(a,len-1);
for (int i = 1; i < 7; i++)
{
cout << a[i] << " ";
}
return 0;
}
标签:大顶,结点,temp,int,堆排序,len,算法,排序,节点 来源: https://www.cnblogs.com/Sna1lGo/p/14594079.html