程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 帶你看懂Dictionary的內部實現,看懂dictionary實現

帶你看懂Dictionary的內部實現,看懂dictionary實現

編輯:C#入門知識

帶你看懂Dictionary的內部實現,看懂dictionary實現


 

了解Dictionary的開發人員都了解,和List相比,字典添加會慢,但是查找會比較快,那麼Dictionary是如何實現的呢?

Dictionary的構造

下面的代碼我看看Dictionary在構造時都做了什麼:

        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<TKey, TValue>[prime];
            this.freeList = -1;
        } 

 

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

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

我們以Dictionary<int,string> 為例,來展示一下Dictionary如何添加元素:

首先,我們構造一個:

Dictionary<int, string> test = new Dictionary<int, string>(6);

初始化後:

添加元素時,集合內部Bucket和entries的變化

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在添加,刪除元素按照如下方法進行:

 

好吧,熬了半宿,今天先寫到這了,如果看了有所收獲就幫忙頂一下,有問題歡迎拍磚。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved