#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
typedef int ElemType;
typedef struct{
ElemType *elem;
int TableLen;
}SSTable;
void ST_Init(SSTable &ST,int len)//申请空间,并进行随机数生成
{
ST.TableLen=len;
ST.elem=(ElemType *)malloc(sizeof(ElemType)*ST.TableLen);
int i;
srand(time(NULL));
for(i=0;i<ST.TableLen;i++)
{
ST.elem[i]=rand()%100;
}
}
void ST_print(SSTable ST)
{
for(int i=0;i<ST.TableLen;i++)
{
printf("%3d",ST.elem[i]);
}
printf("\n");
}
void swap(ElemType &a,ElemType &b)
{
ElemType tmp;
tmp=a;
a=b;
b=tmp;
}
void AdjustHeap(int *&A,int parent,int len){
int child;
child = 2*parent+1;
while(child<len){
if(child<len-1 && A[child]<A[child+1]){
child++; //右子树比左子树大
}
if(A[child]>A[parent]){
swap(A[parent],A[child]);
parent = child;
child = 2*parent+1;
}else {
break;
}
}
}
void HeapSort(int *&A,int len){
int i;
//初始化堆,定义每一棵子树的具体堆排序,确定好中间层正确的排序
for(i=len/2-1;i>=0;i--){
AdjustHeap(A,i,len);
}
swap(A[len-1],A[0]);
//对堆进行排序
int count;
for(count=len-1;count>0;count--){
AdjustHeap(A,0,count);
swap(A[count-1],A[0]);
}
//不能够直接这样进行排序,因为无法处理隔代。所以初始化堆是有道理的,从最后一个非叶子结点开始进行堆排序能够让所有大的节点成为父节点
//而下面这个方法是直接从根节点开始找最大孩子节点,会忽略隔代。比如 67 86 84 90 20 19 72 11 89 45排出来是 11 19 20 45 67 72 84 89 90 86,事实上最大为90
//90之所以没被检测到是因为爷结点67在和父节点86交换之后,父节点就变成86,父节点再和90交换,但是90却不会和67交换了
//因此我们需要的是一个基本构建好的大根堆,也就是中间层的大小一定要正确,只能是第一层和第二层的排序有误。这样才能让根节点顺利从根结点处沿着正确方向到达应该去的地方
// 【排序直接从根节点开始沿着路线的子树遍历即可】其他方向的子树大小排序并不会改变也无需发生改变
// for(i=len;i>0;i--){
// AdjustHeap(A,0,i);
// swap(A[i-1],A[0]);
// }
}
//堆排序
int main()
{
SSTable ST;
ST_Init(ST,10);//初始化
ST_print(ST);
HeapSort(ST.elem,10);//所有元素参与排序
ST_print(ST);
return 0;
}