数据结构,王道练习题

题目:将顺序表中元素值为x的删除并输出删除之后的表;
问题:为什么感觉逻辑上没错,删除元素会出现删不干净呢?

#include<stdlib.h>
#include<stdio.h>
# define Maxsize 100
# define ElemType int
# define Status int
//结构
typedef struct {
    ElemType* elem;
    int length;
    int listsize;
}SqList;
//初始化
Status InitList(SqList& L)
{
    L.elem = (ElemType*)malloc(Maxsize * sizeof(ElemType));
    if (!L.elem) return false;
    L.length = 0;
    L.listsize = Maxsize;
    return true;
}
//输入数据
Status Enter(SqList& L, int n)
{
    for (int i = 0; i < n; i++)
    {
        scanf_s("%d", &(L.elem[i]));
        L.length++;
    }
    return true;
}
//输出数据
Status Out(SqList& L)
{
    if (!L.elem)
        return false;
    for (int i = 0; i < L.length; i++)
        printf("%d ", L.elem[i]);
    return true;
}
Status Handle(SqList& L)
{
    int j = 0, a[20];
    for (int i = 0; i < L.length; i++)
    {
        if (L.elem[i] == 7)
        {
            a[j] = i;
            j++;
        }
    }
    for (int m = 0; m < j; m++)
    {
            int* p = &(L.elem[a[m]]);
            int e = *p;
            int* q = L.elem + L.length - 1;
            for (++p; p <= q; ++p) *(p - 1) = *p;
            --L.length;
    }
    return true;
        
}


int main()
{
    SqList L;
    InitList(L);
    int n;
    printf("输入数据的规模:");
    scanf_s("%d", &n);
    printf("输入数据:");
    Enter(L, n);
    printf("原先的数据:");
    Out(L);

    Handle(L);
    printf("\n经过删除x=7后的数据:");
    Out(L);
    
    return 0;
}

删除里,算法设计有问题的,当找到待删除的位置存放在a[]数组里。然后下面开始删除a[0]第一个位置后,表长度减一 --L.length; ,表往前移一位,再删第二位置即a[1] 时记录的是原长度的下标值,与前移一次的位置就不对应了,错位了。将第53行的代码:int* p = &(L.elem[a[m]]); 修改为:
int* p = &(L.elem[a[m] - m]); ,即可,供参考:

#include<stdlib.h>
#include<stdio.h>
# define Maxsize 100
# define ElemType int
# define Status int
//结构
typedef struct {
    ElemType* elem;
    int length;
    int listsize;
}SqList;
//初始化
Status InitList(SqList& L)
{
    L.elem = (ElemType*)malloc(Maxsize * sizeof(ElemType));
    if (!L.elem) return false;
    L.length = 0;
    L.listsize = Maxsize;
    return true;
}
//输入数据
Status Enter(SqList& L, int n)
{
    for (int i = 0; i < n; i++)
    {
        scanf_s("%d", &(L.elem[i]));
        L.length++;
    }
    return true;
}
//输出数据
Status Out(SqList& L)
{
    if (!L.elem)
        return false;
    for (int i = 0; i < L.length; i++)
        printf("%d ", L.elem[i]);
    return true;
}
Status Handle(SqList& L)
{
    int j = 0, a[20];
    for (int i = 0; i < L.length; i++)
    {
        if (L.elem[i] == 7)
        {
            a[j] = i;
            j++;
        }
    }
    for (int m = 0; m < j; m++)
    {
        int* p = &(L.elem[a[m] - m]);  //int* p = &(L.elem[a[m]]); 修改
        int e = *p;
        int* q = L.elem + L.length - 1;
        for (++p; p <= q; ++p) *(p - 1) = *p;
        --L.length;
    }
    return true;

}


int main()
{
    SqList L;
    InitList(L);
    int n;
    printf("输入数据的规模:");
    scanf_s("%d", &n);
    printf("输入数据:");
    Enter(L, n);
    printf("原先的数据:");
    Out(L);

    Handle(L);
    printf("\n经过删除x=7后的数据:");
    Out(L);

    return 0;
}

建议将删除函数换种写法,供参考:

Status Handle(SqList& L)
{
    int j = 0, x = 7;
    for (int i = 0; i < L.length; i++)
    {
        if (L.elem[i] - x)
            L.elem[j++] = L.elem[i];
    }
    L.length = j;
    return true;
}

该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
在你的代码中,删除元素的逻辑上是正确的。但是在实际情况中,可能会出现删除不完全的情况,这是由于你删除元素时,只删除了第一个找到的元素,而没有考虑到顺序表中可能存在多个相同的元素。

例如,如果顺序表中有如下元素序列:{7, 2, 7, 8, 7, 6, 7},且要删除的元素值为7,则你的程序只会删除第一个找到的7,结果为{2, 7, 8, 7, 6, 7},而实际上还有两个7没有被删除。

因此,你需要修改代码,考虑到顺序表中可能存在多个相同的元素。可以使用一个循环,每次找到一个需要删除的元素时,就把它后面的元素依次往前移动一个位置,直到把所有的需要删除的元素都删除为止。修改后的代码如下:

Status Handle(SqList& L, ElemType x)
{
    int k = 0; // 记录已删除的元素个数
    for (int i = 0; i < L.length - k; i++)
    {
        if (L.elem[i] == x)
        {
            k++;
            for (int j = i; j < L.length - k; j++)
            {
                L.elem[j] = L.elem[j + 1];
            }
            i--; // 因为元素往前移了一位,所以需要将i回退一位
        }
    }
    L.length -= k; // 更新顺序表的长度
    return true;
}

在这个修改后的代码中,我们使用一个变量k来记录已经删除的元素个数,每次删除一个元素后,都将k加1。在循环中,我们从第一个元素开始遍历,如果找到一个需要删除的元素,就将后面的元素依次往前移动一个位置,直到移动到顺序表的末尾。因为每次删除一个元素后,顺序表的长度会减少1,所以我们需要在循环结束后,更新顺序表的长度。


如果以上回答对您有所帮助,点击一下采纳该答案~谢谢