[算法相關]幾種常用的排序算法

1. 冒泡排序法

冒泡排序(Bubble Sort),是一種計算機科學領域的較簡單的排序算法。
它重複地走訪過要排序的元素列,依次比較兩個相鄰的元素,如果順序(如從大到小、首字母從從Z到A)錯誤就把他們交換過來。走訪元素的工作是重複地進行直到沒有相鄰元素需要交換,也就是說該元素列已經排序完成。
這個算法的名字由來是因爲越小的元素會經由交換慢慢“浮”到數列的頂端(升序或降序排列),就如同碳酸飲料中二氧化碳的氣泡最終會上浮到頂端一樣,故名“冒泡排序”。
冒泡排序的原理如下:
1.比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
2.對每一對相鄰元素做同樣的工作,從開始第一對到結尾的最後一對。在這一點,最後的元素應該會是最大的數。
3.針對所有的元素重複以上的步驟,除了最後一個。
4.持續每次對越來越少的元素重複上面的步驟,直到沒有任何一對數字需要比較。
例子:
C語言:

#include <stdio.h>

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

        if (isSorted) {
            break;
        }
    }
}

int main() {
    int arr[] = {1, 5, 1, 5, 3, 2, 2, 9, 8, 9};
    int i, len = sizeof(arr) / sizeof(arr[0]);

    printf("Before sort: ");
    for (i = 0; i < len; i++) {
        printf("%d  ", arr[i]);
    }
    printf("\n");

    bubbleSort(arr, len);

    printf("After  sort: ");
    for (i = 0; i < len; i++) {
        printf("%d  ", arr[i]);
    }
    printf("\n");
    return 0;
}

2. 選擇排序法

選擇排序法是一種不穩定的排序算法。它的工作原理是每一次從待排序的數據元素中選出最小(或最大)的一個元素,存放在序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。以此類推,直到全部待排序的數據元素排完。

選擇排序法的第一層循環從起始元素開始選到倒數第二個元素,主要是在每次進入的第二層循環之前,將外層循環的下標賦值給臨時變量,接下來的第二層循環中,如果發現有比這個最小位置處的元素更小的元素,則將那個更小的元素的下標賦給臨時變量,最後,在二層循環退出後,如果臨時變量改變,則說明,有比當前外層循環位置更小的元素,需要將這兩個元素交換。
例子:
C語言:

#include <stdio.h>

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

void selectSort2(int *arr, int len) {
    int i = 0, j = 0, tmp = 0;
    for (i = 0; i < len - 1; i++) {
        int min = i;
        for (j = i + 1; j < len; j++) {
            if (arr[j] < arr[min]) {
                min = j;
            }
        }

        tmp = arr[min];
        arr[min] = arr[i];
        arr[i] = tmp;
    }
}

int main() {
    int arr[] = {1, 5, 1, 5, 3, 2, 2, 9, 8, 9};
    int i, len = sizeof(arr) / sizeof(arr[0]);

    printf("Before sort: ");
    for (i = 0; i < len; i++) {
        printf("%d  ", arr[i]);
    }
    printf("\n");

    selectSort2(arr, len);

    printf("After  sort: ");
    for (i = 0; i < len; i++) {
        printf("%d  ", arr[i]);
    }
    printf("\n");
    return 0;
}

3.快速排序法

快速排序(Quicksort)是對冒泡排序的一種改進。
快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然後再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。
快速排序算法通過多次比較和交換來實現排序,其排序流程如下:
(1)首先設定一個分界值,通過該分界值將數組分成左右兩部分。
(2)將大於或等於分界值的數據集中到數組右邊,小於分界值的數據集中到數組的左邊。此時,左邊部分中各元素都小於或等於分界值,而右邊部分中各元素都大於或等於分界值。
(3)然後,左邊和右邊的數據可以獨立排序。對於左側的數組數據,又可以取一個分界值,將該部分數據分成左右兩部分,同樣在左邊放置較小值,右邊放置較大值。右側的數組數據也可以做類似處理。
(4)重複上述過程,可以看出,這是一個遞歸定義。通過遞歸將左側部分排好序後,再遞歸排好右側部分的順序。當左、右兩個部分各數據排序完成後,整個數組的排序也就完成了。
例子:
C語言:

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

void quickSort(int *arr, int len) {
    if (len < 2) {
        return;
    }

    int i = 0, num = arr[0];
    int *lessArr = malloc(len * sizeof(int));
    int *middleArr = malloc(len * sizeof(int));
    int *greatArr = malloc(len * sizeof(int));
    int lessArrLen = 0, greatArrLen = 0, middleArrLen = 0;

    for (i = 1; i < len; i++) {
        if (arr[i] < num) {
            lessArr[lessArrLen++] = arr[i];
        } else if (arr[i] > num) {
            greatArr[greatArrLen++] = arr[i];
        } else {
            middleArr[middleArrLen++] = arr[i];
        }
    }

    quickSort(lessArr, lessArrLen);
    quickSort(greatArr, greatArrLen);

    if (lessArrLen > 0) {
        memcpy(arr, lessArr, lessArrLen * sizeof(int));
    }
    arr[lessArrLen] = num;
    if (middleArr > 0)
        memcpy(arr + lessArrLen + 1, middleArr, middleArrLen * sizeof(int));
    if (greatArrLen > 0)
        memcpy(arr + lessArrLen + 1 + middleArrLen, greatArr, greatArrLen * sizeof(int));

    free(lessArr);
    free(greatArr);
}

void quickSort2(int *a, int left, int right) {
    if (left >= right)
        return;

    int key = a[left];
    int i = left;
    int j = right;

    //[i, j]範圍內快速查找
    while (i < j) {
        //從右向左找到一比key值小的值,放到key所在的位置,即i的位置
        while (i < j && a[j] >= key) {
            j--;
        }

        a[i] = a[j];

        //從左向右找到一比key值大的值,放到剛纔所查到的位置,即j的位置
        while (i < j && a[i] <= key) {
            i++;
        }

        a[j] = a[i];

     }

    //實現了比key值小的值在最左側,比key值大的值在最右側,key值在中央
    a[i] = key;
    quickSort2(a, left, i - 1);
    quickSort2(a, i + 1, right);
}

int main() {
    int arr[] = {1, 5, 1, 5, 3, 2, 2, 9, 8, 9};
    int i, len = sizeof(arr) / sizeof(arr[0]);

    printf("Before sort: ");
    for (i = 0; i < len; i++) {
        printf("%d  ", arr[i]);
    }
    printf("\n");

    //quickSort(arr, len);
    quickSort2(arr, 0, len - 1);

    printf("After  sort: ");
    for (i = 0; i < len; i++) {
        printf("%d  ", arr[i]);
    }
    printf("\n");
    return 0;
}
發佈了40 篇原創文章 · 獲贊 8 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章