Sequential List Insert Delete
顺序表的插入与删除
插入操作
ListInsert(&L, i, e) 表示在顺序表 L 的第 i 个位置插入元素 e。
合法范围:1 <= i <= L.length + 1。
基本步骤:
- 判断插入位置是否合法。
- 判断表是否已满。
- 从最后一个元素开始,到第
i个元素为止,依次后移一位。 - 将
e放入第i个位置,即数组下标i - 1。 length加 1。
注意移动顺序必须从后往前,否则会覆盖尚未移动的元素。
1 | bool ListInsert(SqList *list, int index, ElemType value) { |
代码中的 moveIndex 是数组下标相关的位置。插入第 index 位时,原第 index 位到原表尾都要右移一格,所以循环从 list->length 开始,目标位置是 data[moveIndex],来源位置是 data[moveIndex - 1]。
插入时间复杂度
设表长为 n。
- 最好情况:插入表尾,不需要移动元素,
O(1)。 - 最坏情况:插入表头,需要移动
n个元素,O(n)。 - 平均情况:插入位置等概率出现,移动期望为
n/2个元素,O(n)。
删除操作
ListDelete(&L, i, &e) 表示删除第 i 个位置的元素,并用 e 返回被删除元素。
合法范围:1 <= i <= L.length。
基本步骤:
- 判断删除位置是否合法。
- 用
e保存第i个元素的值。 - 从第
i + 1个元素开始,依次前移一位。 length减 1。
1 | bool ListDelete(SqList *list, int index, ElemType *deletedValue) { |
删除第 index 位后,原第 index + 1 位要补到第 index 位,所以循环从数组下标 index 对应的元素开始,把 data[moveIndex] 复制到 data[moveIndex - 1]。
删除时间复杂度
设表长为 n。
- 最好情况:删除表尾,不需要移动元素,
O(1)。 - 最坏情况:删除表头,需要移动
n - 1个元素,O(n)。 - 平均情况:删除位置等概率出现,平均移动约
(n - 1)/2个元素,O(n)。
易错点
- 位序从 1 开始,数组下标从 0 开始。
- 插入第
i个位置时,元素放入data[i - 1]。 - 删除时若不使用
&e(取址),被删除值无法带回调用处。 - 顺序表插入删除的主要时间开销来自移动元素。
- 插入必须从后往前移动;删除必须从前往后移动。方向错了就会覆盖仍需保留的数据。
关联
链式存储的插入删除见 单链表的插入与删除。顺序表插入删除的主要成本是移动元素,链表的主要成本是定位前驱结点。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Elian's blog page!