堆排序(實現c++)

碼出地球發表於2019-08-06

  堆可以看作是一個完全二叉樹,分為大頂堆和小頂堆,本文我們以大頂堆為例來實現堆排序。

  (1)建堆

  先把給定的序列轉換成一棵完全二叉樹,然後逐步對其調整使其每個結點的值都大於其兩個子結點的值,因此我們需要從第一個非葉結點開始逐步向前調整(葉結點不存在子結點比其大的狀況,所以從非葉結點往前調整),假設一共有n個元素,那麼第一個調整的結點為n/2。

  (2)交換並調整

  每次調整後將第一個最大的結點跟尾結點換位,則每一輪都是最大的在末尾,然後再次堆第一個結點進行調整,使得成為大頂堆,然後再次交換並調整,以此往復。

void shift(int a[], int low, int high){
    //對陣列中處於low位的結點進行一次向下調整
    int temp = a[low];
    int i = low, j = 2*i; //i為待調整結點,j為i的子結點,
    while(j <= high){
        //若i沒有子結點則跳出迴圈
        if(a[j] < a[j+1]) //跟子結點中較大的比較
            j++;
        if(a[j] > temp){ //大頂堆子結點較大就跟雙親結點換位
            a[i] = a[j];
            i = j;
            j = 2 * i;
        }
        else
            break;
    }
    a[i] = temp;
}
void heapSort(int a[], int n){
    //陣列下標從1開始
    int i;
    int temp;
    for (i = n/2; i >= 1; --i) //建堆,從第一個非頁結點即n/2開始逐步往前調整
    {
        shift(a, i, n);
    }
    
    for (i = n; i >= 2; ++i)//調整的第二個結點就行了,後面n-1個結點有序,且較大
    {
        tmep = a[1];//每次調整後將第一個最大的跟尾結點換位,則每一輪都是最大的在末尾
        a[1] = a[i];
        a[i] = temp;
        shift(a, 1, n-1);
    }
}

 

相關文章