8.2再談排序與檢索

8.2.1歸併排序

第一種高效排序算法是歸併排序,按照分治三步法,對歸併排序算法介紹如下

劃分問題:把序列分成元素個數儘量相等的兩半

遞歸求解:把兩半元素分別排序

合併問題:把兩個有序表合併成一個

void merge_sort(int* A,int x,int y,int* T){
    if(y-x>1){
        int m=x+(y-x)/2;          //劃分
        int p=x,q=m,i=x;
        merge_sort(A,x,m,T);  //遞歸分解
        merge_sort(A,m,y,T);   //遞歸
        while(p<m||q<y){
            if(q>=y||(p<m&&A[p]<=A[q]))
                T[i++]=A[p++];
            else
                T[i++]=A[q++];
        }
        for(i=x;i<y;i++)
            A[i]=T[i];   //從輔助空間複製回數組A
    }
}

逆序對問題

分析:n特別大,所以n*n枚舉會超時,因此需尋找更高效的方法。下面試試“分治三步法”

“劃分問題”過程是吧序列分成元素個數儘量相等的兩半;

“遞歸求解”是統計i和j均在左邊或者均在右邊的逆序數對個數;

“合併問題”則是統計i在左邊,但j在右邊的逆序對個數,對於右邊的每個j,統計左邊比他大的元素個數f(j),f(j)之和便是答案


8.2.2快速排序

快速排序是最快的通用內部排序算法。

劃分問題:把數組的各個元素重排後分成左右兩部分,使得左邊的任意元素都小於或等於右邊的任意元素

遞歸求解:把左右兩部分分別排序

合併問題:不用合併,因爲此時數組已經完全有序

8.2.3二分查找

int bsearch(int* A,int x,int y,int v){
    int m;
    while(x<y){
        m=x+(y-x)/2;
        if(A[m]==v)
            return m;
        else if(A[m]>v)
            y=m;
        else
            x=m+1;
    }
    return -1;
}

下面的程序,當V存在時返回他出現的第一個位置。如果不存在,返回這樣一個下標i,在此處插入V後序列仍然有序

二分查找求下界

int lower_bound(int* A,int x,int y,int v){
    int m;
    while(x<y){
        m=x+(y-x)/2;
        if(A[m]>=v)
            y=m;
        else
            x=m+1;
    }
    return x;
}





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