演算法入門--堆排序(最大堆,從小到大排序)
阿新 • • 發佈:2019-01-30
#include <stdio.h> #include <stdlib.h> /*由於不會動態獲得當前堆的元素數量heap_size,所以暫時用傳參的方法,但是當多次執行後發現 為了防止錯誤應該把heap_size設定為全域性變數,主函式初始化後,讓它被各個函式操作過程中動態 改變也是可以的。 */ int left(int i)//返回左孩子位置 { return 2*i; } int right(int i)//返回右孩子位置 { return 2*i+1; } void max_heapify(int *a,int heap_size,int i)//保持堆性質,使以i為根的子樹成為最大堆 ,heap_size當前堆中元素數量 { //假設左右孩子已經分別為最大堆 //l,r分別為左右孩子的位置,largest用於臨時存放當前節點與左右孩子中最大的節點的位置 int l,r,largest; int temp; l=left(i); r=right(i); if(l<=heap_size&&a[l]>a[i])//當做孩子大於父節點時,左孩子設為最大,否則父節點最大 largest=l; else largest=i; if(r<=heap_size&&a[r]>a[largest])//繼續判斷,當右孩子大於最大時,右孩子設為最大,否則剛才的最大不變 largest=r; if(largest!=i)//如果largest變化了,則通過交換使當前最大節點為父節點 { temp=a[i]; a[i]=a[largest]; a[largest]=temp; max_heapify(a,heap_size,largest);//繼續遞迴保持交換後的某一孩子的堆的性質。 } } void build_max_heap(int *a,int length)//建立最大堆 { /*從第一個葉子的前一個節點開始迴圈維護最大堆,由於這個節點後的都是葉子,單一元素可以當做最大堆。 這個葉子往前迴圈,保證每個處理後的節點的子節點都已經是最大堆,一直到根節點。*/ int i,heap_size; for(i=length/2;i>=1;i--) max_heapify(a,length,i); } void heap_sort(int *a,int length)//堆排序,從小到大 ,length為堆中元素數量 { int heap_size=length; int i,temp; build_max_heap(a,length);//建立最大堆 for(i=length;i>=2;i--)//每次把最大堆頂部的元素,即當前的最大值放入陣列末尾,然後維護最大堆性質。 { temp=a[i]; a[i]=a[1]; a[1]=temp; heap_size--; max_heapify(a,heap_size,1);//重新調整為最大堆 } } int main(int argc, char *argv[]) { // int a[11]={0,4,1,3,2,16,9,10,14,8,7};//測試資料 //int length=10; int length;//陣列中的堆的資料的長度 int a[100]; a[0]=0; int i; printf("請輸入元素的數量:"); scanf("%d",&length); printf("\n請依次輸入%d個元素,空格結束:\n",length); for(i=1;i<=length;i++) scanf("%d",&a[i]); printf("\n"); for(i=1;i<=length;i++) printf("%d ",a[i]); printf("\n建立最大堆以後\n"); build_max_heap(a,length); for(i=1;i<=length;i++) printf("%d ",a[i]); printf("\n"); printf("使用堆排序後:\n"); heap_sort(a,length); for(i=1;i<=length;i++) printf("%d ",a[i]); system("PAUSE"); return 0; }