1. 程式人生 > >演算法入門--堆排序(最大堆,從小到大排序)

演算法入門--堆排序(最大堆,從小到大排序)

#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;
}