【演算法初探】陣列、連結串列與選擇排序
前端也要懂演算法,閱《演算法圖解》有所得。
一、陣列與連結串列
1. 記憶體的原理:
相信我們經常會聽到“堆”、“棧”之類的字眼,那麼計算機的記憶體是什麼呢?當我們去游泳時,我們需要將東西存在保險櫃裡,可能東西比較多,一個放不下,這時候就需要申請2個保險櫃,再將東西放在櫃子裡,手裡拿著開櫃的鑰匙。
計算機的記憶體分配亦是如此,當我們需要使用記憶體時,我們需要申請空閒記憶體,再將資料存入申請的記憶體裡,最終得到存放資料的記憶體地址。如果我們需要訪問一個數據,只需要知道資料存放的地址,就能訪問。
2. 陣列與連結串列
陣列和連結串列是計算機最基礎的2種資料結構。假如我們需要將5個數據放入記憶體中,那麼計算機需要分給我們5個記憶體空間,那麼使用陣列和連結串列的區別是什麼呢?
1)陣列
如果使用陣列儲存,那麼我們需要計算機分配5個相鄰的記憶體空間,因為陣列的每個元素都是有序且相鄰的。此時,我們很容易發現,如果我需要往數組裡插入一個元素,那麼我們可能會面臨如下困境:
- 相鄰的記憶體被其他資料佔用了。
- 計算機剩餘的相鄰記憶體長度不足以放下陣列
如果使用連結串列來儲存,以上問題將會迎刃而解。
2)連結串列
同樣,以連結串列的形式儲存5個元素,每個元素都記錄著下一個元素的地址,那麼只需要知道一個元素,就能得到整個連結串列,而不需要每個元素都相鄰。
這樣我們插入一個新元素,只需要改變上一個元素記錄的地址。
當然,事情不會這麼簡單,陣列與連結串列各有優劣。
3)優劣
上篇文章介紹了大O計數法表示一個演算法的速度,那麼我們來看看陣列與連結串列插入、刪除、和查詢一個元素的速度:
陣列 連結串列
查詢 O(1) O(n)
插入 O(n) O(1)
刪除 O(n) O(1)
顯而意見,陣列在查詢操作上的效能較高,因為陣列的每個元素都是相鄰的,從而支援隨機查詢,即如果知道了第一個元素,那麼第4個元素的位置也能猜到。相反,連結串列儲存的資料則需要從頭開始查詢,因為只有前一個元素才知道後一個元素的位置。
同理: 對於插入和刪除, 連結串列只需要修改上一個元素的地址,而陣列如果插入的資料是中間的,則需要對後面所有的元素進行補位。
由此,很容易得出結論:
- 陣列比較適合查詢多,增刪少的場景
- 連結串列多用於增刪頻繁而不需要經常查詢的資料儲存。
二、選擇排序
1. 原理
選擇排序的思想是,如果有一組資料需要從大到小排序,那麼先找出最大的,移除,再在剩下的數中找第二大的,依次類推。其演算法速度:O(n^2)
2. js實現
function selectionSort(myArray){
var len = myArray.length,
min;
for (i = 0; i < len; i++){
// 將當前位置設為最小值
min = i;
// 檢查陣列其餘部分是否更小
for (j = i+1; j < len; j++){
if (myArray[j] < myArray[min]){
min = j;
}
}
// 如果當前位置不是最小值,將其換為最小值
if (i != min){
swap(myArray, i, min);
}
}
return myArray;
}
function swap(myArray, p1, p2){
var temp = myArray[p1];
myArray[p1] = myArray[p2];
myArray[p2] = temp;
}