1. 程式人生 > >C++ 歸併排序與快速排序

C++ 歸併排序與快速排序

歸併排序:

【演算法邏輯】
歸併的思路(分治)是把一個大問題a拆解成兩個小問題b和c,解決了兩個子問題再整合一下,就解決了原問題。用遞迴的方法,先分解再合併(分治是一種解決問題的處理思想,遞迴是一種程式設計技巧,這兩者並不衝突):

【程式碼實現】

#include<iostream>

using namespace std;

void Merge(int arr[], int l, int q, int r){
    int n=r-l+1;//臨時陣列存合併後的有序序列
    int* tmp=new int[n];
    int i=0;
    int left=l;
    int right=q+1;
    while(left<=q && right<=r)
        tmp[i++] = arr[left]<= arr[right]?arr[left++]:arr[right++];
    while(left<=q)
        tmp[i++]=arr[left++];
    while(right<=r)
        tmp[i++]=arr[right++];
    for(int j=0;j<n;++j)
        arr[l+j]=tmp[j];
    
}

void MergeSort(int arr[], int l, int r){
    if(l==r)
        return;
    int q = (l + r)/2;
    MergeSort(arr, l, q);
    MergeSort(arr, q + 1, r);
    Merge(arr, l, q, r);
    
}

int main(){
    int a[8] = {3,1,2,4,5,8,7,6};
    MergeSort(a,0,8);
    for(int i=0;i<8;++i)
        cout<<a[i]<<" ";
}

快速排序:

【演算法邏輯】

從數列中挑出一個元素,稱為 “基準”(pivot); 
重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。在這個分割槽退出之後,該基準就處於數列的中間位置。這個稱為分割槽(partition)操作; 
遞迴地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序。

根據分治、遞迴的處理思想,我們可以用遞迴排序下標從 p 到 q-1 之間的資料和下標從 q+1 到 r 之間的資料,直到區間縮小為 1,就說明所有的資料都有序了。這裡涉及到基準的選擇問題,因此必須有函式Partition()來實現“基準”。

【程式碼實現】

#include<iostream>

using namespace std;

int Parition(int a[], int low,int high){
    int pivot=a[high];
    int i=low;
    for(int j=low;j<high;++j)
    {
        if (a[j]<pivot) {
            swap(a[j], a[i]);
            i++;
        }
    }
    swap(a[i], a[high]);
    return i;
    
}

void QuickSort(int a[], int low, int high){
    if(low<high)
    {
        int q=Parition(a,low, high);
        QuickSort(a, low, q-1);
        QuickSort(a, q+1,high);
        
    }
    
}

int main(){
    int a[8] = {3,1,2,4,5,8,7,6};
    QuickSort(a,0,8);
    for(int i=0;i<8;++i)
        cout<<a[i]<<" ";
}