排序算法的判別: Insert or Merge,Insertion or Heap Sort

1. 09-排序2 Insert or Merge

#include<stdio.h>
#define ElementType int
#define MAXN 101


int arrayEqual(int A[], int B[], int N)
{
    int i,ans = 1;
    for(i=0; i<N; i++)
    {
        if(A[i] != B[i])    
        {
            ans = 0;
            break;
        }
    }
    return ans;
}
void printArray(int A[], int N)
{
    int i;
    printf("%d",A[0]);
    for(i=1; i<N; i++)
    {
        printf(" %d",A[i]);
    }
    printf("\n");
}
void Insert_sort(ElementType A[], ElementType B[], int N){
    int i,j;
    int equ = 0;
    ElementType tmp;
    for(i=1; i<N; i++){
        tmp = A[i];         //摸下一張牌
        for(j=i-1; j>=0 && tmp<A[j]; j--){
            A[j+1] = A[j];      //移出空位
        }
        A[j+1] = tmp;           //新牌落位

        if(equ == 1)
        {
            printf("Insertion Sort\n");
            printArray(A,N);
            break;

        }
        if(arrayEqual(A,B,N))
        {
            equ = 1;
        }                  
    }
}

void Merge(ElementType A[],ElementType tmpA[], int L, int R, int rightEnd)
{
    int tmp = L,leftEnd = R-1,size = rightEnd-L+1;
    while(L<=leftEnd && R<=rightEnd)
    {
        if(A[L] <= A[R])    tmpA[tmp++] = A[L++];
        else                tmpA[tmp++] = A[R++];
    }
    while(L<=leftEnd)       tmpA[tmp++] = A[L++];
    while(R<=rightEnd)      tmpA[tmp++] = A[R++];

    int i;
    for(i=0; i<size; i++)   A[rightEnd-i] = tmpA[rightEnd-i];

}
//將A[]中的N個元素歸併到tmpA[]中,其中length表示當前有序子列的長度 
void Merge_pass(ElementType A[], ElementType tmpA[], int N, int length)
{
    int i;
    for(i=0; i<=N-2*length; i+=2*length)
    {
        Merge(A, tmpA, i, i+length, i+2*length-1);
    }
    //歸併最後兩個列 
    if(i+length < N)    Merge(A, tmpA, i, i+length, N-1);
    else{//如果最後只剩一個子列 
        for(; i<N; i++) tmpA[i] = A[i];     
    }               
}

void Merge_sort(ElementType A[],ElementType B[], int N)
{
    int length = 1, equ = 0;
    ElementType *tmpA;
    tmpA = malloc(sizeof(ElementType) * N);
    if(tmpA != NULL)
    {
        while(length < N)
        {
            //將A歸併到tmpA 
            Merge_pass(A, tmpA, N, length);
            length *= 2;
            if(equ == 1)
            {
                printf("Merge Sort\n");
                printArray(tmpA, N);
                break;
            }
            if(arrayEqual(tmpA, B, N))  equ = 1;

            //將tmpA歸併到A中 
            Merge_pass(tmpA, A, N,length);
            length *= 2;
            if(equ == 1)
            {
                printf("Merge Sort\n");
                printArray(A, N);
                break;
            }
            if(arrayEqual(A, B, N)) equ = 1;
        }
        free(tmpA);     
    }else
    {
        printf("空間不足\n");
    } 

}


int main()
{
    int ini[MAXN],res[MAXN];
    int tmp[MAXN];
    int N,i;
    //freopen("insertOrMerge.txt","r",stdin);

    scanf("%d",&N);
    for(i=0; i<N; i++)  scanf("%d",&ini[i]);
    for(i=0; i<N; i++)  scanf("%d",&res[i]);

    for(i=0; i<N; i++)  tmp[i] = ini[i];
    Insert_sort(tmp,res,N);

    for(i=0; i<N; i++)  tmp[i] = ini[i];
    Merge_sort(tmp,res,N);

    return 0;
}

  • 小結
    這兒有一個優化,可以讓插入排序有一個返回值,如果確實是插入排序,就不再執行歸併排序了。
    但我這兒看到N比較小,也就沒有這樣做了。

2. Insertion or Heap Sort

  • 題目
    09-排序3 Insertion or Heap Sort (25分)
  • 分析
    這道題和上面那一道是同種類型的題目。不過是把判斷歸併排序改成了判斷堆排序。
    堆排序要注意的是數組從0還是1的位置開始放入有效元素。如果是從0開始,那麼 leftChild = parent*2;從1開始,那麼 leftChild = parent*2+1。我就是這兒沒注意導致結果一直有問題。
    同時我上面說的那個小優化在這次代碼中實現了。
  • 我的代碼
#include<stdio.h>
#define ElementType int
#define MAXN 101


int arrayEqual(int A[], int B[], int N)
{
    int i,ans = 1;
    for(i=0; i<N; i++)
    {
        if(A[i] != B[i])    
        {
            ans = 0;
            break;
        }
    }
    return ans;
}

void printArray(int A[], int N)
{
    int i;
    printf("%d",A[0]);
    for(i=1; i<N; i++)
    {
        printf(" %d",A[i]);
    }
    printf("\n");
}

int Insert_sort(ElementType A[], ElementType B[], int N){
    int i,j;
    int equ = 0, right = 0;
    ElementType tmp;
    for(i=1; i<N; i++){
        tmp = A[i];         //摸下一張牌
        for(j=i-1; j>=0 && tmp<A[j]; j--){
            A[j+1] = A[j];      //移出空位
        }
        A[j+1] = tmp;           //新牌落位

        if(equ == 1)
        {
            right = 1;
            printf("Insertion Sort\n");
            printArray(A,N);
            break;

        }
        if(arrayEqual(A,B,N))
        {
            equ = 1;
        }                  
    }

    return right;
}

void Filter(ElementType A[], int pos, int N)
{
    int child,parent;
    ElementType tmp = A[pos];
    for(parent=pos; parent*2+1<N; parent=child)
    {
        child = parent*2+1;
        if(child+1<N && A[child]<A[child+1])    child++;

        if(A[child] > tmp){
            A[parent] = A[child];
        }else{
            break;
        }
    }
    A[parent] = tmp;
}
void BuildMaxHeap(ElementType A[], int N)
{
    int i;
    for(i=N/2-1; i>=0; i--) Filter(A, i, N);    
} 

Swap(ElementType A[], int i, int j)
{
    ElementType tmp = A[i];
    A[i] = A[j];
    A[j] = tmp;
}

int Heap_sort(ElementType A[], ElementType B[], int N)
{
    int i;
    int equ = 0, right = 0;
    BuildMaxHeap(A, N);

    //printArray(A,N);
    for(i=N-1; i>=0; i--)
    {
        Swap(A, 0, i);
        Filter(A, 0, i);

    //  printArray(A,N);

        if(equ == 1)
        {
            right = 1;
            printf("Heap Sort\n");
            printArray(A,N);
            break;

        }
        if(arrayEqual(A,B,N))
        {
            equ = 1;
        }   
    } 
    return right;
}

int main()
{
    int ini[MAXN],res[MAXN];
    int tmp[MAXN];
    int N,i;

    #ifndef ONLINE_JUDGE
    freopen("insertOrMerge.txt","r",stdin);
    #endif

    scanf("%d",&N);
    for(i=0; i<N; i++)  scanf("%d",&ini[i]);
    for(i=0; i<N; i++)  scanf("%d",&res[i]);

    for(i=0; i<N; i++)  tmp[i] = ini[i];
    int right = Insert_sort(tmp,res,N);

    if(right == 0)
    {
        for(i=0; i<N; i++)  tmp[i] = ini[i];
        Heap_sort(tmp,res,N);
    }


    return 0;
}
  • 小結
    在這次我學到了一個小技巧:
    如果經常在本地代碼進行重定向,從文件輸入,然後提交到OJ上經常忘記註釋的話,可以這樣:
#ifndef ONLINE_JUDGE
    freopen("insertOrMerge.txt","r",stdin);
#endif

因爲一般的OJ都會給我們提交的程序加上#define ONLINE_JUDGE
這是一種條件編譯
上述代碼意思就是如果沒有 define ONLINE_JUDGE的話,就會編譯下面的語句;如果已經定義了的話,比如在程序前面加上#define ONLINE_JUDGE,那麼就不會編譯下面的語句,標準輸入設備還是鍵盤。
還有一種比較常用的條件編譯如下:

#define DEBUG 1
#if DEBUG
    printf("%d %d\n",x,y);
#endif

在我們調試程序的時候使 DEBUG 值爲1,就可以輸出一些中間結果,方便程序的調試;當我們調試結束,要提交代碼的時候,可是又不想刪除掉這些輸出語句時(爲了方便以後程序的修改調試),那麼我們只需要修改 DEBUG 的值爲0,編譯器進行預處理的時候就不會編譯下面的這句語句了。
所以條件編譯有時候是很有用的。

發佈了90 篇原創文章 · 獲贊 46 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章