簡體   English   中英

如何添加一個LinkedList<T> 到鏈表<T>在 C# 中?

[英]How does one add a LinkedList<T> to a LinkedList<T> in C#?

人們會認為簡單的代碼

llist1.Last.Next = llist2.First;
llist2.First.Previous = llist1.Last;

會起作用,但顯然在 C# 的 LinkedList、First、Last 中,並且它們的屬性僅為 Get。

我能想到的另一種方法是

llist1.AddLast(llist2.First);

但是,這也不起作用——它失敗了,因為 llist2 的第一個節點已經在一個鏈表中。

這是否意味着我必須有一個循環將 llist2 的每個節點手動 AddLast 到 llist1? 這不會破壞鏈表的效率嗎????

是的,不幸的是,您必須循環。 這是一個 O(n) 操作 - 對於添加的每個條目 O(1)。 沒有需要調整緩沖區大小和復制等的風險 - 盡管垃圾收集當然可能會做粗略的 :) 您甚至可以編寫方便的擴展方法:

public static class LinkedListExtensions   
{
    public static void AppendRange<T>(this LinkedList<T> source,
                                      IEnumerable<T> items)
    {
        foreach (T item in items)
        {
            source.AddLast(item);
        }
    }

    public static void PrependRange<T>(this LinkedList<T> source,
                                       IEnumerable<T> items)
    {
        LinkedListNode<T> first = source.First;
        // If the list is empty, we can just append everything.
        if (first is null)
        {
            AppendRange(source, items);
            return;
        }

        // Otherwise, add each item in turn just before the original first item
        foreach (T item in items)
        {
            source.AddBefore(first, item);
        }
    }
}

編輯:Erich 的評論表明為什么您可能認為這是低效的 - 為什么不通過更新第一個列表尾部的“next”指針和第二個列表頭部的“prev”指針將兩個列表連接在一起? 好吧,想想第二個列表會發生什么……也會改變。

不僅如此,這些節點的所有權會怎樣? 現在每個本質上都是兩個列表的一部分……但是LinkedListNode<T>.List屬性只能談論其中一個。

雖然我可以理解為什么在某些情況下您可能想要這樣做,但 .NET LinkedList<T>類型的構建方式基本上禁止它。 我認為這個文檔評論最好地解釋了它:

LinkedList<T>)類不支持鏈接、拆分、循環或其他會使列表處於不一致狀態的功能。

llist1 = new LinkedList<T>(llist1.Concat(llist2));

這將連接兩個列表(需要 .NET 3.5)。 缺點是它創建了一個新的 LinkedList 實例,這可能不是你想要的......你可以這樣做:

foreach(var item in llist2)
{
    llist1.AddLast(item);
}

在這里你可以找到我的鏈表實現,它的連接和拆分時間為 O(1)。

為什么 .NET LinkedList 不支持 Concat 和 Split 操作?

簡短的摘要

與 .NET LinkedList 相比的優勢:

  • 更少的內存消耗,因此與原始 .NET 實現不同,每個節點 SimpleLinkedListNode 都有三個指針(prev、next、value)而不是四個(prev、next、list、value)。

  • 支持 O(1) 中的 Concat 和 Split 操作

  • 支持 O(1) 中的 IEnumarable Reverse() 枚舉器 - 順便說一下,我沒有看到任何原因為什么它沒有在 .NET LinkedList 上本地提供。 適當的擴展方法需要 O(n)。

缺點:

  • 不支持計數。
  • Concat 操作使第二個列表處於不一致狀態。
  • 拆分操作使原始列表處於不一致狀態。
  • 您可以在列表之間共享節點。

其他:

  • 我選擇了一種替代策略來實現枚舉和查找操作,而不是更冗長和純粹可讀的原始實現。 我希望負面性能影響仍然微不足道。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM