(c)无序向量
理清无序向量的 ADT 接口语义、查找代价与顺序无关的操作边界
按 空格/→ 演示下一步
全部页面点击任意一页,跳回舞台从这页播放
(c)无序向量
理清无序向量的 ADT 接口语义、查找代价与顺序无关的操作边界
概述
上一节点了'无序向量'这个名字。它和常见的词向量、位置编码有什么本质不同?这一页先把轮廓勾出来——是什么、关键性质、典型用法。
把苹果、香蕉、橘子混装一袋,怎么倒怎么摇,集合不变;只看'有什么、各多少'
: 循秩访问
无序向量内部元素没有按关键码排序,要找到某个元素,最直接的办法就是「按位置数」——这正是循秩访问的思路。
叫到几号就服务几号——直接按编号找人,不问其他信息
插入
循秩访问让我们 O(1) 找到第 r 个元素;想扩大规模,就得靠插入:在秩 r 处安插新元素 e,原来的第 r 个变成第 r+1 个,其他元素依次后移一格。
新人站到位置 r,原本在那及后面的人依次后退一格,队伍变长
区间删除
单元素删除不过是「区间删除」的退化——只要把秩区间缩成 [r, r+1)。但批量清除过期记录、截取日志片段时,真正上场的就是区间删除。这页把它的代价与边界讲透。
划掉后把后面整段往前抄补齐缺口,而不是留空
单元素删除
上一页的区间删除把 [lo, hi) 整段一锅端。如果区间长度退化为 1,就回到最朴素的场景:只删一个元素。这页拆开来看,看清里面那一步「搬家」。
人走后,他身后所有人依次向前一步把队形补齐
查找
前面讲了怎么插入、删除元素,但更多时候我们只是想确认某个值在不在——这就是查找。无序向量里元素位置没有规律可循,没有捷径,只能从首元素起逐个比对过去。
没有目录只能一本本翻到底;翻完都没找到就是'不存在'
唯一化
前面我们学会了在线性时间内查找。现在问一个自然延伸:若同一个值在向量里反复出现,能不能把重复的全都去掉?
名册记下已放行的名字(集合),后面重复名字直接拦下
遍历
查找、唯一化都暗用了遍历——把向量从头到尾过一遍。现在把它独立出来,作为最基础的操作。
从头到尾一个不漏;对每个元素做什么由传入的函数决定
本节要点
- ✓O(1) 访问换 O(n) 增删查,是无序向量的代价核心
- ✓消除顺序依赖就能向量化,把 O(n²) 压到 O(n)
- ✓唯一化是典范:双循环变前缀+后缀扫描
- ✓区间删除 O(n-m+1) 是通用范式,单点是其特例
- ✓工程上别忘缩容策略与稳定性等边界条件
课后思考
先自己想,再看参考答案。三问层层递进,检验你对无序向量的理解深度。
参考答案用'查找慢'换来了'插入快'。查找少而插入频繁时,这种交换划算;反之就是亏本买卖。数据结构的本质就是权衡。
参考答案不是。每次查找都要扫一遍,最坏要比较 10 万次。应当改用有序向量加二分查找,查找降到 O(logn),约 17 次比较就够。
参考答案被删除的空间只是'逻辑隐藏',可被后续插入原地复用,避免反复申请。但若历史容量远大于当前规模,会浪费内存——需主动申请更小的新数组并整体迁移来释放。