神的規範 排序演算法(二) 簡單選擇排序

2021-07-06 11:35:13 字數 2701 閱讀 3404

寫在前面:

排序又稱為分類,它是資料處理中經常用到的一種重要運算。

雖然並未列入世界最偉大的幾大演算法之一,但毫無疑問,在各行各業的各個時期排序都是作為奠基者般的存在為程式所呼叫,也為程式設計者所敬仰。只是,也許正是因為它與我們息息相關,以至於我們竟然時常忽略它的存在。

事實上我們生活中無時無刻不在做排序:考試成績排名,按身高、年齡、能力高低去評判他人,劃分任務處理的優先順序,等等·······

為簡單起見,我們採用順序儲存的結構存放所排序的資料元素序列。

雖然簡單選擇排序與簡單插入排序都是「簡單的排序」,但是我們好奇的是:它們的思想和實現有什麼區別呢?

我們已經知道,所謂簡單插入排序,就是將所有待排序元素分為有序無序兩個部分,每次取出無序部分的第乙個元素,通過資料比較,插入到有序序列的合適位置,依次類推直到所有資料有序,它是乙個穩定的演算法。

而簡單選擇排序,重在「選擇」二字,怎麼個選法呢?

大家試想一下公司(比如谷歌)是如何選擇招聘優秀員工的?

在一群(無序的)應聘者中,首先把表現最好(排序碼最小)的員工挑出來(形成有序部分的第乙個元素),然後在剩下的所有員工中再選出表現最後的(放入到有序部分的第二個位置),以此類推直到選出所有公司需要的職員。

相信這一流程非常容易理解,因為它很符合人類的思維(但有缺點,缺點後面詳述)。

我們將簡單選擇排序的思想規範化描述一下:第一趟排序是在無序的中按排序碼選出最小的元素,將它與r1交換;第二趟排序是在無序的中選出最小的元素,將它與r2交換;而第i趟排序時已排好序,在當前無序的中再選出最小的元素,將它與ri交換,使有序。值得注意的是,i-1趟排序後,整個資料元素就是遞增有序的(為什麼?)

我們可以給出乙個簡單選擇排序的c語言描述(假設待排序元素為double型資料):

void selectsort1(double a,int n) 

}a[i] = small; //it is the ith smallest element}}

以上**經測試(此處略)實現了遞增排序,但是我們注意到有乙個問題:它可能要多次交換資料,即a[j]與small,而它並沒有對我們的排序結果(根據這一排序演算法)做出實際貢獻。這勢必會導致整體執行效率的低下。那麼有沒有改良的方案呢?

有。我們考慮不移動資料,只把排序碼做個變化,**如下:

void selectsort2(double a,int n) 

if (i != small) }}

這樣一來,交換資料的動作在最壞情況下也就只需n-1個,大大減少了交換所需的開銷。

簡單評估一下簡單選擇排序:

函式selectsort中外層for迴圈需執行n-1次,而對於找出排序碼最小的資料元素的內層for迴圈,最壞情況下需要執行n-i次資料比較,因此簡單選擇排序最壞情況下需要執行n-1+n-2+…1 = n(n-1)/2次比較,演算法效率為o[n^2](注意,與簡單插入排序效率等級相同)。

如此一來,我們有了乙個疑問,乙個是簡單選擇排序,乙個是簡單插入排序,這兩種「簡單排序」誰更快呢?

有人會想,應該是一樣快吧,畢竟演算法效率都一樣。

非也非也,是騾子是馬,牽出來遛遛。我們用**進行測試(包括針對第一種不完善的簡單選擇排序的測試),測試**如下:

#include "stdio.h"

#include "stdlib.h"

#include "time.h"

void print(double a,int n);

void selectsort1(double a,int n);

void selectsort2(double a,int n);

void insertsort(double a,int n);

#define num 20000

int main(int argc, char* argv)

void print(double a,int n)

printf("\n");

}void selectsort1(double a,int n)

}a[i] = small; //it is the ith smallest element

}}void selectsort2(double a,int n)

if (i != small)

}}void insertsort(double a,int n)

a[j+1] = temp; //insert element temp}}

測試大量(**中是20000,可更改)資料的結果如下圖(不妨多測幾次,排除干擾):

三次測試中,我們發現:對於相同的資料樣本,簡單插入排序的效果每次都好於簡單選擇排序。這說明,實際上簡單插入排序演算法平均效率最高(而不是最壞情況下效率最高,我們有理由相信,最壞情況下簡單選擇排序與簡單插入排序演算法效率相等或相近)。

至於為什麼,乙個直覺的答案是:簡單插入排序是穩定的,而簡單選擇排序則不穩定(為什麼?)。

to be continued…

排序演算法(二)簡單選擇排序

一 介紹 1 氣泡排序的基本思想就是不斷地比較 交換,通過交換完成最終的排序 而相比氣泡排序來說,選擇排序法的基本思想是在排序時找到合適的關鍵字再做交換,且只移動一次就完成相應關鍵字的排序定位,也就是說每一趟在n i 1 i 1,2.n 1 個記錄中選取關鍵字最小的記錄作為有序序列的第i個記錄。二 ...

排序演算法 選擇排序 簡單選擇排序

package 選擇排序 簡單選擇排序 不穩定 基本思想 在要排序的一組數中,選出最小的乙個數與第乙個位置的數交換 然後在剩下的數當中再找最小的與第二個位置的數交換,如此迴圈到倒數第二個數和最後乙個數比較為止。public class 簡單選擇排序 system.out.println 排序之前 f...

排序演算法 簡單選擇排序

簡單選擇排序是一種選擇排序。1.簡單選擇排序的定義 每趟從待排序的記錄中選出關鍵字最小的記錄,順序放在已排序的記錄序列末尾,直到全部排序結束為止。2.簡單選擇排序的流程 例項 注 紅色數字是位置發生變化的數值。3.簡單選擇排序的 實現 public class selectsort 若min有變化,...