堆排序(Heapsort)
堆排序是一种原地排序算法,在任何时候只有常数个元素存储在输入数组以外,其运行时间为O(nlgn)。
堆数据结构被视为一颗完全二叉树,树的每个节点对应数组中该节点的值,树的每一层都是满的(最后一层可能不满)。堆的数组A具有两个属性,即数组的长度length(A)和存放在A中的堆的元素的个数heap-size[A]。树的根为A[0],给定某个节点的下标i,其父节点Parent(i),其左儿子为lchild(i)和右儿子rchild(i):
Parent(i)=i/2;
lchild(i)=2*i+1;
rchild(i)=2*i+2;
二叉堆有最大堆和最小堆之分,最大堆的左右儿子节点均小于父节点(根为最大元素),最小堆的左右儿子节点均大于父节点(根为最小元素),下面以最大堆为例:
最大堆:
MAX-HEAPIFY(A,i)
l <- lchild(i)
r <- rchild(i)
if l<heap-size[A] and A[l]>A[i]
then max <- l
else max <- i
if r<heap-size[A] and A[r]>A[max]
then max <- r
if max ≠ i
then exchange A[i] <-> A[max]
MAX-HEAPIFY(A,max)
建堆:
BUILD-MAX-HEAP(A)
heap-size[A] <- length[A]
for i <- length/2 downto 0
do MAX-HEAPIFY(A,i)
堆排序:
HEAPSORT(A)
BUILD-MAX-HEAP(A)
for i<- length[A] downto 0
do exchange A[0] <-> A[i]
heap-size[A] <- heap-size[A]-1
MAX-HEAPIFY(A,0)
C 语言实现代码:
#include<stdio.h>
void Swap(int * a,int * b)
{
int temp=*a;
*a=*b;
*b=temp;
}
void Max_Heap(int A[],int n,int root)
{
int lchild=2*root+1;
int rchild=2*root+2;
int max=root;
if((lchild<n)&&(A[lchild]>A[max]))
max=lchild;
if((rchild<n)&&(A[rchild]>A[max]))
max=rchild;
if(max!=root)
{
Swap(&A[max],&A[root]);
Max_Heap(A,n,max);
}
}
void Build_Heap(int A[],int n)
{
int i;
for(i=n/2;i>=0;i--)
{
Max_Heap(A,n,i);
}
}
void Heap_Sort(int A[],int n)
{
int i;
Build_Heap(A,n);
for(i=n-1;i>=0;i--)
{
Swap(&A[0],&A[i]);
n--;
Max_Heap(A,n,0);
}
}
void main()
{
int j;
int A[]={0,16,20,3,11,17,8};
Heap_Sort(A,7);
for(j=0;j<7;j++)
{
printf("%d ",A[j]);
}
printf("\n\n");
system("pause");
}