堆:
堆的性质:(二叉)堆数据结构是一种数组对象,它可以被视为一棵完全二叉树。树中每个结点与数组中存放该结点值的那个元素对应。树的每一层都是填满,最后一层可能除外(最后 一层从一个结点的左子树开始填)。表示堆的数组A是一个具有两个属性的对象:length[A]是数组中元素的个数,heap-size[A]是存放在A中的堆的元素个数。就是说,虽然A[1...length[A]]中都可以包含有效值,但A[heap-size[A]]之后的元素都不属于相应的堆,此处heap-size[A]<=length[A]。树的为A[1]。树的根为A[1]。(摘自《算法导论》)
堆排序基本原理:
先建一个最大堆或者最小堆,然后再把最后一个元素与树根交换,heap-szie减一,从而缩小堆的大小,被交换出去的树根是所有元素中的最大值或者最小值,堆外的元素为已排序元素。然后用Heapify对新树根保持堆性质。依此类推,直到堆剩下一个元素。
时间复杂度:O(nlgn)
代码实现():
#include<stdio.h>
#define N 50
#define INIFINE -10000
#define LEFT(i) (2*(i)) //use the "<<" or ">>" will be TLE
#define RIGHT(i) (2*(i)+1)
#define PARENT(i) ((i)/2)
int nHeapSize = 0 ;
int nLength = 0 ;
void MaxHeapify(int *A,int i) ; //保持堆性质的一个最重要的过程
void BuildMaxHeap(int *A) ;
void HeapSort(int *A) ;
int HeapDelete(int *A,int i) ; //练习题6.5-7,未测试
int HeapMaximun(int *A) ; //返回堆的最大值,未测试
int HeapExtractMax(int *A) ; //返回堆的最大值,并将之去除
void HeapIncreaseKey(int *A,int i,int nKey) ; //增加某个结点的关键字的值
void MaxHeapInsert(int *A,int nKey) ; //向堆插入新的元素
int main(void)
{
int i,n ;
int A[N] ;
freopen("in.txt","r",stdin) ;
while(scanf("%d",&n) != EOF )
{
nLength = 0 ;
nHeapSize = 0 ;
for(i = 1 ; i <= n ; i++)
{
scanf("%d",&A[i]) ;
nLength++ ;
}
printf("You had input the List:\n") ;
for(i = 1 ; i <= n ; ++i)
{
printf("%-3d",A[i]) ;
}
printf("\n") ;
HeapSort(A) ;
printf("After Sort:\n") ;
for(i = 1 ; i <= n ; ++i)
{
printf("%-3d",A[i]) ;
}
printf("\n\n") ;
}
return 0 ;
}
int HeapDelete(int *A,int i) //like the HeapSort function
{
int nTemp ;
nTemp = A[i] ;
A[i] = A[nHeapSize] ;
A[nHeapSize] = nTemp ;
nHeapSize-- ;
MaxHeapify(A,i) ;
return nTemp ;
}
void HeapInsert(int *A,int nKey)
{
nHeapSize++ ;
A[nHeapSize] = -INIFINE ; //aim to keep the heap attribute
HeapIncreaseKey(A,nHeapSize,nKey) ;
}
void HeapIncreaseKey(int *A,int i,int nKey)
{
int nTemp = 0 ;
if(nKey < A[i])
{
return ;
}
A[i] = nKey ;
while(i > 1 && A[PARENT(i)] < A[i])
{
nTemp = A[i] ;
A[i] = A[PARENT(i)] ;
A[PARENT(i)] = nTemp ;
i = PARENT(i) ;
}
}
int HeapExtractMax(int *A)
{
int nMax = 0 ;
if(nHeapSize < 1)
{
return -1 ;
}
nMax = A[1] ;
A[1] = A[nHeapSize] ;
nHeapSize-- ;
MaxHeapify(A,1) ;
return nMax ;
}
int HeapMaximun(int *A)
{
return A[1] ;
}
void HeapSort(int *A)
{
int i,nTemp ;
BuildMaxHeap(A) ;
for(i = nLength ; i >= 2 ; --i)
{
nTemp = A[i] ;
A[i] = A[1] ;
A[1] = nTemp ;
nHeapSize-- ;
MaxHeapify(A,1) ;
}
}
void BuildMaxHeap(int *A)
{
int i ;
nHeapSize = nLength ; //
for(i = nLength/2 ; i >= 1 ; --i)
{
MaxHeapify(A,i) ;
}
}
void MaxHeapify(int *A,int i)
{
int l,r,nTemp,nLargest ;
l = LEFT(i) ;
r = RIGHT(i) ;
if(l <= nHeapSize && A[i] < A[l])
{
nLargest = l ;
}
else
{
nLargest = i ;
}
if(r <= nHeapSize && A[nLargest] < A[r] )
{
nLargest = r ;
}
if(i != nLargest)
{
nTemp = A[i] ;
A[i] = A[nLargest] ;
A[nLargest] = nTemp ;
MaxHeapify(A,nLargest) ;
}
}