#include<stdio.h> #include<stdlib.h> #define CAPACITY 20 /*堆有兩個性質: * 1.結構性:堆必須是一顆完全二叉樹 * 2.堆序性:堆的父節點要么都大於子節點,要么小於子節點,前者叫大頂堆,后者叫小頂堆; * 由此,堆可以用一個數組來表示,並有如下性質: * 1.對於任意i位置的元素,他的左子節點在2i位置,右子節點在2i+1位置; * 2.他的父節點(假如有)在i/2位置*/ /*創建一個小頂堆,size代表的是實際元素的個數*/ typedef struct MinHeap { int size; int data[CAPACITY]; } heap; void init( heap *h ); void insert(heap *h,int x); void travel(heap *h); /*數組0位置要空着*/ void init( heap *h ) { h->size=0; } void insert(heap *h,int x) { if(h->size == CAPACITY) { printf("heap is full!"); return; } int i; h->size++; for(i=h->size; i>=1; i/=2) { if(x < h->data[i/2]) { h->data[i]=h->data[i/2]; } else { break; } } h->data[i]=x; } /*刪除最小元素,在小頂堆即意味着刪除根節點 * 1.首先將根元素保存,等待最后return; * 2.將最后一個元素賦值給根元素,並將這個值賦給緩沖區,這樣保證了堆的結構性; * 3.從根節點開始遍歷,比較父節點和兩個子節點的大小,如果緩沖區值大於較小的子節點,則將小節點的值賦給父節點 * 4.直到緩沖區值小於游標的兩個子節點,此時將緩沖區值賦給游標所在位置*/ int deleteMin(heap *h) { int child; int result=h->data[1]; h->data[1]=h->data[h->size]; h->size--; int i=1; int temp=h->data[1]; for(i=1; 2*i <= h->size; i=child) { child=2*i; if(child !=h->size && h->data[child] > h->data[child+1] ) {/*如果左子節點非最后元素且>右子節點,則右子節點最小*/ child++; } if(temp > h->data[child]) {/*如果temp大於當前元素的最小子節點,則將最小子節點賦值給父節點,否則跳出*/ h->data[i]=h->data[child]; } else { break; } } h->data[i]=temp;/*將緩沖區值賦給當前游標*/ return result; } /*遍歷堆數組:越過空白位置0,從1開始*/ void travel(heap *h) { int i; for(i=1; i<=h->size; i++) { printf("%d ",h->data[i]); } printf("\n"); } /*堆排序*/ void heap_sort(int a[],int n) { int i; heap *h=(heap*)malloc(sizeof(heap));/*給堆指針分配空間*/ init(h);/*初始化堆*/ for(i=0; i<n; i++) {/*將數組的元素依次插入堆*/ insert(h,a[i]); } for(i=0; i<n; i++) { a[i]=deleteMin(h); } } /*遍歷數組*/ void travel_array(int a[],int n) { int i; for(i=0; i<n; i++) { printf("%d ",a[i]); } printf("\n"); } main() { int a[]= {67,8,4,34,86,87,6,45,7,864,56,1,3,78,9,13}; int n=sizeof(a)/sizeof(int); travel_array(a,n); heap_sort(a,n); travel_array(a,n); }