堆排序
堆排序是在排序过程中,将向量中存储的数据看成一颗完全二叉树,利用完全二叉树中双亲结点和孩子结点之间的内在关系来选择关键字的最小的记录,即待排序记录中仍采用向量数组的方式存储,并非采用树的存储结构,二仅仅是采用完全二叉树的顺序结构的特征进行分析而已。
二叉树的顺序表示, 每个结点最多有两个孩子结点(left, right), 这样表示出来的二叉树是一颗完全二叉树。如果父结点的下标为i, 则其左孩子下标为 2i+1, 右孩子下标为2i+2;如果一个结点的下标为j, 则其父结点的下标为(j-1)/ 2。
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define NUMBER 15
void OneAdjust(int* arr,int len,int root)
{
int tmp=arr[root];
int left=2*root+1;
int right=2*root+2;
while(left<len)
{
int max=left;
if(right<len&&arr[left]<arr[right])
{
max=right;
}
if(arr[max]<tmp)
{
break;
}
arr[root]=arr[max];
root=max;
left=2*root+1;
right=2*root+2;
}
arr[root]=tmp;
}
void CreateHeap(int* arr,int len)//建大根堆
{
int root=(len-2)/2;//最后一个结点的下标是len-1,算出的root为最后一棵子树的根结点下标
for(;root>=0;--root)
{
OneAdjust(arr,len,root);
}
}
void Swap(int* a,int* b)
{
int tmp=*a;
*a=*b;
*b=tmp;
}
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);
}
}
int main()
{
srand((unsigned int)time(NULL));
int arr[NUMBER]={0};
for(int i=0;i<NUMBER;++i)
{
arr[i]=rand()%100;
printf("%d ",arr[i]);
}
printf("\n");
HeapSort(arr,NUMBER);
for(int i=0;i<NUMBER;++i)
{
printf("%d ",arr[i]);
}
printf("\n");
return 0;
}
运行结果如下: