牛客IOI周賽22-普及組 簽訂協議(c++)
故事背景
假如本次考試,本學校有100個學生,對於每個學生我們記錄了他的分數,現在你需要將同學們的分數,按照從高到低排名
思路excel地址:https://docs.qq.com/sheet/DU0doeGJIcmxtdUxT
那麼該如何做呢,一種辦法是,遍歷整個資料,然後吧分數最高的加入到一個新的列表中
依次這樣做,我們可以得到一個有序列表
從計算機的角度看待一個這個問題
O(n)時間意味著檢視列表中的每個元素一次。例如,對學生列表進行簡單查詢時,意味著每個學生都要檢視一次
要找出分數最高的學生,必須檢查列表中的每個元素。正如你剛才看到的,這需要的時間為O(n)。因此對於這種時間為O(n)的操作,你需要執行n次
需要檢查的元素數越來越少
隨著排序的進行,每次需要檢查的元素數在逐漸減少,最後一次需要檢查的元素都只有一個。既然如此,執行時間怎麼還是O(n2)呢?這個問題問得好,這與大O表示法中的常數相關。
後面將詳細解釋,這裡只簡單地說一說。
你說得沒錯,並非每次都需要檢查n個元素。第一次需要檢查n個元素,但隨後檢查的元素數依次為n 1, n – 2, …, 2和1。平均每次檢查的元素數為1/2 × n,因此執行時間為O(n × 1/2 × n)。
但大O表示法省略諸如1/2這樣的常數(有關這方面的完整討論,後面我會接著討論),因此簡單地寫作O(n × n)或O(n^2)。
選擇排序是一種靈巧的演算法,但其速度不是很快。快速排序是一種更快的排序演算法,其執行時間為O(n log n),這將在後面介紹
選擇排序(Selection sort)是一種簡單直觀的排序演算法。它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。
選擇排序的主要優點與資料移動有關。如果某個元素位於正確的最終位置上,則它不會被移動。選擇排序每次交換一對元素,它們當中至少有一個將被移到其最終位置上,因此對 n 個元素的表進行排序總共進行至多 n -1 次交換。在所有的完全依靠交換去移動元素的排序方法中,選擇排序屬於非常好的一種
下述程式碼提供了類似的功能:將陣列元素按從小到大的順序排列。先編寫一個用於找出陣列中最小元素的函式
C 語言演示
def findSmallest(arr):
smallest = arr[0]
smallest_index = 0
for i in range(1, len(arr)):
if arr[i] < smallest:
smallest = arr[i]
smallest_index = i
return smallest_index
// 現在可以使用這個函式來編寫選擇排序演算法了。
def selectionSort(arr):
newArr = []
for i in range(len(arr)):
smallest = findSmallest(arr)
newArr.append(arr.pop(smallest))
return newArr
// 進行測試
print selectionSort([5, 3, 6, 2, 10])
PHP 語言演示
<?php
$arr = array(5, 8, 6, 7, 3);
// 選擇排序演算法實現
function SelectSort($arr = array()) {
//獲取陣列長度
$size = sizeof($arr);
//外層迴圈控制比較的數值下標與輪詢次數
for ($i=0; $i<$size; $i++) {
// 先假設最小值的位置
$p=$i;
//內層迴圈控制比較次數
for ($j=$i+1; $j<$size; $j++) {
// 如果 j 下標的值比 p 小標的值小
if ($arr[$p] > $arr[$j]) {
//記錄最小值的下標
$p = $j;
}
}
// 不相同則互換位置
if ($p != $i){
$tmp = $arr[$i];
$arr[$i] = $arr[$p];
$arr[$p] = $tmp;
}
}
return $arr;
}
// 測試執行
print_r(SelectSort($arr));