標籤:
簡單概念
在c#中,List是順序線性表(非鏈表),用一組地址連續的儲存單元依次儲存資料元素的線性結構。
雜湊表也叫散列表,是一種通過把關鍵碼值對應到表中一個位置來訪問記錄的資料結構。c#中的雜湊表有Hashtable,Dictionary,Hashtable繼承自Map,實現一個key-value映射的關係。Dictionary則是一種泛型雜湊表,不同於Hashtable的key無序,Dictionary是按照順序儲存的。雜湊表的特點是:1.尋找速度快,2.不能有重複的key。
建立過程
在c#中,我們執行個體化list時,如果不指定容量,則內部會產生一個靜態空數組,有添加操作時,執行個體化為一個長度為4的數組,滿了以後,自動擴充為兩倍的容量。
雜湊表也是類似的情況,先預設產生一個長度為11的雜湊表,滿後,自動添加,而添加規則是內部迴圈素數數組,稍大於當前的長度,比如15 ,則長度設定為17。在雜湊表建立可分為確定雜湊函數,解決雜湊衝突兩個步驟。
實驗執行結果
下面進行兩個實驗,實驗一,比較Hashtable,Dictionary,List三者在不同長度時的建立速度,實驗二比較三者在不同時間時的尋找速度。(實驗代碼在最後)
硬體:intel core 2 quad cpu @ 2.66GHZ,4GB記憶體。
軟體:windows 2008,2010 VS編譯環境。
表1.三者的建立時間
長度\類型 |
Hashtable |
Dictionary |
List |
1 |
0.001s |
0s |
0s |
10 |
0S |
0S |
0s |
100 |
0S |
0S |
0s |
1000 |
0.003s |
0.005s |
0.001s |
10000 |
0.0032s |
0.003s |
0.002s |
100000 |
0.038s |
0.042s |
0.002s |
1000000 |
0.520s |
0.512s |
0.015s |
3000000 |
1.807s |
1.441s |
0.042s |
6000000 |
3.752s |
2.952s |
0.087s |
8000000 |
4.744s |
3.740s |
0.102s |
表2.三者的尋找時間
長度\類型 |
Hashtable |
Dictionary |
List |
1 |
0s |
0s |
0s |
10 |
0s |
0s |
0s |
100 |
0s |
0s |
0s |
1000 |
0s |
0s |
0s |
10000 |
0s |
0s |
0.001s |
100000 |
0s |
0s |
0.010s |
1000000 |
0s |
0s |
0.009s |
3000000 |
0s |
0s |
0.009s |
6000000 |
0s |
0s |
0.058s |
8000000 |
0s |
0s |
0.077s |
總結
實驗一表明:雜湊表比list需要花費更多的時間建立資料結構,這是因為雜湊表花費時間去解決雜湊衝突,而list不需要。但需要注意的是建立操作只需要執行一次。
實驗二表明:雜湊表的尋找速度幾乎不需要花費時間,這是因為雜湊表在添加一對元素(key-value)時,就已經記錄下value的位置,所以尋找時就會非常的快。雜湊的尋找複雜度O(1),list 的尋找複雜度是O(n)。
雜湊表的高速尋找是空間換時間的典型應用,前期的建立時間隨著數量級的增加而增加,後期的尋找則永遠是O(1)。所以我們得出結論:如果面對海量資料,且需要大量搜尋,那建議使用雜湊表。而當面對小量資料(數量級由伺服器決定)時,使用List更合適。
最後友情提醒:第一,雖然在尋找上雜湊佔有優勢,但不足的是1.佔有空間大,2.不能有重複健。第二,如果需要使用雜湊表,建議多使用Dictionary。Dictionary的已耗用時間比hashtable稍快,而且Dictionary是型別安全的,這有助於我們寫出更健壯更具可讀性的代碼,省去我們強制轉化的麻煩。Dictionary是泛型的,當K或V是實值型別時,其速度遠遠超過Hashtable。
- /*
- *Author: chao
- *Date:2012.3.27
- *Fun: Compare list with hash in c#
- */
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Collections;
- namespace hash_vs_list
- {
- class Program
- {
-
- const int MAX = 50000;
- static void Main(string[] args)
- {
- //hash_table
- Console.WriteLine("hash_table");
- TimeSpan hash_start = new TimeSpan(DateTime.Now.Ticks); //開始時間
- Hashtable h1 = new Hashtable();
- for (int i = 0; i < MAX; i++)
- h1.Add(i, i.ToString());
- TimeSpan hash_end = new TimeSpan(DateTime.Now.Ticks); //結束時間
- TimeSpan hash_diff = hash_start.Subtract(hash_end).Duration();// 計算時間差
- string hash_create_diff = hash_diff.TotalSeconds.ToString(); //
-
- //hashtable search
- hash_start = new TimeSpan(DateTime.Now.Ticks);
- string tmp = h1[0].ToString();
- hash_end = new TimeSpan(DateTime.Now.Ticks);
- hash_diff = hash_start.Subtract(hash_end).Duration();
- string hash_search_diff = hash_diff.TotalSeconds.ToString();
-
- Console.WriteLine("create:{0} search:{1}", hash_create_diff, hash_search_diff);
- Console.WriteLine();
-
-
-
-
- //dict
- Console.WriteLine("dictionary");
- Dictionary<int, string> dict = new Dictionary<int, string>();
- TimeSpan dict_start = new TimeSpan(DateTime.Now.Ticks);
- for (int i = 0; i < MAX; i++)
- {
- dict.Add(i, i.ToString());
- }
- TimeSpan dict_end = new TimeSpan(DateTime.Now.Ticks);
- TimeSpan dict_diff = dict_start.Subtract(dict_end).Duration();
- string dict_create_diff = dict_diff.TotalSeconds.ToString();
-
- //dict search
- dict_start = new TimeSpan(DateTime.Now.Ticks);
- tmp = dict[0];
- dict_end = new TimeSpan(DateTime.Now.Ticks);
- dict_diff = dict_start.Subtract(dict_end).Duration();
- string dict_search_diff = dict_diff.TotalSeconds.ToString();
- Console.WriteLine("create:{0} search:{1}", dict_create_diff, dict_search_diff);
- Console.WriteLine();
-
-
-
- //list create
- Console.WriteLine("list");
- TimeSpan list_start = new TimeSpan(DateTime.Now.Ticks);
- List<int> l1 = new List<int>();
- for (int i = 0; i < MAX; i++)
- l1.Add(i);
- TimeSpan list_end = new TimeSpan(DateTime.Now.Ticks);
- TimeSpan list_diff = list_start.Subtract(list_end).Duration();
- string list_create_diff = list_diff.TotalSeconds.ToString();
-
-
- //list foreach
- list_start = new TimeSpan(DateTime.Now.Ticks);
- foreach (int i in l1)
- {
- if (i == MAX)
- break;
- }
- list_end = new TimeSpan(DateTime.Now.Ticks);
- list_diff = list_start.Subtract(list_end).Duration();
- string list_foreach_diff = list_diff.TotalSeconds.ToString();
- Console.WriteLine("create:{0},foreach:{1}", list_create_diff, list_foreach_diff);
- Console.WriteLine();
-
-
- Console.Read();
- }
- }
- }
C#中雜湊表與List的比較