• C#中哈希表与List的比较


    简单概念

    在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。

    1. /* 
    2.  *Author: chao 
    3.  *Date:2012.3.27 
    4.  *Fun: Compare list with hash in c# 
    5.  */  
    6. using System;  
    7. using System.Collections.Generic;  
    8. using System.Linq;  
    9. using System.Text;  
    10. using System.Collections;  
    11. namespace hash_vs_list  
    12. {  
    13.     class Program  
    14.     {  
    15.   
    16.         const int MAX = 50000;  
    17.         static void Main(string[] args)  
    18.         {  
    19.             //hash_table   
    20.             Console.WriteLine("hash_table");  
    21.             TimeSpan hash_start = new TimeSpan(DateTime.Now.Ticks);  //开始时间   
    22.             Hashtable h1 = new Hashtable();  
    23.             for (int i = 0; i < MAX; i++)  
    24.                 h1.Add(i, i.ToString());  
    25.             TimeSpan hash_end = new TimeSpan(DateTime.Now.Ticks);  //结束时间   
    26.             TimeSpan hash_diff = hash_start.Subtract(hash_end).Duration();//  计算时间差   
    27.             string hash_create_diff = hash_diff.TotalSeconds.ToString();   //     
    28.   
    29.             //hashtable search   
    30.             hash_start = new TimeSpan(DateTime.Now.Ticks);  
    31.             string tmp = h1[0].ToString();  
    32.             hash_end = new TimeSpan(DateTime.Now.Ticks);  
    33.             hash_diff = hash_start.Subtract(hash_end).Duration();  
    34.             string hash_search_diff = hash_diff.TotalSeconds.ToString();  
    35.   
    36.             Console.WriteLine("create:{0} search:{1}", hash_create_diff, hash_search_diff);  
    37.             Console.WriteLine();  
    38.   
    39.   
    40.   
    41.   
    42.             //dict   
    43.             Console.WriteLine("dictionary");  
    44.             Dictionary<intstring> dict = new Dictionary<intstring>();  
    45.             TimeSpan dict_start = new TimeSpan(DateTime.Now.Ticks);  
    46.             for (int i = 0; i < MAX; i++)  
    47.             {  
    48.                 dict.Add(i, i.ToString());  
    49.             }  
    50.             TimeSpan dict_end = new TimeSpan(DateTime.Now.Ticks);  
    51.             TimeSpan dict_diff = dict_start.Subtract(dict_end).Duration();  
    52.             string dict_create_diff = dict_diff.TotalSeconds.ToString();  
    53.               
    54.             //dict search   
    55.             dict_start = new TimeSpan(DateTime.Now.Ticks);  
    56.             tmp = dict[0];  
    57.             dict_end = new TimeSpan(DateTime.Now.Ticks);  
    58.             dict_diff = dict_start.Subtract(dict_end).Duration();  
    59.             string dict_search_diff = dict_diff.TotalSeconds.ToString();  
    60.             Console.WriteLine("create:{0} search:{1}", dict_create_diff, dict_search_diff);  
    61.             Console.WriteLine();  
    62.   
    63.   
    64.   
    65.             //list create   
    66.             Console.WriteLine("list");  
    67.             TimeSpan list_start = new TimeSpan(DateTime.Now.Ticks);  
    68.             List<int> l1 = new List<int>();  
    69.             for (int i = 0; i < MAX; i++)  
    70.                 l1.Add(i);  
    71.             TimeSpan list_end = new TimeSpan(DateTime.Now.Ticks);  
    72.             TimeSpan list_diff = list_start.Subtract(list_end).Duration();  
    73.             string list_create_diff = list_diff.TotalSeconds.ToString();  
    74.   
    75.   
    76.             //list foreach   
    77.             list_start = new TimeSpan(DateTime.Now.Ticks);  
    78.             foreach (int i in l1)  
    79.             {  
    80.                 if (i == MAX)  
    81.                     break;  
    82.             }  
    83.             list_end = new TimeSpan(DateTime.Now.Ticks);  
    84.             list_diff = list_start.Subtract(list_end).Duration();  
    85.             string list_foreach_diff = list_diff.TotalSeconds.ToString();  
    86.             Console.WriteLine("create:{0},foreach:{1}", list_create_diff, list_foreach_diff);  
    87.             Console.WriteLine();  
    88.   
    89.   
    90.             Console.Read();  
    91.         }  
    92.     }  
    93. }  
  • 相关阅读:
    QT中的定时器使用
    range()函数常和len()函数一起用于字符串索引。在这里我们要显示每一个元素及其索引值。
    range()的print 《P核》P30
    2.13 带逗号的print语句输出的元素之间自动带个空格
    Python3.x和Python2.x的区别
    print语句默认每行添加一个换行符 来自2.13
    2.12 while循环 print与计数器先后顺序对结果的影响
    函数本地绑定与全局绑定的区别
    字典映射{ :}
    《Python核心编程》P21输入数值字符串→转整型
  • 原文地址:https://www.cnblogs.com/hjtdlx/p/3361374.html
Copyright © 2020-2023  润新知