堆的定义
1,L(i)<=L(2i) 且 L(i)<=L(2i+1);小根堆
2,L(i)>=L(2i) 且 L(i)>=L(2i+1);大根堆
原理
对初始序列建堆,就是一个反复筛选的过程。
n个结点的完全二叉树,最后一个节点是n/2个结点的孩子,对第m/2和其之前的节点为根的子树摔选,看该节点信息与其左右子结点的值比较,如果不符合条件,交换后,再对交换后的子结点进行判断,也就是不断向下调整的过程
源程序:
//测试数据53 17 78 9 45 65 87 32,插入63
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
void AdjustDown(ElemType A[],int k,int len);
//交换实参数据
void swap(int &m,int &n)
{
int tmp;
tmp=m;
m=n;
n=tmp;
}
//建立大根堆
void BuildMaxHeap(ElemType A[],int len)
{
for(int i=len/2;i>0;i--)
AdjustDown(A,i,len);
}
//建堆,向下调整
void AdjustDown(ElemType A[],int k,int len)
{
A[0]=A[k];
for(int i=2*k;i<=len;i*=2)
{
if(i<len && A[i]<A[i+1])
i++;
if(A[0]>=A[i]) break;
else
{
A[k]=A[i];
k=i;
}
}
A[k]=A[0];
}
//堆排序
void HeapSort(ElemType A[],int len)
{
//BuildMaxHeap(A,len);
int i;
for(i=len;i>1;i--)
{
swap(A[i],A[1]);
AdjustDown(A,1,i-1);
}
}
//插入数据,向上调整
void AdjustUp(ElemType A[],int k)
{
A[0]=A[k];
int i=k/2;
while(i>0 && A[i]<A[0])
{
A[k]=A[i];
k=i;
i=k/2;
}
A[k]=A[0];
}
int main()
{
int n;
printf("输入数据个数:");
scanf("%d",&n);
ElemType *B=(ElemType *) malloc ((n+2) * sizeof(ElemType));
ElemType *A=(ElemType *) malloc ((n+2) * sizeof(ElemType));
//ElemType B[10];
//ElemType A[10];
//int *A=new int[m];
int i;
for(i=1;i<=n;i++)
scanf("%d",&A[i]);
BuildMaxHeap(A,n);
printf("大根堆:");
for(i=1;i<=n;i++)
printf("%d ",A[i]);
printf("\n插入一个数:");
scanf("%d",&A[n+1]);
printf("\n插入后的大根堆:");
BuildMaxHeap(A,n+1);
for(i=1;i<=n+1;i++)
printf("%d ",A[i]);
AdjustUp(A,n+1);
HeapSort(A,n+1);
printf("\n堆排序:");
for(i=1;i<=n+1;i++)
printf("%d ",A[i]);
return 0;
}
结果
hadoop@master:~/algorithm/sort/HeapSort$ g++ -c HeapSort.cpp
hadoop@master:~/algorithm/sort/HeapSort$ g++ HeapSort.o -o HeapSort
hadoop@master:~/algorithm/sort/HeapSort$ ./HeapSort
输入数据个数:8
53 17 78 9 45 65 87 32
大根堆:87 45 78 32 17 65 53 9
插入一个数:63
插入后的大根堆:87 63 78 45 17 65 53 9 32
堆排序:9 17 32 45 53 63 65 78 87
堆排序的过程实际就是不断删除堆的根数据的过程,每删除一个根元数,就对其余剩余的数据再次建堆,建堆中在不断的向下调整序列。
空间复杂度:O(1)
时间复杂度:建堆:O(n),每次调整:O(h),h调整的高度,最好,最坏和平均情况都是一样的复杂度:O(nlogn)
稳定性:不稳定