要理解堆排序需要理解一下概念:
二叉树:树中每个节点至多有两个子节点
二叉搜索树:对于树中任何节点,如果其左子节点不为空,那么该节点的value值永远 >=
其左子节点;如果其右子节点不为空,那么该节点的value值永远 <=
其右子节点
满二叉树:树中除了叶子节点,每个节点都有两个子节点
完全二叉树:在满足满二叉树的性质后,最后一层的叶子节点均需在最左边
完美二叉树:满足完全二叉树性质,树的叶子节点均在最后一层(也就是形成了一个完美的三角形)
满二叉树、完全二叉树、完美二叉树的定义是越来越严格的。
堆排序是一种完全二叉树,一般使用顺序存储结构。
堆的性质:
① 堆是一棵采用顺序存储结构的完全二叉树, k1是根结点;
② 堆的根结点是关键字序列中的最小(或最大)值,分别称为小(或大)根堆;
③ 从根结点到每一叶子结点路径上的元素组成的序列都是按元素值(或关键字值)非递减(或非递增)的;
④堆中的任一子树也是堆;也是堆。
基本思想:
1、建立堆。
2、将最大值排在最后
3、循环1、2两步。
源码如下:
#include "globle.h"
#define LENG 3
//#define LENG 10
void sort(int a[],int n);
void Getheap(int a[],int inode ,int length){
int child = 2*inode+1; /*左节点位置*/
int tmp = a[inode]; /*节点值*/
while ( child < length )
{
gnum++;
// printf("get: %d %d %d\n",child,inode,length);
if ( child < length && a[child] < a[child + 1] )
{
++child;
}
if ( a[inode] < a[child] )
{
a[inode] = a[child];
inode = child;
child = 2*inode+1;
}
else
{
break;
}
a[inode] = tmp;
}
//print(a,10,10);
}
void sort(int a[],int n){
int inode = (n-2)/2;
for ( ;inode > 0 ; --inode ){
Getheap(a,inode,n);
}
}
void heapsort(int a[],int n){
sort(a,n);
printf("build heap finshed: ");
print(a,LENG,LENG);
for ( int i = n-1;i>1;i--)
{
Getheap(a,0,i);
int temp = a[i];
a[i] = a[0];
a[0]= temp;
printf("build heap finshed %d [%d]: ",i,a[i]);
//print(a,10,10);
}
printf("after sort finshed: ");
//print(a,10,10);
}
int main(){
//int iarry[10]={1,3,0,2,4,7,6,5,9,8};
// int iarry[10]={8,1,4,9,5,3,6,7,2,0};
int iarry[10]={1,8,4};
print(iarry,LENG,LENG);
heapsort(iarry,LENG);
printf(" gnum : %d\n",gnum);
/* int i=1;
int k=2;
k=k^i;
i=k^i;
k=k^i;
printf(" %d %d \n",k,i);*/
return 0;
}