1. 程式人生 > >【演算法初探】陣列、連結串列與選擇排序

【演算法初探】陣列、連結串列與選擇排序

前端也要懂演算法,閱《演算法圖解》有所得。

一、陣列與連結串列

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;
}