跳到主要内容

线性数据结构

线性结构按序列组织元素,但它们的表示方式和允许的操作并不相同。

对比

结构索引访问末端插入/删除已知内部位置的插入/删除主要权衡
动态数组O(1)O(1)摊销 O(1)O(1)O(n)O(n) 次移动局部性和随机访问
单链表O(n)O(n)有尾指针时插入为 O(1)O(1);删除尾部为 O(n)O(n)已知前驱后为 O(1)O(1)间接寻址和节点开销
双链表O(n)O(n)维护两端时为 O(1)O(1)已知节点后为 O(1)O(1)每个节点多一条链接
不属于接口契约在栈顶压入/弹出接口不允许LIFO 纪律
队列不属于接口契约在相对两端入队/出队接口不允许FIFO 纪律

寻找内部节点或位置与修改它是两件事。“链表插入是 O(1)O(1)”这句话隐含了相关节点或前驱已经可用这一前提。

选择规则

  • 通用序列和以迭代为主的工作,优先使用动态数组。
  • 当稳定的节点身份和局部拼接占主导时,考虑链式节点。
  • 如果受限访问比通用列表更能表达算法不变量,就暴露栈或队列接口。
  • 有界队列若要求存储可预测,可使用环形缓冲区。

在 Python 中,list 是对象引用的动态数组;collections.deque 支持高效的双端操作。

按下一步操作选择

需要直接取第 100 项时,读数组。算法已经持有节点、需要在旁边拼接时,读链表;只知道数字位置,并不等于已经拿到节点。要匹配最近一个尚未闭合的分隔符,用。要按到达顺序处理,用队列

这里的 nn 是已存元素数,移动一个槽位或沿一条链接访问的成本视为常数。摊销成本约束的是一整串操作,包括偶尔发生的扩缩容,不是对随机输入取平均。栈和队列两行描述接口,具体实现成本需要分别查看。这些比较针对内存中的顺序容器,不涉及并发消息投递或磁盘索引。

来源

探索关联打开关联网络