跳转至

AB37-删除顺序表中第一个值为x的元素

代码实现

C
/**
 * 删除顺序表中第一个值为x的元素
 * @param L 指向顺序表的指针
 * @param x 要删除的目标值
 * @return 删除成功返回true,未找到返回false
 */
bool del_x(Sqlist *L, int x) {
    // 遍历顺序表查找目标元素
    for (int i = 0; i < L->length; i++) {
        // 找到第一个值为x的元素
        if (L->data[i] == x) {
            // 将该位置之后的所有元素前移一位(覆盖要删除的元素)
            for (int j = i + 1; j < L->length; j++) {
                L->data[j - 1] = L->data[j];
            }

            // 更新顺序表长度
            L->length--;

            // 删除成功,返回true
            return true;
        }
    }

    // 遍历完整个顺序表都未找到目标元素,删除失败
    return false;
}

算法执行流程图解

删除过程示例:

Text Only
原顺序表:[3][7][2][9][2][5]  (length=6)  删除x=2

查找过程:
i=0: data[0]=3 ≠ 2  继续查找
i=1: data[1]=7 ≠ 2  继续查找
i=2: data[2]=2 = 2  找到目标元素!

删除操作:
位置i=2的元素2需要被删除

元素前移过程:
j=3: data[2] = data[3] = 9  → [3][7][9][9][2][5]
j=4: data[3] = data[4] = 2  → [3][7][9][2][2][5]  
j=5: data[4] = data[5] = 5  → [3][7][9][2][5][5]

更新长度:
length = 5

最终结果:[3][7][9][2][5]  (length=5)

前移操作详细图解

Text Only
删除前:[A][B][C][D][E][F]
         0  1  2  3  4  5
          删除C

前移过程:
j=3: data[2] = data[3]  → [A][B][D][D][E][F]
j=4: data[3] = data[4]  → [A][B][D][E][E][F] 
j=5: data[4] = data[5]  → [A][B][D][E][F][F]

结果:[A][B][D][E][F][F]  length=5
               新的有效范围

复杂度分析

时间复杂度:O(n)

  • 查找时间
  • 最好情况:O(1) - 目标元素在第一个位置
  • 最坏情况:O(n) - 目标元素在最后一个位置或不存在
  • 平均情况:O(n)

  • 前移时间

  • 最好情况:O(1) - 删除最后一个元素(无需前移)
  • 最坏情况:O(n) - 删除第一个元素(需要前移n-1个元素)
  • 平均情况:O(n)

  • 总体时间复杂度O(n)

空间复杂度:O(1)

  • 只使用了常数个额外变量:ij
  • 原地操作,无需额外存储空间
  • 空间复杂度:O(1)

优化版本:添加边界检查和更清晰的逻辑

C
/**
 * 优化版本:添加边界检查和更清晰的逻辑
 */
bool del_x_Optimized(Sqlist *L, int x) {
    // 边界条件检查
    if (L == NULL || L->length <= 0) {
        return false;
    }

    // 查找目标元素
    for (int i = 0; i < L->length; i++) {
        if (L->data[i] == x) {
            // 元素前移(从后往前移动,减少赋值次数)
            for (int j = i; j < L->length - 1; j++) {
                L->data[j] = L->data[j + 1];
            }

            L->length--;
            return true;
        }
    }

    return false;  // 未找到目标元素
}

算法变体:删除所有值为x的元素

C
/**
 * 删除顺序表中所有值为x的元素
 * @param L 指向顺序表的指针
 * @param x 要删除的目标值
 * @return 删除的元素个数
 */
int del_all_x(Sqlist *L, int x) {
    int count = 0;  // 记录删除的元素个数
    int k = 0;      // 新顺序表的下标

    // 遍历原顺序表
    for (int i = 0; i < L->length; i++) {
        if (L->data[i] != x) {
            // 不是要删除的元素,保留在新顺序表中
            L->data[k] = L->data[i];
            k++;
        } else {
            // 是要删除的元素,计数器加1
            count++;
        }
    }

    L->length = k;  // 更新顺序表长度
    return count;   // 返回删除的元素个数
}

算法特点

优点: - 实现简单,逻辑清晰 - 适用于无序顺序表 - 原地操作,空间效率高

缺点: - 时间复杂度较高O(n) - 只删除第一个匹配元素

核心思想: 先查找目标元素位置,然后将该位置之后的所有元素整体前移一位,实现删除效果。

注意点: - 前移操作要从前往后进行,避免数据覆盖 - 及时更新顺序表长度 - 正确处理未找到目标元素的情况