当您预先知道数据的大小时,数组就非常有用。但是,当数据不可预测地到达时会发生什么——传感器读数流、人工智能要处理的任务队列,或者随着每条消息而增长的对话历史记录?您需要能够优雅地增长和收缩的结构。
输入链表、堆栈和队列 - 动态三重奏。
链表将项目存储为节点链。每个节点保存两件事:数据本身和指向链中下一个节点的指针(引用)。
[data: "A" | next: →] → [data: "B" | next: →] → [data: "C" | next: null]
与数组不同,链表节点不会并排位于内存中。它们可以分散在任何地方 - 指针只是告诉您在哪里可以找到下一个。
|运营|数组|链接列表 | |------------|---------|-------------| |通过索引访问 | O(1) ⚡ | O(n) 🐢 | |在开头插入 | O(n) 🐢 | O(1) ⚡ | |插入中间 | O(n) 🐢 | O(1)* ⚡ | |从中间删除 | O(n) 🐢 | O(1)* ⚡ | |内存使用情况 |紧凑|额外(指针)|
*一旦找到位置 - 找到它仍然是 O(n)。
浏览器的选项卡栏可让您自由打开、关闭和重新排列选项卡。数组或链表更适合管理打开的选项卡列表吗?考虑一下当您关闭中间的选项卡时会发生什么。
堆栈的工作方式与一堆盘子完全相同:添加到顶部并从顶部删除。最后放入堆栈的项目是第一个取出的项目。
Push "A" → [A]
Push "B" → [A, B]
Push "C" → [A, B, C]
Pop → [A, B] (removed "C")
Pop → [A] (removed "B")
两个操作定义一个堆栈:
两者都是 O(1) - 即时的,无论堆栈大小如何。
当您看到“堆栈溢出”错误时,它的字面意思是调用堆栈空间不足 - 通常是因为函数不断调用自身而不停止(无限递归)。著名的开发者问答网站 Stack Overflow 就是以这个错误命名的。
登录 参与讨论
您正在为绘图应用程序实现”撤消”功能。哪种数据结构最能模拟行为历史?
队列就像商店里的队列一样:第一个加入的人就是第一个被服务的人。项目在后面添加,从前面删除。
Enqueue "A" → [A]
Enqueue "B" → [A, B]
Enqueue "C" → [A, B, C]
Dequeue → [B, C] (removed "A")
Dequeue → [C] (removed "B")
两个操作定义一个队列:
AI API 每秒接收 10,000 个请求。哪种结构可确保请求按照到达的顺序进行处理?
有一个优先级队列,其中项目根据优先级而不是到达顺序出队。人工智能系统使用优先级队列首先处理紧急任务 - 例如,自动驾驶汽车可能会优先考虑障碍物检测而不是路线规划。
语言模型将文本作为序列进行处理。在底层,PyTorch 和 TensorFlow 等框架使用类似链表的结构来构建计算图 - 每个步骤都指向下一个步骤的操作链。
训练神经网络时,随着张量(多维数组)的创建和销毁,内存会不断分配和释放。内存分配器通常使用空闲内存块的链表,为新张量找到合适的空间。
聊天机器人需要记住对话中的最后 10 条消息,但丢弃较旧的消息。你会使用堆栈、队列还是其他东西?当第 11 条消息到达时会发生什么?
关于链表的哪项陈述是错误的?
大多数应用程序中的撤消历史记录都有限制 - 通常为 100 到 1,000 个操作。如果没有这个限制,堆栈将消耗不断增长的内存。一些高级系统使用堆栈和队列(“双端队列”)的组合来保留最新的操作,同时丢弃最旧的操作。