帶你看懂Dictionary的內部實現

2021-08-22 11:29:32 字數 2813 閱讀 5352

了解dictionary的開發人員都了解,和list相比,字典新增會慢,但是查詢會比較快,那麼dictionary是如何實現的呢?

下面的**我看看dictionary在構造時都做了什麼:

c#private void initialize(int capacity)

int prime = hashhelpers.getprime(capacity);

this.buckets = new int[prime];

for (int i = 0; i < this.buckets.length; i++)

this.buckets[i] = -1;

this.entries = new entry[prime];

this.freelist = -1;

我們看到,dictionary在構造的時候做了以下幾件事:

初始化乙個this.buckets = new int[prime]

初始化乙個this.entries = new entry[prime]

bucket和entries的容量都為大於字典容量的乙個最小的質數

其中this.buckets主要用來進行hash碰撞,this.entries用來儲存字典的內容,並且標識下乙個元素的位置。

我們以dictionary為例,來展示一下dictionary如何新增元素:

首先,我們構造乙個:

(檢視大圖)

test.add(4,」4″)後:

根據hash演算法: 4.gethashcode()%7= 4,因此碰撞到buckets中下標為4的槽上,此時由於count為0,因此元素放在entries中第0個元素上,新增後count變為1

(檢視大圖)

test.add(11,」11″)

根據hash演算法 11.gethashcode()%7=4,因此再次碰撞到buckets中下標為4的槽上,由於此槽上的值已經不為-1,此時count=1,因此把這個新加的元素放到entries中下標為1的陣列中,並且讓buckets槽指向下標為1的entries中,下標為1的entry之下下標為0的entries。

(檢視大圖)

test.add(18,」18″)

我們新增18,讓hashcode再次碰撞到buckets中下標為4的槽上,這個時候新元素新增到count+1的位置,並且bucket槽指向新元素,新元素的next指向entries中下標為1的元素。此時你會發現所有hashcode相同的元素都形成了乙個鍊錶,如果元素碰撞次數越多,鍊錶越長。所花費的時間也相對較多。

(檢視大圖)

test.add(19,」19″)

再次新增元素19,此時hash碰撞到另外乙個槽上,但是元素仍然新增到count+1的位置。

(檢視大圖)

test.remove(4)

我們刪除元素時,通過一次碰撞,並且沿著鍊錶尋找3次,找到key為4的元素所在的位置,刪除當前元素。並且把freelist的位置指向當前刪除元素的位置,freecount置為1

(檢視大圖)

test.remove(18)

刪除key為18的元素,仍然通過一次碰撞,並且沿著鍊錶尋找2次,找到當前元素,刪除當前元素,並且讓freelist指向當前元素,當前元素的next指向上乙個freelist元素。

此時你會發現freelist指向了乙個鍊錶,鍊錶裡面不包含任何元素,freecount表示不包含元素的鍊錶的長度。

(檢視大圖)

test.add(20,」20″)

再新增乙個元素,此時由於freelist鍊錶不為空,因此字典會優先新增到freelist鍊錶所指向的位置,新增後freecount減1,freelist鍊錶長度變為1

(檢視大圖)

通過以上試驗,我們可以發現dictionary在新增,刪除元素按照如下方法進行:

通過hash演算法來碰撞到指定的bucket上,碰撞到同乙個bucket槽上所有資料形成乙個單鏈表

預設情況entries槽中的資料按照新增順序排列

刪除的資料會形成乙個freelist的鍊錶,新增資料的時候,優先向freelist鍊錶中新增資料,freelist為空則按照count依次排列

字典查詢及其的效率取決於碰撞的次數,這也解釋了為什麼dictionary的查詢會很快。

一文帶你看懂資料庫的CRUD

ddl 運算元據庫 表 1.運算元據庫 crud c create 建立 建立資料庫 create database 資料庫名稱 建立資料庫,判斷不存在,再建立 create database if not exists 資料庫名稱 建立資料庫,並指定字符集 create database 資料庫名...

一文帶你看懂ES6中的Set,Map,Symbol

隨著2020年的帶來,js基本型別也增加到了7種,bigint這個玩意說起來也挺好理解的,再加上undefined,null,string,number,boolean,相對於引用型別,都是比較好明白的。哎等會,好像少了乙個,symbol這個es6新增的東西到底有啥用呢?es6前沒有實現集合和字典型...

10分鐘帶你看懂氣泡排序Yu選擇排序

你可以這樣理解 從小到大排序 存在10個不同大小的氣泡,由底至上地把較少的氣泡逐步地向上公升,這樣經過遍歷一次後,最小的氣泡就會被上公升到頂 下標為0 然後再從底至上地這樣公升,迴圈直至十個氣泡大小有序。在氣泡排序中,最重要的思想是兩兩比較,將兩者較少的公升上去 問題 設有一陣列,其大小為10個元素...