国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

數據結構與算法的重溫之旅(三)——數組

jsliang / 2588人閱讀

摘要:整個程序在存入是數據大于數組長度的時候才會發生數組的刪除操作。數組作為非?;A的數據結構,通過下標隨機訪問數組元素又是其非常基礎的編程操作,效率的優化就要盡可能做到極致。

本系列所有文章的代碼都是用JavaScript實現,之所以用JavaScript實現是因為它可以直接在瀏覽器宿主中運行代碼,即在瀏覽器中按f12打開控制臺,選擇console按鈕,在下面空白的文本框把本例的代碼黏貼上去回車即可運行。方便各位同學學習和調試。

一、前言

數組這個概念相信各位同學在日常寫代碼的時候肯定會經常用到,我們通常用數組作為容器來存儲數據?;旧厦恳环N編程語言都有這種數據結構,它是一個基礎的數據結構,下面將仔細的講解數組的原理及應用。

二、數組概念

什么是數組呢?按照專業的名詞解釋,數組是一種線性表數據結構,它用連續的內存空間來存儲一組具有相同類型的數據。從定義里我們可以看到幾個關鍵詞,分別是線性表(Linear List)和連續的內存空間和相同類型的數據。

1.線性表

線性表的意思其實就是數據排成像一條線一樣的結構。每個線性表上的數據最多只有前和后兩個方向。其實除了數組,鏈表、隊列、棧等都是線性表結構。而與線性表對立的則是非線性表 ,比如二叉樹、圖、堆等。之所以叫非線性,是因為非線性表中的數據并不是簡單的前后關系。

2.連續的內存空間和相同類型的數據

當我們聲明一個數組的時候,計算機就會為數組分配一個連續的內存空間。假如我們聲明的數組長度是10,在數組中存儲的元素都說int類型的數據,如果內存的首地址為1000,則計算機為數組分配了1000~1039的連續內存空間。數組和鏈表不同的一點就是數組存儲的都是連續的內存空間,而鏈表存儲的都說不連續的內存空間,所以如果一個計算機的內存只有1G的情況下,我們聲明了一個占用1G內存的數組很有可能會導致內存溢出,因為有可能內存里有不連續的空間,而聲明1G內存的鏈表則不會出現這種情況。

結合上面所說的兩點,數組由于是線性的并且是連續的內存空間,隨機訪問的時候時間復雜度非常的快,為O(1)。數組的隨機訪問并不需要遍歷本身,只需要知道下標就可以得出值。但是有利也有弊,與快速的查詢相反的就是在插入和刪除的時候所要耗費更多的復雜度。在這里需要提一點的是,數組是隨機查找的時候時間復雜度為O(1),不能籠統的認為數組在執行查找操作的時候時間復雜度為O(1),如果你用二分查找來對數組進行查找操作,耗費的時間復雜度為O(logn)。

三、數組的插入和刪除

上面提到數組由于連續的內存空間導致了在執行插入和刪除操作的時候占用大量的性能。首先我們來說一下插入操作在數組的執行過程。

假設我們聲明了一個數組長度為n,如果我們要插入的數組在數組第m個位置的時候,為了能夠讓數據成功的插入下標m當中,我們要把m到n這一部分的數據往后移一位,然后把數據放入下標m當中。那如果數據是要插入到數組最后面的話,那時間復雜度也只是O(1),如果是在開頭插入的話時間復雜度則為O(n),因為每個位置的概率都是一樣的,所以我們可以得到平均時間復雜度為:。

如果一個數組是有序的,我們為了保持數組的有序性,的確只能用上述的方法來解。但是如果數組是無序的,為了避免大規模的數據移動,我們可以把當前下標m的數據放到最后面,把我們的值放入到下標m當中。利用這個方法我們可以將時間復雜度降到O(1),性能將極大的提升。

同理在刪除中,如果我們要刪除下標為m的元素,為了內存的連續性,也需要把m到n后面的數據往前移,不然就不連續。刪除的最好時間復雜度是O(1),即刪除的是結尾的數據的時候。最壞時間復雜度則為O(n),即在開頭的數據被刪除。它的平均時間復雜度的公式也和上面插入的公式一樣,結果為O(n)。

那么如果我們對數組進行頻繁的刪除操作,程序的性能將會極大的降低,有時候辦法可以解決呢?這個時候我們可以借助JVM標記清除垃圾回收算法來實現。當執行刪除操作的時候我們并不是真的把數組里的元素給刪除掉,而是給該元素標記一個刪除狀態,等到后面數組沒有更多的空間存儲數組的時候再一次性的執行刪除操作,極大地減少數據的遷移。下面用JavaScript代碼來簡單的實現一下:

var arr = new Array(10)
var count = 0
function insertArr(obj) {
    if (typeof arr[9] === "object") {
        var tempArr = []
        for (var a = 0; a < arr.length; a++) {
            if (!arr[a].removeSign) {
                arr[a].index = tempArr.length
                arr[a].removeSign = false
                tempArr.push(arr[a])
            }
        }
        arr = tempArr
        count = tempArr.length
        if (arr.length === 10) {
            console.error("數組越界")
            return
        }
    }
    arr[count] = {
        value: obj.value,
        removeSign: false,
        index: count
    }
    count++
}
function removeArr(index){
    if (arr.length === 0) {
        console.error("數組長度為0,不能刪除元素")
        return
    }
    else if (index > arr.length) {
        console.error("數組越界")
        return
    }
    // 如果當前的已標記為true則查看下一個元素是否為true,如果不是則標記為true,是的話則繼續遞歸
    if (arr[index].removeSign) {
        return removeArr(++index)
    }
    arr[index].removeSign = true
}
閱讀需要支付1元查看
<