你会在Javascript中实现一个链表吗?

时间:2015-06-20 03:33:15

标签: javascript

我第一次正式学习数据结构。对我来说,传统上描述链接列表的一些好处(更容易的内存分配以及更快的输入和删除到列表的主体)在js中看起来没有实际意义,因为数组的工作方式(比如带有数字键的对象)。

有人可以举例说明我为什么要在javascript中使用链接列表吗?

5 个答案:

答案 0 :(得分:18)

如评论所述,如果您需要从列表中不断插入/删除时间,请执行此操作。

可以合理地实现Array两种方式,允许填充非连续索引:

  1. 作为一个实际的C类连续内存块,其大小足以包含所有使用的索引;未填充的索引将包含对虚拟值的引用,因此它们不会被视为已填充的条目(超出最大索引的超出容量可能会被视为垃圾,因为length表示它不是重要)
  2. 作为由整数键入的哈希表(基于类C数组)
  3. 在任何一种情况下,最后插入的成本都将分摊O(1),但只要基础类C数组的容量耗尽,就会完成O(n)的峰值工作(或者超出哈希负载阈值)并且需要重新分配。

    如果您在开头或中间插入(并且正在使用的索引),您可能会遇到与之前相同的工作峰值和新问题。不,现有指数的数据不会改变。但是,您强制进入的条目上方的所有键必须递增(实际或逻辑)。如果它是一个简单的C类数组实现,那么它们大多只是memmove(模块化垃圾收集等的需求)。如果它是一个哈希表实现,你需要基本上读取每个元素(从最高索引到最低索引,这意味着要么对键进行排序,要么查找当前长度以下的每个索引,即使它是稀疏的Array),弹出它,然后用一个更高的键值重新插入它。对于一个大的Array,成本可能是巨大的。在某些浏览器中实现可能会通过使用" offset"来做一些聪明的废话。这将在内部使用负面"键"相对于偏移量,以避免在索引0之前插入时重新散列,但它会使所有操作更加昂贵,以换取shift / unshift更便宜。

    重点是,用JavaScript编写的链接列表会导致成为JS的开销(对于类似的工作,它通常比内置运行更慢)。但是(忽略了内存管理器本身引入工作高峰的可能性),它是可预测的:

    • 如果您想从开头或结尾插入或删除,那么它是固定工作(一次分配或解除分配,以及参考修正)
    • 如果您正在迭代并插入/删除,除了迭代成本之外,它是相同的固定工作
    • 如果事实证明在您的浏览器的实施过程中没有使用偏移来实现shift / unshift(使用它们,shift通常会很便宜,并且unshift便宜,直到你unshift - 比你shift - ed更多,那么你肯定想在使用链表时使用可能无限大小的FIFO队列

    完全有可能所有浏览器都使用偏移来优化(避免memmove或在某些条件下重新键入,尽管它不能避免偶尔realloc和{{1}或不重复而不浪费记忆)。我不知道主要浏览器的方式或方式,但如果您尝试编写具有一致性能的可移植代码,您可能不会认为他们牺牲了一般性能使memmove s shift / unshift案例更快,他们可能更愿意让所有其他操作更快,并假设Array / shift只会与小unshift一起使用,其中费用很小。

答案 1 :(得分:8)

I think there are some legit cases / reasons to prefer linked lists:

Reason 1: As others already described, insertion and deletion operations perform fixed in O(1) time for linked lists. This might be a significant advantage depending on your problem.

Reason 2: You can do things with linked lists that you can't do with arrays. This is due to the nature of a linked list -> every list entry has got references to it's follower (and prececessor if it's a double linked list).

Example1:

So if you have a linked list of items cou could store a reference to a "currentItem" in a variable. If you need to access the item's neighbors you could just write:

curItem.getNext();

or

curItem.getPrev();

Now you could argue that you could do the same with arrays while curItem is just the current Index. Basically this is true (and in most cases I would use that), but remember that in javascript it is possible to skip indices. So if your array looks like this, the index-method would not work as easily as thought:

myArray = [];
myArray[10] = 'a';
myArray[20] = 'b';

If you find yourself in that kind of situation, maybe a linked ist is the better choice.

However, if you need random access to the data (which is more seldom than it seems in most cases) you would go with arrays almost every time.

Example2:

If you want to "split" your list into 2 separate lists, this would also be possible O(1) time. With arrays you'd need to use slice, which is more imperformant. However, this is only an issue if you work with large datasets and perform this operation often. 20 repetitions of slicing of an array of 10 million strings took about 4 seconds on my machine, whereas the separation of one list into 2 took <1 second (providing you already have a reference to the list element where you want to start the separation of course!).

Conclusion:

In some cases you would benefit from a list's nature and it's performance. In some cases, you would suffer from it's imperformance (inability to randomly access multiple data). I've never used a list in javascript, but similar structures like trees or graphs are used for data representation (in both backend and frontend javascript). So analyzing/learning list implementations in javascript is a good idea for more complex structures.

答案 2 :(得分:5)

@ noob-in-need我建议你观看关于JavaScript垃圾收集器的视频:https://www.youtube.com/watch?v=RWmzxyMf2cE

在其中,他解释了为什么使用链表可以让您更好地控制代码的速度(如ShadowRanger深入讨论),并防止意外的垃圾收集速度减慢。此外,它是在像海盗一样的谈话中拍摄的。 :)

答案 3 :(得分:2)

归结为arraylinkedlist的基本差异。

  1. 在元素数组中插入新元素的成本很高,因为必须为新元素创建空间并创建空间,需要移动现有元素。但对于链接列表,它只是更改引用。
  2. 但是数组中的读取和随机访问比链接列表更容易。不允许随机访问。我们必须从第一个节点开始按顺序访问元素。所以我们不能用链表进行二进制搜索。
  3. 列表的每个元素都需要一个指针的额外内存空间,用于存储next的引用。

答案 4 :(得分:1)

下面您可以找到Linked ListArray之间的简单比较
参考:https://en.wikipedia.org/wiki/Linked_list#Disadvantages

enter image description here