【问题标题】:Does Dart provide an easy-to-use Linked List?Dart 是否提供易于使用的链表?
【发布时间】:2014-04-13 02:37:58
【问题描述】:

我有一个算法,出于性能原因,应该使用链表。我希望不断地从列表中添加和删除元素,而且我永远不需要按索引查找特定元素。

我看到 Dart 在dart:collection 中有一个LinkedList (API docs),但这要求所有条目都为LinkedListEntry 的子类。我不控制需要放入列表的元素,也不想创建包装器。

我在核心 Dart SDK 中有哪些选择?

【问题讨论】:

  • 我怀疑答案是“使用队列”,但仍然很好奇。 Queue API 文档没有关于使用成本的详细信息。
  • ListQueue 文档说:“保持元素的循环缓冲区,并在填满时增长到更大的缓冲区。这保证了恒定时间的查看和删除操作,以及摊销的恒定时间添加操作。 " DoubleLinkedQueue 表示“允许恒定时间添加、末端删除和查看操作。” - 由于子实现可能不同,因此队列接口没有说明任何内容。
  • 谢谢@lrn。阅读 Queue 并没有将我指向 ListQueue 或 DoubleLinkedQueue。我想知道我们是否可以在文档中链接(哈哈明白吗?)这两者。
  • 我一直发现 LinkedList 的实现是错误的。 Java 的 LinkedList 是正确的方式,它提供了没有进一步限制的 List 接口,而 Dart LinkedList 没有。我认为没有人会使用 LinkedList over Queue。

标签: dart


【解决方案1】:

如果要在两端添加和删除,则需要Queue。您可以使用ListQueue(这是使用new Queue() 时获得的默认值)或DoubleLinkedQueue。 前者只保证末端加减的分摊常数时间操作,而后者有绝对保证。 ListQueue 有时需要在添加时增长其后备存储,这需要线性时间,但它仅在列表已满时发生,并且它执行传统的增长倍增以保证摊销恒定操作。

如果你只想在末尾添加和删除(基本上是一个堆栈),普通列表应该没问题。

【讨论】:

    【解决方案2】:

    您可以创建一个可重用的包装器,而不是让每个值都成为 LinkedListEntry 的子类

    import 'dart:collection';
    
    class MyLinkedListEntry<T> extends LinkedListEntry {
      T value;
      MyLinkedListEntry(this.value);
      @override
      String toString() => '${super.toString()}: ${value}';
    }
    
    void main(List<String> args) {
      var l = new LinkedList();
    
      var s = new MyLinkedListEntry<String>("SomeString");
      l.add(s);
      s.insertAfter(new MyLinkedListEntry<int>(125));
    
      l.forEach((e) => print(e));
    }
    

    【讨论】:

    • 没错,但如果可能的话,我想避免使用包装器。 :)
    • LinkedList 元素需要下一个/上一个指针。不可能不实现LinkedListEntry 或使用实现的包装器。队列(DoubleLinkedQueue 不是 ListQueue)在幕后这样做。它是隐藏 LinkedListEntryWrapper 的包装器;-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    • 2021-03-28
    相关资源
    最近更新 更多