日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【萌味】小夕说,不了解动态空间增长的程序喵都是假喵(中)

發(fā)布時(shí)間:2024/7/5 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【萌味】小夕说,不了解动态空间增长的程序喵都是假喵(中) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

親愛的小屋客人,昨天小夕將小屋的討論室重新裝修啦!希望您會喜歡哦~除了口令[d],現(xiàn)在也可以通過主頁下方的“喵了個(gè)咪”進(jìn)入討論室啦。

ps:昨天小夕裝修討論室的時(shí)候發(fā)生了N次差點(diǎn)吐血的事件,明天小夕與大家含淚分享T_T。

在上一篇文章中,小夕為大家講解了鏈表與遞增式擴(kuò)容的姿勢,而這一篇,將會是本系列文章的高潮哦(不!要!污!)

源于數(shù)組

上篇文章中,小夕為了避免大家理解起來抽象,讓大家注意了幾個(gè)數(shù)據(jù)結(jié)構(gòu):

如果您是C++程序喵,那么請注意一下Vector數(shù)據(jù)結(jié)構(gòu);如果是Java程序喵,請注意一下ArrayList、LinkedList、哈希系列(HashSet/ HashTable/ HashMap);如果是不用Java也不用C++的程序喵,或者是已經(jīng)脫離XX編程語言層次的程序喵,那么請注意一下可變數(shù)組(可增長順序表)、鏈表、哈希(散列)。

上篇文章中小夕講解了基于鏈表實(shí)現(xiàn)的數(shù)據(jù)結(jié)構(gòu)都是遞增式擴(kuò)容最優(yōu)。那么對于C++中的Vector,Java中的ArrayList、HashSet/ HashTable/ HashMap,也就是數(shù)據(jù)結(jié)構(gòu)中的可變數(shù)組、哈希來說,空間增長方式是怎樣呢?可能有可愛的讀者寶寶此時(shí)在想“天吶,這些數(shù)據(jù)結(jié)構(gòu)又特喵的不一樣,怎么放到一起討論了呢?”好啦,讓小夕碾壓這些讀者寶寶吧(小夕再次跑路)!其實(shí)這些表面看似不同的東西,底層的實(shí)現(xiàn)方式確是一樣的,它們在底層都是通過操縱靜態(tài)數(shù)組來實(shí)現(xiàn)他們的動(dòng)態(tài)空間增長功能,下文會詳細(xì)介紹哦。

講到這里,可能愛思考的讀者寶寶會記得小夕在上一篇中也提到過哈希,說哈希的橫向增長是基于鏈表的,因此遞增式擴(kuò)容是最優(yōu)動(dòng)態(tài)空間增長方案。那這一篇中又說哈希是基于靜態(tài)數(shù)組的,這是怎么回事呢?下面給沒有接觸過哈希的讀者寶寶先科普一下哈希:

哈希的橫向增長是基于鏈表實(shí)現(xiàn)的,即當(dāng)新元素的哈希值與已有元素哈希值相同時(shí),新元素會插入到某個(gè)鏈表中,因此是遞增式增長。但是更多的情況下,哈希是縱向增長的。學(xué)過數(shù)據(jù)結(jié)構(gòu)的寶寶知道,哈希在縱向上就是一個(gè)指針數(shù)組,數(shù)組的每個(gè)索引值即代表一個(gè)哈希值,數(shù)組的每個(gè)元素是一個(gè)指向某鏈表的指針。畫個(gè)圖來看就是這樣的。

所以,在本篇文章中,我們不看哈希的橫向增長啦,就看豎著的,也就是縱向增長,此時(shí)顯然是基于靜態(tài)數(shù)組實(shí)現(xiàn)的哦。

下面小夕直接以“數(shù)據(jù)結(jié)構(gòu)”代稱所有這些基于靜態(tài)數(shù)組實(shí)現(xiàn)的動(dòng)態(tài)空間分配的數(shù)據(jù)結(jié)構(gòu),包括但不限于C++中的Vector(即數(shù)據(jù)結(jié)構(gòu)中的動(dòng)態(tài)數(shù)組),Java中的ArrayList(即動(dòng)態(tài)數(shù)組)、Hash系列(即哈希/散列)等~

具體來說,如何用靜態(tài)數(shù)組實(shí)現(xiàn)上述的動(dòng)態(tài)空間增長的數(shù)據(jù)結(jié)構(gòu)呢?其實(shí)很簡單,每次數(shù)據(jù)結(jié)構(gòu)要擴(kuò)容時(shí)只需要依次進(jìn)行下述操作就完成啦:

  • 開辟一段新的內(nèi)存空間,空間大小就是擴(kuò)容后的數(shù)據(jù)結(jié)構(gòu)大小。

  • 把舊數(shù)據(jù)結(jié)構(gòu),也就是舊的內(nèi)存空間的元素一個(gè)個(gè)的復(fù)制到新的內(nèi)存空間

  • 釋放舊的內(nèi)存空間(代碼上就是刪除舊空間的指針,當(dāng)然像Java這種自動(dòng)管理內(nèi)存的語言就不用程序喵操心這一步了)

  • 通過上述擴(kuò)容的三步操作,可以看到每次哈希表的擴(kuò)容操作的代價(jià)還是挺大的。第1步和第3步的代價(jià)不算大,但是第2步的代價(jià)會隨著要搬移元素?cái)?shù)量的增加而直線上升。所以這就相當(dāng)于一個(gè)完整搬家的過程:先買個(gè)新房子,再把舊房子里的全部家當(dāng)搬到新房子里去,再把舊房子注銷,你說麻不麻煩喵= ̄ω ̄=

    加倍式擴(kuò)容

    既然代價(jià)如此之大,那么顯然我們要盡量減小擴(kuò)容次數(shù)呀~每次擴(kuò)容都是大出血...怎么擴(kuò)呢?一個(gè)很creative的想法就是每次使數(shù)據(jù)結(jié)構(gòu)變?yōu)樽陨淼膬杀?#xff01;再機(jī)智一點(diǎn),每次使數(shù)據(jù)結(jié)構(gòu)變?yōu)樽陨淼腘倍!其中N只要大于1就可以!這種每次使自身的大小變?yōu)橹癗倍的數(shù)據(jù)結(jié)構(gòu)動(dòng)態(tài)空間增長方式稱為【加倍式擴(kuò)容】。實(shí)際上,基于靜態(tài)數(shù)組的數(shù)據(jù)結(jié)構(gòu)的動(dòng)態(tài)空間增長問題上加倍式擴(kuò)容遠(yuǎn)遠(yuǎn)優(yōu)于遞增式擴(kuò)容口說無憑,待小夕用萌味算法分析來證明!

    假如數(shù)據(jù)結(jié)構(gòu)A使用【遞增式擴(kuò)容】。每次數(shù)據(jù)結(jié)構(gòu)滿了的時(shí)候就固定的增加10個(gè)單位的空間(增加單位的數(shù)量不會影響最終分析出來的復(fù)雜度哦)。好,那小夕現(xiàn)在手里有n個(gè)元素想添加進(jìn)數(shù)據(jù)結(jié)構(gòu),假如n的數(shù)值很大,遠(yuǎn)遠(yuǎn)的大于10,那么要執(zhí)行多少次擴(kuò)容操作呢?當(dāng)然是n/10次啦~這n/10次擴(kuò)容的累計(jì)開銷大約為cost=10+2*10+3*10+…+(n/10)*10,計(jì)算一下這個(gè)級數(shù),就是cost=[(n/10)/2]*[(n/10)+1]*10,所以復(fù)雜度是O(n2)的數(shù)量級,所以平均每個(gè)元素被添加進(jìn)哈希表時(shí)的開銷為cost/n,也就是O(n)的復(fù)雜度。

    ?

    假如數(shù)據(jù)結(jié)構(gòu)B使用【加倍式擴(kuò)容】。每次數(shù)據(jù)結(jié)構(gòu)滿了的時(shí)候,數(shù)據(jù)結(jié)構(gòu)的大小就變成原來的2倍(與之前同樣的,這個(gè)倍數(shù)取不同的值并不會影響最終分析出來的復(fù)雜度哦~當(dāng)然倍數(shù)必須大于1!)。同樣,小夕將n個(gè)元素添加進(jìn)數(shù)據(jù)結(jié)構(gòu),假如n的數(shù)值很大,遠(yuǎn)遠(yuǎn)的大于2,那么要執(zhí)行的擴(kuò)容操作的次數(shù)是…小夕去算一會...嗯…應(yīng)該是log2n!令c=log2n,則這c次擴(kuò)容操作的累計(jì)開銷為cost=21+22+…+2c。這個(gè)級數(shù)的和為cost=[2/(1-2)]*(1-2c),代入c=log2n得cost=2(n-1)。也就是說復(fù)雜度為O(n),所以平均每個(gè)元素被添加進(jìn)哈希表時(shí)的開銷為cost/n,也就是O(1)的復(fù)雜度!注意前面我們計(jì)算過,這里數(shù)據(jù)結(jié)構(gòu)A(遞增式擴(kuò)容)的復(fù)雜度為O(n)!

    怎么樣~小夕說的沒錯(cuò)吧,讀者寶寶有沒有撥開云彩見到日呢( ̄? ̄)。所以說呀,正是因?yàn)檫@類數(shù)據(jù)結(jié)構(gòu)采用了加倍式擴(kuò)容,導(dǎo)致這類數(shù)據(jù)結(jié)構(gòu)申請內(nèi)存的時(shí)候翻倍翻倍的要。結(jié)果當(dāng)時(shí)在那個(gè)機(jī)器學(xué)習(xí)任務(wù)中,小夕算的是一個(gè)超大哈希表只需要占用5個(gè)G作右的內(nèi)存空間,而實(shí)際上在往這個(gè)哈希表加數(shù)據(jù)時(shí),從4個(gè)G直接爆到了接近8個(gè)G,導(dǎo)致小夕內(nèi)存8G的小電腦直接崩盤了~

    等等,看似此文可以結(jié)了,實(shí)際上,敏銳的讀者寶寶可能想到了,“遞增式擴(kuò)容你都告訴我了每次擴(kuò)容增加一個(gè)單位的空間就最優(yōu)了,那加倍式擴(kuò)容每次增大幾倍最優(yōu)呢?”如果讀者寶寶能發(fā)現(xiàn)這一點(diǎn)的話,真的非常棒啦!答案是2倍嗎?當(dāng)然不!那是幾呢?下篇萌貨(萌味干貨的簡稱)見分曉( ̄? ̄)。

    啊啊,高潮果然是最累的(我說文章的高潮啊喂~),小夕好累喵(′Д` )。所以親愛的讀者寶寶是不是有一種抑制不住要鼓勵(lì)小夕的沖動(dòng)吖(?????????)

    小夕已委托維權(quán)騎士對小夕發(fā)布文章的版權(quán)行為進(jìn)行追究與維權(quán)。如需轉(zhuǎn)載,請聯(lián)系微信xiyaomengmengda。

    總結(jié)

    以上是生活随笔為你收集整理的【萌味】小夕说,不了解动态空间增长的程序喵都是假喵(中)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。