我第一次正式学习数据结构。对我来说,传统上描述链接列表的一些好处(更容易的内存分配以及更快的输入和删除到列表的主体)在js中看起来没有实际意义,因为数组的工作方式(比如带有数字键的对象)。
有人可以举例说明我为什么要在javascript中使用链接列表吗?
答案 0 :(得分:18)
如评论所述,如果您需要从列表中不断插入/删除时间,请执行此操作。
可以合理地实现Array
两种方式,允许填充非连续索引:
length
表示它不是重要)在任何一种情况下,最后插入的成本都将分摊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)
归结为array
与linkedlist
的基本差异。
next
的引用。答案 4 :(得分:1)
下面您可以找到Linked List
和Array
之间的简单比较
参考:https://en.wikipedia.org/wiki/Linked_list#Disadvantages