選擇排序

基本思想:

在要排序的一組數(shù)中,選出最小(或者最大)的一個(gè)數(shù)與第1個(gè)位置的數(shù)交換;然后在剩下的數(shù)當(dāng)中再找最小(或者最大)的與第2個(gè)位置的數(shù)交換,依次類推,直到第n-1個(gè)元素(倒數(shù)第二個(gè)數(shù))和第n個(gè)元素(最后一個(gè)數(shù))比較為止。

簡單選擇排序示例

初始值: 3  1  5  7  2  4  9  6
第一趟: 1  3  5  7  2  4  9  6
第二趟: 1  2  5  7  3  4  9  6
第三趟: 1  2  3  7  5  4  9  6
第四趟: 1  2  3  4  5  7  9  6
第五趟: 1  2  3  4  5  7  9  6
第六趟: 1  2  3  4  5  6  9  7
第七趟: 1  2  3  4  5  6  7  9
第八趟: 1  2  3  4  5  6  7  9

操作方法:

第一趟,從n 個(gè)記錄中找出關(guān)鍵碼最小的記錄與第一個(gè)記錄交換;

第二趟,從第二個(gè)記錄開始的n-1 個(gè)記錄中再選出關(guān)鍵碼最小的記錄與第二個(gè)記錄交換;

......

第 i 趟,則從第 i 個(gè)記錄開始的 n-i+1 個(gè)記錄中選出關(guān)鍵碼最小的記錄與第 i 個(gè)記錄交換,直到整個(gè)序列按關(guān)鍵碼有序。

算法的實(shí)現(xiàn):

// 輸出數(shù)組內(nèi)容
void print(int array[], int length, int i) {
    printf("i=%d:",i);
    for (int j = 0; j < length; j++) {
        printf(" %d ", array[j]);
    }
    printf("\n");
}

// 獲取數(shù)組最小值下標(biāo)
int SelectMinKey(int array[], int length, int i) {
    int k = i;
    for (int j = i + 1; j < length; j ++) {
        if (array[k] > array[j]) {
            k = j;
        }
    }
    return k;
}

// 簡單選擇排序(Simple Selection Sort)
void SelectSort(int array[], int length) {
    int key, temp;
    for (int i = 0; i < length; i ++) {
        key = SelectMinKey(array, length, i); // 獲取最小元素的下標(biāo)
        if (key != i) { // 最小元素與第i位置元素交換
            temp = array[i];
            array[i] = array[key];
            array[key] = temp;
        }
        print(array, length, i);
    }
}

int main(int argc, const char * argv[]) {
    int arraySelectSort[8] = { 3, 1, 5, 7, 2, 4, 9, 6 };
    SelectSort(arraySelectSort, 8);
    printf("\n");

    return 0;
}

算法的改進(jìn)(二元選擇排序)

簡單選擇排序,每趟循環(huán)只能確定一個(gè)元素排序后的定位。我們可以考慮改進(jìn)為每趟循環(huán)確定兩個(gè)元素(當(dāng)前趟最大和最小記錄)的位置,從而減少排序所需的循環(huán)次數(shù)。改進(jìn)后對n個(gè)數(shù)據(jù)進(jìn)行排序,最多只需進(jìn)行[n/2]趟循環(huán)即可。具體實(shí)現(xiàn)如下:

// 二元選擇排序
void SelectSort2(int array[], int length) {
    int i, j, min, max;
    for (i = 0; i < length / 2; i ++) { // i 跑 n / 2 趟排序就會(huì)排序完成
        min = max = i; // 先將 min 和 max 都指向待排序的第一個(gè)元素
        for(j = i; j < length - i; j ++) {
            if (array[j] < array[min]) {
                min = j;
                continue;
            }
            if (array[j] > array[max]) {
                max = j;
            }
        }

        // 將最小值放在第i處,將最大值放在第length-i-1處
        // 注意:這里不能把 array[max]、array[min] 直接和 array[i] 和 array[length-i-1]調(diào)換
        int maxtemp = array[max];
        int mintemp = array[min];
        array[max] = array[length-i-1];
        array[min] = array[i];
        array[i] = mintemp;
        array[length-i-1] = maxtemp;

        print(array, 8, i);
    }
}

總結(jié)

在簡單選擇排序過程中,所需移動(dòng)記錄的次數(shù)比較少。最好情況下,即待排序記錄初始狀態(tài)就已經(jīng)是正序排列了,則不需要移動(dòng)記錄。

最壞情況下,即待排序記錄初始狀態(tài)是按第一條記錄最大,之后的記錄從小到大順序排列,則需要移動(dòng)記錄的次數(shù)最多為3(n-1)。簡單選擇排序過程中需要進(jìn)行的比較次數(shù)與初始狀態(tài)下待排序的記錄序列的排列情況無關(guān)。當(dāng)i=1時(shí),需進(jìn)行n-1次比較;當(dāng)i=2時(shí),需進(jìn)行n-2次比較;依次類推,共需要進(jìn)行的比較次數(shù)是(n-1)+(n-2)+…+2+1=n(n-1)/2,即進(jìn)行比較操作的時(shí)間復(fù)雜度為O(n^2),進(jìn)行移動(dòng)操作的時(shí)間復(fù)雜度為O(n)。

簡單選擇排序是不穩(wěn)定排序。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容