代碼來自ILSpy分析結果,與實際代碼可能有些微出入。手寫版http://min.us/mqjnYB
從下面可以看到,LinkedList是雙向鏈表,但是SortedList實際上使用的還是數組。
而SortedDictionary與SortedSet關係非常緊密。
----------------------------------------------------------
----------------------------------------------------------
LinkedList<T> 通過雙向鏈表這種資料結構實現。
關鍵資料成員:LinkedListNode head;
很顯然這是鏈表的頭。每個Node會有Previous以及Next這樣的property。
Find()功能通過遍曆List實現,所以是O( n )
----------------------------------------------------------
----------------------------------------------------------
Queue<T> 先進先出的隊列。
關鍵資料成員: T[] _array; 毫無疑問,是通過數組來存放資料。
_tail; _head; _size;
有頭有尾有大小,基本就是這樣。
關鍵操作Enqueue()入隊列 Dequeue()出隊列。
----------------------------------------------------------
----------------------------------------------------------
SortedDictionary<T> 索引值對字典資料類型,介面是IDictionary<TKey, TValue>。
內部關鍵資料成員TreeSet< KeyValuePair<TKey, TValue> > _set;
而TreeSet繼承了SortedSet,操作基本上都是通過類似這樣:第一個值使用Key,第二個值使用Default(TValue)
構造產生,然後調用_set的相關操作。
----------------------------------------------------------
----------------------------------------------------------
SortedList<T> 排序列表
TKey[] keys;
TKey[] values;
_size;
Add(),通過Array.BinarySearch<TKey>找到索引位置,然後進行插入操作。O(log n)。
----------------------------------------------------------
----------------------------------------------------------
另外要說一下,這裡面的比較都是使用了IComparer,這實際上使用了設計模式中的策略模式,讓使用者可以自己定製。預設情況下是使用Comparer<T>.Default.
----------------------------------------------------------
----------------------------------------------------------
SortedSet<T>
關鍵資料成員:SortedSet<T>.Node root;
插入操作為AddIfNotPresent()這個函數名字已經說明了一切。
內部構造使用的資料結構為紅/黑樹狀結構(一種自平衡二叉搜尋樹),有IsBlack和IsRed,以及Left、Right這些property。
搜尋、插入、刪除都是O(log n)。
----------------------------------------------------------
另外要注意其中的Reverse()函數,使用了yield return xxx;以及yield break;這兩種用法。
----------------------------------------------------------
----------------------------------------------------------
Stack<T>
T[] _array; 後進先出,沒啥可說的。
----------------------------------------------------------
HashSet<T>
關鍵資料成員:
int[] m_buckets;
HashSet<T>.Slot[] m_slots;
----------------------------------------------------------
Slot的定義如下:
internal struct Slot
{
internal int hashCode;
internal T value;
internal int next;
}
搜尋或者是插入演算法基本上是這個路子:
----------------------------------------------------------
int num = this.InternalGetHashCode(value);
for (int i
= this.m_buckets[num % this.m_buckets.Length] - 1; i >= 0; i
= this.m_slots[i].next)
{
//if (this.m_slots[i].hashCode ==
num && this.m_comparer.Equals(this.m_slots[i].value, value))
…
}
----------------------------------------------------------
這裡是搜尋,先算出一個雜湊值,然後判斷在那個桶中,拿到桶裡面第一個元素(this.m_slots[i])。
然後通過next這個成員變數來擷取下一個索引位置,然後對hash代碼以及通過comparer比較。
(圖片來自http://en.wikipedia.org/wiki/Hash_table)
----------------------------------------------------------
插入操作也差不多,在這裡面有一個this.m_freeList(一個int整數)儲存了空閑列表位置,
然後把要插入的元素放在這個列表位置,再把m_freelist設定為這個列表位置的next。
因為空白間可能不是連續的,所以我們使用的m_freelist這個位置與next未必是緊挨著的關係。
這個空閑列表的next關係維護,是由IncreaseCapacity()函數完成。其實C語言中的malloc函數也可以這樣簡單實現(當然實際中malloc肯定是複雜的多得多得多)。
----------------------------------------------------------
----------------------------------------------------------
ILSpy是個好東西,最新版本在這裡下載http://www.ilspy.net/