常用排序算法C++版小結

常用排序算法及其時間複雜度和空間複雜度

代碼來自網絡和日常整理:

#include <iostream>

using std::cout;

inline void swap(int &a, int &b) { int tmp = a; a = b; b = tmp; }

//AVG: O(n*n) WOREST: O(n*n), Space: O(1), Ascend
void bubbleSort(int *arr, int len);

//AVG: O(n*n) WOREST: O(n*n), Space: O(1), Ascend
void selectSort(int *arr, int len);

//AVG: O(n*n) WOREST: O(n*n), Space: O(1), Ascend
void insertSort(int *arr, int len);

//AVG: O(n*logn) WOREST: <O(n*n), Space: O(1), Ascend
void shellSort(int *arr, int len);

//AVG: O(n*logn) WOREST: O(n*n), Space: O(n*logn), Ascend
void quickSort(int *arr, int start, int end);

//AVG: O(n*logn) WOREST: O(n*logn), Space: O(1), Ascend
void mergeSort(int *arr, int start, int end);
void mergeSort2(int *arr, int start, int mid, int end);

//AVG: O(n*logn) WOREST: O(n*logn), Space: O(1), Ascend
void heapSort(int *arr, int len);
void heapSort2(int *arr, int idx, int len);//大根堆, 根節點的值大於子節點

//基數排序的時間複雜度表達式不好寫,見下文
//AVG: WOREST:,Space: O(n), Ascend
int GetLoopCnt(int *arr, int len);
void radixSort(int *arr, int len);



int main()
{
    int array[] = {1, 3, 4, 2, 1, 3, 5, 8, 9, 6};
    int len = sizeof(array)/sizeof(int);
    cout << "Before sorting:\n";
    std::copy(array, array+len, std::ostream_iterator<int>(cout, "\t"));
    cout << '\n';

    //bubbleSort(array, len);
    //selectSort(array, len);
    //quickSort(array, 0, len-1);
    //mergeSort(array, 0, len-1);
    //insertSort(array, len);
    //shellSort(array, len);
    //heapSort(array, len);
    radixSort(array, len);

    cout << "After sorting:\n";
    std::copy(array, array+len, std::ostream_iterator<int>(cout, "\t"));
    cout << '\n';

}

void bubbleSort(int *arr, int len)
{
    bool flag = true;
    for(int i=0; i<len-1 && flag; i++) {
        flag = false;
        for(int j=0; j<len-i-1; j++) {
            if(arr[j]>arr[j+1]) {
                swap(arr[j], arr[j+1]);
                flag = true;
            }              
        }
    }
}


void selectSort(int *arr, int len)
{
    for(int i=0; i<len-1; i++) {
        int min = arr[i];
        int index = i;
        for(int j=i+1; j<len; j++) {
            if(min>arr[j]) {
                min = arr[j];
                index = j;
            }              
        }
        if(index != i) {
            swap(arr[i], arr[index]);
        }
    }
}

void quickSort(int *arr, int start, int end)
{
    int i = start;
    int j = end;
    int key = arr[i];
    while(i<j) {
        while(i<j && arr[j]>=key) j--;
            arr[i] = arr[j];
        while(i<j && arr[i]<=key) i++;
            arr[j] = arr[i];
    }//找到 key對應的支點位置
    arr[i] = key;
    //遞歸調用, 注意遞歸調用條件,去除支點
    if(i-1 >start) quickSort(arr, start, i-1);
    if(i+1 < end) quickSort(arr, i+1, end);
}

void mergeSort(int *arr, int start, int end)
{
    if(start < end) {
        int mid = start + (end-start)/2;
        mergeSort(arr, start, mid);
        mergeSort(arr, mid+1 , end);
        mergeSort2(arr, start, mid, end);
    }
}

void mergeSort2(int *arr, int start, int mid, int end)
{
    int ls = mid-start+1;
    int rs = end-mid;
    int *left = new int[ls];
    int *right = new int[rs];

    int i=0, j=0, k=start;
    while(i<ls) left[i++] = arr[k++];
    while(j<rs) right[j++] = arr[k++];

    i=0; 
    j=0; 
    k=start;
    while(i<ls && j<rs) {
        arr[k++] = (left[i]>right[j]) ? (right[j++]) : (left[i++]);

    }

    while(i<ls) arr[k++] = left[i++];
    while(j<rs) arr[k++] = right[j++];

    delete[] left;
    delete[] right;
}

void insertSort(int *arr, int len)
{
    for(int i=1; i<len; i++) {
        int tmp = arr[i];
        int j=i;
        while(j>0 && arr[j-1]>tmp) {
            arr[j] = arr[j-1]; 
            j--;
        }
        arr[j] = tmp;
    }
}

void shellSort(int *arr, int len)
{
    for(int gap=len/2; gap>=1; gap/=2) {
        for(int i=gap; i<len; i++) {
            for(int j=i-gap; j>=0; j-=gap) {
                if(arr[j]>arr[j+gap])
                    swap(arr[j], arr[j+gap]);
            }
        }
    }
}

void heapSort(int *arr, int len)
{
    //建立大根堆
    for(int i=len/2-1; i>=0; i--)
        heapSort2(arr, i, len);

    for(int i=len-1; i>0; i--) {
        swap(arr[0], arr[i]);//獲得根節點值
        heapSort2(arr, 0, i);//以剩餘元素新建大根堆
    }
}

void heapSort2(int *arr, int idx, int len)
{
    int left = 2*idx + 1;
    int right = left + 1;
    int max = idx;
    if(left<len && arr[left]>arr[max]) max = left;
    if(right<len && arr[right] > arr[max]) max = right;
    if(max != idx) {
        swap(arr[idx], arr[max]);
        heapSort2(arr, max, len);
    }
}

int GetLoopCnt(int *arr, int len)
{
    int n=1, tmp = 10;
    for(int i=0; i<len; i++) {
        int absval = abs(arr[i]);
        while( absval > tmp ) {
            ++n;
            tmp*=10;
        }
    }
    return n;
}

void radixSort(int *arr, int len)
{
    int n = GetLoopCnt(arr, len);
    const int radixCnt = 19;
    const int base = 10;
    int radix = 1;

    int* num = new int[len];
    int* tmp = new int[len];

    for(int i=0; i<n; ++i) {
        int count[radixCnt] = {0};
        int j=0;
        for (; j<len; ++j) {
            num[j] = 9 + (arr[j]/radix)%10;
            ++count[num[j]];
        }

        for(j=1; j<radixCnt; ++j) {
            count[j] += count[j-1];
        }

        for(j=len-1; j>=0; j--) {
            tmp[--count[num[j]]] = arr[j]; //不懂你在幹什麼
        }

        for(j=0; j<len; j++) 
            arr[j] = tmp[j];

        radix *= base;
    }

    delete[] num;
    delete[] tmp;
}

PS: 基數排序平均時間複雜度:O(logR B),最壞時間複雜度::O(logR B).
另外時間複雜度與初始排序無關的算法包括: 選擇排序, 堆排序, 歸併排序和基數排序.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章