堆:
堆的性质:(二叉)堆数据结构是一种数组对象,它可以被视为一棵完全二叉树。树中每个结点与数组中存放该结点值的那个元素对应。树的每一层都是填满,最后一层可能除外(最后 一层从一个结点的左子树开始填)。表示堆的数组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) ; } }