成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

數(shù)據(jù)結(jié)構(gòu)與算法的重溫之旅(三)——數(shù)組

jsliang / 2593人閱讀

摘要:整個程序在存入是數(shù)據(jù)大于數(shù)組長度的時候才會發(fā)生數(shù)組的刪除操作。數(shù)組作為非?;A(chǔ)的數(shù)據(jù)結(jié)構(gòu),通過下標(biāo)隨機訪問數(shù)組元素又是其非常基礎(chǔ)的編程操作,效率的優(yōu)化就要盡可能做到極致。

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

一、前言

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

二、數(shù)組概念

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

1.線性表

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

2.連續(xù)的內(nèi)存空間和相同類型的數(shù)據(jù)

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

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

三、數(shù)組的插入和刪除

上面提到數(shù)組由于連續(xù)的內(nèi)存空間導(dǎo)致了在執(zhí)行插入和刪除操作的時候占用大量的性能。首先我們來說一下插入操作在數(shù)組的執(zhí)行過程。

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

如果一個數(shù)組是有序的,我們?yōu)榱吮3謹(jǐn)?shù)組的有序性,的確只能用上述的方法來解。但是如果數(shù)組是無序的,為了避免大規(guī)模的數(shù)據(jù)移動,我們可以把當(dāng)前下標(biāo)m的數(shù)據(jù)放到最后面,把我們的值放入到下標(biāo)m當(dāng)中。利用這個方法我們可以將時間復(fù)雜度降到O(1),性能將極大的提升。

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

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

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("數(shù)組越界")
            return
        }
    }
    arr[count] = {
        value: obj.value,
        removeSign: false,
        index: count
    }
    count++
}
function removeArr(index){
    if (arr.length === 0) {
        console.error("數(shù)組長度為0,不能刪除元素")
        return
    }
    else if (index > arr.length) {
        console.error("數(shù)組越界")
        return
    }
    // 如果當(dāng)前的已標(biāo)記為true則查看下一個元素是否為true,如果不是則標(biāo)記為true,是的話則繼續(xù)遞歸
    if (arr[index].removeSign) {
        return removeArr(++index)
    }
    arr[index].removeSign = true
}
閱讀需要支付1元查看
<