似乎它们都以相同的方式做同样的事情:以特定但非必要索引的顺序进行惰性操作,并且不一定要回溯。
4 回答
链表是一种表示内存中数据元素序列的特定方式,其中每个元素都与指向序列中下一个元素的排序指针配对。链表允许您对其子序列执行一系列操作:您可以剪切或插入整个元素链,或者以非常低的成本从中间删除元素。
另一方面,流是按顺序访问数据的抽象,对它们在内存中的表示没有任何特定要求。您可以使用链表来实现流,但也可以为此使用其他数据结构,例如普通数组或循环数组缓冲区。
我认为这有点像比较苹果和橘子。
链表是一种数据结构,其中每个节点都指向另一个节点。它们是一种有用的结构,因为从链表中插入和删除项目只是重新指向一个节点的问题,而不是使用需要进行更多改组的数组。有关详细信息,请参阅http://en.wikipedia.org/wiki/Linked_list。
流是用于表示一系列字节的抽象对象。在大多数框架(Java、.NET 等)中,有几种具体的流实现(内存流、文件流等)用于从相关源(内存、文件等)读取字节数组。
链表是一种数据结构,其中每个元素都有一个指向下一个元素的指针,并且可能在另一个方向上相同。循环链表甚至有一个从最后一个元素到第一个元素的指针,反之亦然。这些指针(或没有指针的语言中的引用)定义了数据结构。它们暗示了某种操作模式,但它们并不强制这样做。例如,Java 中的LinkedList
类可以像数组一样使用,尽管那时它不会很有效。它也可以用作(双端)队列或堆栈,具体取决于您调用的函数。
另一方面,流不是定义为数据结构,而是定义为元素的源或汇。如果您想到文件流、套接字流或包装流的读取器/写入器类,这些元素可能是字节或字符。流提供的元素也可能更复杂,例如解析器的标记。在这种情况下,流可能在内部使用某种队列,可以使用链表或某种数组构造来实现。
只要确保理解这两件事是在不同的抽象层上定义的。链表是根据它在内部的工作方式来定义的,而流是根据它在外部的工作方式来定义的。
只读单链表和输入流之间有一个共同的抽象,C++ 将其形式化为InputIterator
:您可以读取一个值并且可以向前移动。在许多流 API 中,您必须同时执行这两项操作,但鉴于该 API,很容易看出如何使用缓存一个值的包装器将它们分开:C++ 调用此类istream_iterator
。
但是,单链表具有流并不总是具有的属性,C++ 将其形式化为ForwardIterator
:您可以复制当前位置,将副本向前移动,但仍可以读取原始位置的值。通用流无法做到这一点,因为底层 I/O 只有一个“当前位置”。使用链表,您可以有多个指向列表中不同节点的指针,而不会遇到麻烦。
一些流可以被标记和重置、倒带、寻找(寻找?)等,添加有点像 C++ ForwardIterator 甚至 RandomAccessIterator 的设施。
我使用 C++ 作为示例并不是因为它特别重要,而是因为 C++ 的迭代器概念部分设计用于提供数据结构和流共有的抽象。并非所有语言都有这样一个共同的抽象,但是对于 Python 中的另一个示例,您可以编写for x in y:
ify
是容器数据结构或 ify
是类文件对象,或者一般来说 ify
是“可迭代的”。