冒泡排序
原理:用第一項與第二項進行比較,若第一項大於第二項則將其交換順序,然後用交換後的第一項與第三項進行比較,直到第一項後面的所有數字都比它小,所以第一項爲所有數字中的最小項,然後再用第二項與後面的數字進行比較
for(var i=0;i < array.length;i++){
for(var j = i + 1;j < array.length;j++){
if(array[i] > array[j]){
var tmp = array[i];
array [i] = array[j];
array[j] = tmp;
}
}
}
時間複雜度:O(n^2)
選擇排序
原理:假定數組中的第一項爲最小值,然後進行比較,若第二項比第一項小,則把第二項作爲最小值,依次類推
function swap(items, firstIndex, secondIndex){
var temp = items[firstIndex];
items[firstIndex] = items[secondIndex];
items[secondIndex] = temp;
};
function selectionSort(){
let items = [...document.querySelectorAll('.num-queue span')].map(num => +num.textContent);
let len = items.length, min;
for (i = 0; i < len; i++){
min = i;
for(j = i + 1; j < len; j++){
if(items[j] < items[min]){
min = j;
}
}
if(i != min){
swap(items, i, min);
}
}
return items;
};
時間複雜度: O(n^2)
插入排序
與上述兩種排序算法不同, 插入排序是穩定排序算法(stable sort algorithm), 穩定排序算法指不改變列表中相同元素的位置, 冒泡排序和選擇排序不是穩定排序算法, 因爲排序過程中有可能會改變相同元素位置. 對簡單的值(數字或字符串)排序時, 相同元素位置改變與否影響不是很大. 而當列表中的元素是對象, 根據對象的某個屬性對列表進行排序時, 使用穩定排序算法就很有必要了.
一旦算法包含交換(swap)這個步驟, 不是穩定的排序算法. 列表內元素不斷交換, 無法保證先前的元素排列爲止一直保持原樣. 而插入排序的實現過程不包含交換, 而是提取某個元素將其插入數組中正確位置.
原理:將一個數組分爲兩部分,一部分排序完成,一部分未進行排序,初始狀態下整個數組屬於未排序部分,排序完成部分爲空,然後進行排序,數組內的第一項被加入排序完成部分,由於只有一項,自然輸入排序完成狀態,然後對未完成排序的部分元素進行如下操作:
1. 如果這一項的值應該在排序完成部分最後一項元素之後,則保留這一項在原有位置
2. 如果這一項的值應該在排序完成部分最後一項之前,將這一項從未完成部分暫時移開,將已完成部分的最後一項元素移後一個位置
3. 被暫時移開的元素與已完成部分倒數第二個元素進行比較
4. 如果被移除元素的值在最後一項與倒數第二項的值之間,那麼將其插入兩者之間的位置,否則繼續與前面的元素進行比較,將暫移出的元素放置已完成部分合適位置,依次類推所有元素均被放入排序完成部分
function insertionSort(items) {
let len = items.length, value, i, j;
for (i = 0; i < len; i++) {
value = items[i];
for (j = i-1; j > -1 && items[j] > value; j--) {
items[j+1] = items[j];
}
items[j+1] = value;
}
return items;
};
外層循環的遍歷順序是從數組的第一位到最後一位, 內層循環的遍歷則是從後往前, 內層循環同時負責元素的移位.
插入排序的時間複雜度爲O(n^2)
以上三種排序算法都十分低效, 因此實際應用中不要使用這三種算法, 遇到需要排序的問題, 應該首先使用JavaScript內置的方法Array.prototype.sort();
參考:三種基礎的排序算法