堆排序,用以下无序序列加以验证:
49,38,65,97,76,13,27,49
/*
堆排序,用以下无序序列加以验证:
49,38,65,97,76,13,27,49
*/
#include <stdio.h>
#define N 9
//堆算法,模拟 完全二叉树的一种算法(核心是如根节点下标i 左子树下标等于2 * i 右子树等于左子树+1即2 * i + 1)
//构造成一个大顶堆,k为要调整的非叶子结点下标,size为数组a[]的大小
void adjust_mheap(int a[],int k,int size)
{
int x = a[k];//要处理的元素 (这个始终不变)
int j = 2 * k;//默认为 k 的左孩子下标
//开始从k 开始 下坠调整
while(j <= size)//如果k有左孩子(2 * k <= size数组大小)
{
if(j < size && a[j] < a[j + 1])//j < size说明k有右孩子,然后选择k的两个孩子中值大的进行比较(如果值比其还大 说明比孩子都大)
{
j ++;//说明右孩子大,把j + 1等于右孩子的下标
}
//开始根节点值与 其最大的孩子结点 比较
if(x < a[j])//根是否比其小,满足则交换,大根堆保证 越小越往下走,局部最大值向上浮
{
a[k] = a[j];//变化根的值为其该孩子的值,由于x始终保存起先a[k]的值,所以最先的根值不会遗失--*****
k = j; //然后记录 该孩子的地址 方便后面交换值
j = j * 2; //再类似的 处理 这个孩子的孩子
}
else
{
break;
}
}
a[k] = x;//找到最开始的值 下沉的位置,然后赋值为最初传入的x值,形式上是x值与*号哪一行的a[k]值交换
return;
}
//堆排序(不稳定算法)
void heapSort(int a[],int size)
{
//建立初始大根堆
for(int i = size/2;i >= 1;i --)//(size - 1)/2为最后一个非叶结点,依次-1为倒数第二....
{
adjust_mheap(a,i,size);//参数:数组,开始调整的下标,数组长度。从最后一个非叶结点开始调整
}
int x = 0;//作为交换媒介,用与最大值和最后每处理元素交换
for(int i = size;i >= 2;i --)
{
//大根堆的根为最大值(数组第一个元素),将其与当前没有处理的 最后一个元素交换
x = a[1];a[1] = a[i];a[i] = x;//exchange
//交换后排除最后一个元素(已经是有序),然后调整为大根堆
adjust_mheap(a,1,i - 1);//由于此时只有1由于交换仍可能无序,故只用按照下标0进行 大根堆调整
}
return;
}
void prin_a(int a[]);
int main()
{
int a[N] = {0,49,38,65,97,76,13,27,49};//舍掉第一个 元素空间 不用
//快速排序
heapSort(a,N - 1);//参数:数组,实际处理元素个数(不包括舍弃的第一个空间)
//打印数组
prin_a(a);
return 0;
}
//打印数组
void prin_a(int a[])
{
for(int i = 1;i < N;i ++)
{
printf("%d ",a[i]);
}
printf("\n");
return;
}