LinkedList 和 List 在三种简单算法中效率比较

本文通过实验对比了.Net框架中的List与LinkedList在不同场景下的性能表现。结果显示,在队列算法中,LinkedList更适合长度较长的队列;而在堆栈及简单插入场景下,List表现出更高的效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        .Net 框架提供了两种List类型,一种是基于链表的LinkedList, 一种是基于数组的List。那么在实际应用中到底采用哪种List,如何取舍呢?本文对两种类型在队列,堆栈和简单插入三种简单算法中的效率进行了一个比较。

  首先先让我们来看一下List的初始容量Capacity对List的性能是否有影响。

  测试方法:分别设置初始容量为0,64,255,1024. List插入的最大长度为1000,循环1000次,得到如下结果,单位为ms,下同。

算法/初始容量0642551024
队列35837357533717135711
堆栈302279298289
简单插入100105100100

  从上面数据中我们可以看出List的初始容量对效率没有明显影响。

  队列算法比较

  测试方法:对LinkedList和List采用先进先出的队列算法,分别设置队列最大长度为10,30,50,100,1000,10000,并循环1000次,得到如下结果。

List类型/队列最大长度103050100100010000
LinkedList0.76590.87681.10412.040161691
List0.33261.16771.99851244337516

  从测试结果中我们可以看出LinkedList 随着最大队列长度的增加,所用时间基本成线性增长。而List则成指数增长。我分析主要原因应该是每次删除List的数组头时,List都要做一次整个数数组的拷贝,而链表类型则不存在这个问题。有趣的是当队列长度小于30时,List的效率要比LinkedList要高,这主要是因为链表在增删元素时需要额外创建链表指针,而数组不需要这个操作。在队列长度较小时,这种开销就会显得很明显。

  堆栈算法比较

  测试方法:对LinkedList和List采用先进后出的堆栈算法,分别设置队列最大长度为10,30,50,100,1000,10000,并循环1000次,得到如下结果。

List类型/堆栈最大长度103050100100010000
LinkedList0.85150.92951.11232.187458714
List0.11090.31040.51181.225629284

  从测试结果看两种类型都是线性增长,但List的性能更高一些。我分析这主要是因为List类型在增长到最大值后在从尾部删除元素,其并不重新分配内存,除非你强行让它压缩。所以List从尾部删除只是将Count改变了一下,因此效率很高。而链表类型的效率和队列方式基本相当,这也是在预料之中的,其效率比List低的原因主要还是在增删时创建和删除节点的额外开销。

  简单插入算法比较

  测试方法:对LinkedList和List采用向后追加若干元素的算法,分别设置插入最大长度为10,30,50,100,1000,10000,并循环1000次,得到如下结果。

List类型/插入最大长度103050100100010000
LinkedList0.67780.7650.9381.778340535
List0.08640.16610.25090.431210109

  其测试结果和堆栈算法基本类似,且List的效率更高,这里不再重复论述。

  总结

  如果采用队列算法建议采用LinkedList类型,除非队列长度小于30.

  如果采用堆栈或简单插入算法,建议采用List类型。但有一点需要说明,如果应用对内存占用有限制,建议采用LinkedList类型。

  测试代码

  

  1. class Program
  2.   {
  3.     const int TEST_TIMES = 1000;
  4.     static private void TestQueue(int count)
  5.     {
  6.       TestQueue(count, 0);
  7.     }
  8.     static private void TestQueue(int count, int capacity)
  9.     {
  10.       Console.WriteLine("Count:" + count.ToString());
  11.       LinkedList<int> linkList = new LinkedList<int>();
  12.       List<int> list = new List<int>(capacity);
  13.       Stopwatch watch = new Stopwatch();
  14.       watch.Start();
  15.       for (int i = 0; i < TEST_TIMES; i++)
  16.       {
  17.         for (int j = 0; j < count; j++)
  18.         {
  19.           linkList.AddLast(j);
  20.         }
  21.         for (int j = 0; j < count; j++)
  22.         {
  23.           int test = linkList.First.Value;
  24.           linkList.RemoveFirst();
  25.         }
  26.       }
  27.       watch.Stop();
  28.       String duration;
  29.       if (watch.ElapsedMilliseconds < 10)
  30.       {
  31.         duration = (((double)watch.ElapsedTicks) / 10000).ToString() + "ms";
  32.       }
  33.       else
  34.       {
  35.         duration = watch.ElapsedMilliseconds.ToString() + "ms";
  36.       }
  37.       Console.WriteLine("LinkedList:" + duration);
  38.       watch.Reset();
  39.       watch.Start();
  40.       for (int i = 0; i < TEST_TIMES; i++)
  41.       {
  42.         for (int j = 0; j < count; j++)
  43.         {
  44.           list.Add(j);
  45.         }
  46.         for (int j = 0; j < count; j++)
  47.         {
  48.           int test = list[0];
  49.           list.RemoveAt(0);
  50.         }
  51.       }
  52.       if (watch.ElapsedMilliseconds < 10)
  53.       {
  54.         duration = (((double)watch.ElapsedTicks) / 10000).ToString() + "ms";
  55.       }
  56.       else
  57.       {
  58.         duration = watch.ElapsedMilliseconds.ToString() + "ms";
  59.       }
  60.       Console.WriteLine("List:" + duration);
  61.     }
  62.     static private void TestStack(int count)
  63.     {
  64.       TestStack(count, 0);
  65.     }
  66.     static private void TestStack(int count, int capacity)
  67.     {
  68.       Console.WriteLine("Count:" + count.ToString());
  69.       LinkedList<int> linkList = new LinkedList<int>();
  70.       List<int> list = new List<int>(capacity);
  71.       Stopwatch watch = new Stopwatch();
  72.       watch.Start();
  73.       for (int i = 0; i < TEST_TIMES; i++)
  74.       {
  75.         for (int j = 0; j < count; j++)
  76.         {
  77.           linkList.AddLast(j);
  78.         }
  79.         for (int j = 0; j < count; j++)
  80.         {
  81.           int test = linkList.Last.Value;
  82.           linkList.RemoveLast();
  83.         }
  84.       }
  85.       watch.Stop();
  86.       String duration;
  87.       if (watch.ElapsedMilliseconds < 10)
  88.       {
  89.         duration = (((double)watch.ElapsedTicks) / 10000).ToString() + "ms";
  90.       }
  91.       else
  92.       {
  93.         duration = watch.ElapsedMilliseconds.ToString() + "ms";
  94.       }
  95.       Console.WriteLine("LinkedList:" + duration);
  96.       watch.Reset();
  97.       watch.Start();
  98.       for (int i = 0; i < TEST_TIMES; i++)
  99.       {
  100.         for (int j = 0; j < count; j++)
  101.         {
  102.           list.Add(j);
  103.         }
  104.         for (int j = 0; j < count; j++)
  105.         {
  106.           int test = list[list.Count-1];
  107.           list.RemoveAt(list.Count - 1);
  108.         }
  109.       }
  110.       if (watch.ElapsedMilliseconds < 10)
  111.       {
  112.         duration = (((double)watch.ElapsedTicks) / 10000).ToString() + "ms";
  113.       }
  114.       else
  115.       {
  116.         duration = watch.ElapsedMilliseconds.ToString() + "ms";
  117.       }
  118.       Console.WriteLine("List:" + duration);
  119.     }
  120.     static private void TestInsert(int count)
  121.     {
  122.       TestInsert(count, 0);
  123.     }
  124.     static private void TestInsert(int count, int capacity)
  125.     {
  126.       Console.WriteLine("Count:" + count.ToString());
  127.       LinkedList<int> linkList = new LinkedList<int>();
  128.       List<int> list = new List<int>(capacity);
  129.       Stopwatch watch = new Stopwatch();
  130.       watch.Start();
  131.       for (int i = 0; i < TEST_TIMES; i++)
  132.       {
  133.         for (int j = 0; j < count; j++)
  134.         {
  135.           linkList.AddLast(j);
  136.         }
  137.         linkList.Clear();
  138.       }
  139.       watch.Stop();
  140.       String duration;
  141.       if (watch.ElapsedMilliseconds < 10)
  142.       {
  143.         duration = (((double)watch.ElapsedTicks) / 10000).ToString() + "ms";
  144.       }
  145.       else
  146.       {
  147.         duration = watch.ElapsedMilliseconds.ToString() + "ms";
  148.       }
  149.       Console.WriteLine("LinkedList:" + duration);
  150.       watch.Reset();
  151.       watch.Start();
  152.       for (int i = 0; i < TEST_TIMES; i++)
  153.       {
  154.         for (int j = 0; j < count; j++)
  155.         {
  156.           list.Add(j);
  157.         }
  158.         list.Clear();
  159.       }
  160.       if (watch.ElapsedMilliseconds < 10)
  161.       {
  162.         duration = (((double)watch.ElapsedTicks) / 10000).ToString() + "ms";
  163.       }
  164.       else
  165.       {
  166.         duration = watch.ElapsedMilliseconds.ToString() + "ms";
  167.       }
  168.       Console.WriteLine("List:" + duration);
  169.     }
  170.     static void Main(string[] args)
  171.     {
  172.       //capacity
  173.       TestQueue(10000, 0);
  174.       TestQueue(10000, 64);
  175.       TestQueue(10000, 255);
  176.       TestQueue(10000, 1024);
  177.       TestStack(10000, 0);
  178.       TestStack(10000, 64);
  179.       TestStack(10000, 255);
  180.       TestStack(10000, 1024);
  181.       TestInsert(10000, 0);
  182.       TestInsert(10000, 64);
  183.       TestInsert(10000, 255);
  184.       TestInsert(10000, 1024);
  185.       //compare LinkedList and List
  186.       TestQueue(10);
  187.       TestQueue(30);
  188.       TestQueue(50);
  189.       TestQueue(100);
  190.       TestQueue(1000);
  191.       TestQueue(10000);
  192.       TestStack(10);
  193.       TestStack(30);
  194.       TestStack(50);
  195.       TestStack(100);
  196.       TestStack(1000);
  197.       TestStack(10000);
  198.       TestInsert(10);
  199.       TestInsert(30);
  200.       TestInsert(50);
  201.       TestInsert(100);
  202.       TestInsert(1000);
  203.       TestInsert(10000);
  204.     }
  205.   }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值