1. 程式人生 > >資料結構實驗之排序四:尋找大富翁(SDUT 3401)

資料結構實驗之排序四:尋找大富翁(SDUT 3401)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void Swap(int a[], int i, int j)  // 交換函式
{
    int t = a[i];
    a[i] = a[j];
    a[j] = t;
}

void HeapMerge(int *a,int i,int n)  //調整函式,也是核心地方 // 以下的樹的概念都是把這個堆轉變成樹來說的
{
    int lc = 2*i;  // 因為我們用一位陣列存放的,這裡下標從1開始,如果1存放根結點,那麼左紫薯就是2×i 右紫薯是 2 × 1 + 1
    int rc = 2*i+1;  // 因為堆排序這裡是一顆完全二叉樹,層次遍歷這個樹,然後依次放進這個下標從1開始的陣列中,得到的就是以上結果了
    int k = i;  //存放當前調整的結點的下標
    if(i <= n/2) //如果大於n/2,就是葉子結點了,就不需要再調整了
    {
        if(lc <= n && a[lc] > a[k]) // 左子樹的比較
        {
            k = lc;
        }
        if(rc <= n && a[rc] > a[k]) // 右紫薯的比較 這樣子就是選的左右紫薯中大的那個了
        {
            k = rc;
        }
        if(k != i)  // 如果找到了它的左右紫薯中比它大的
        {
            Swap(a,i,k); // 交換這兩個值
            HeapMerge(a,k,n); // 繼續把k這個位置的數,也就是上一步中為交換前的a[i],往下調整,要保證左右紫薯都小於根節點
        }
    }
}

void HeapCreat(int *a,int n)
{
    for(int i=n/2; i>=1; i--)
    {
        HeapMerge(a,i,n); // 從第一個非葉子結點開始調整樹,n/2就是第一個非葉子結點,完全二叉樹的性質決定的。
    }
}

void HeapSort(int *a,int n)
{
    int i;
    HeapCreat(a,n); //先調整好樹,讓成為一個大頂堆
    for(i=n; i>=1; i--)
    {
       Swap(a,1,i);  // 把這個堆頂,也就是最大的,放到最後
        HeapMerge(a,1,i-1); // i - 1 也就是剩下的再重新調整
                            // 直到全部完成,層次遍歷樹變成有序序列,對應的陣列就是有序陣列
    }
}

int main()
{
    int n,m,p,t, Min;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        int a[12];
        p = 1;
        for(int i = 0; i < n; i++)  // 這個題的原因,不能全部輸入,對於全部的數建堆
        {
            scanf("%d",&t);
            if(p < m + 1)
                a[p++]=t;
            else
            {
                Min = 1;
                for(int j = 2; j < p; j++)
                {
                    if(a[Min] > a[j])
                        Min = j;
                }
                if(a[Min] < t)
                    a[Min] = t;
            }
        }  //挑出來前 m 大的樹
        HeapSort(a,m); // 堆排
        for(int i = m; i >= 1; i--)
            if(i==m)
                printf("%d",a[i]);
            else
                printf(" %d",a[i]);
        printf("\n");
    }
    return 0;
}