删除顺序表中 与输入的元素相同的所有元素问题

双指针实现;
/*
TODO: 删除表中与Item值相同的元素
功能:从键盘输入一个整数item,删除表中与Item数字相同的元素
比如:表为:6 5 4 3 2 1,录入2,则删除2,新的顺序表为:6 5 4 3 1
参数:List *L 是需要操作的表,item是指定删除元素的数值
返回值:空
*/
typedef struct Sq {

int elem[MAX] ;
int length ; //长度;

} List;
void Delete(List *L , int item){

             int  *p1,*p2;
             int i=L->length;
              p1= &L->elem[0], p2=&L->elem[L->length];
             //统计顺序表中为item的总共个数;
             while(i!=-1)
              {
                        if(L->elem[i]==item)
                                  {

                                    L->length--;
                                  }
                                    i--;
              }

                 while(1)
              {

                if( *p1==item  )
                  {
                    while(*p2==item)//当遇到 *p1==item && *p2==item 移动*p2 ;
                                   {

                                      p2++;

                                   }
                                         *p1=*p2 ;
                        if(p1+sizeof(int)==p2)  //相遇时;
                                 {
                                               break;
                                 }
                                         p2++;
                                         p1++;
                           }
                           else
                           p1++;
              }

}
当输入遇到 0 +回车时输入结束;
为什么 无法达到 删除相同的item ? 而且输出中总是有未知的值 ?
希望帮忙解答一下;
输出示例;
QQ图片20200317230502.png

阅读 2.4k
2 个回答
  1. p2=&L->elem[L->length]内存访问越界了,最后一个数是L->elem[L->length-1]
  2. 既然p2已经指向末尾了,后文中的p2++;多次越界
  3. int *p1,*p2,指针是int型,数组也是int型,p1 + 1就是访问下一个元素了,p1+sizeof(int)等于p1+4,所以用p1+sizeof(int)==p2)去判断相遇是不对的
  4. 逻辑考虑不周全,当6 5 4 3 2 1中的3被删掉后,后面的2 1没有向前搬运

追加内容
你的思路可以解题,只是把问题复杂化了。
我有个简洁的思路你参考一下

#include <stdio.h>

#define MAX    10

typedef struct Sq {
    int elem[MAX];
    int length;
} List;

void Delete(List *L , int item) {

    int *p1, *p2;
    int len = L->length;

    p1 = &L->elem[0];   // p1 指向数组开头
    for (p2 = p1; p2 < (L->elem + len); p2++) {     // 用p2遍历整个数组
        if (*p2 != item) {      // 检查数据合法
            *p1++ = *p2;        // 将合法数据搬运到p1,并且p1移位,准备下次接收
        } else {
            L->length--;        // 舍弃不合法的数据,并将数组长度减短
        }
    }
}


// 测试函数
void test(int del_num) {

    List L = {{3,2,3,3,1,1}, 6};

    printf("-------------------\n");
    printf("input array:");
    for (int i = 0; i < L.length; i++) {
        printf("%d ", L.elem[i]);
    }
    printf("\n");
    
    Delete(&L, del_num);
    
    printf("delete num:%d\noutput array:", del_num);
    for (int i = 0; i < L.length; i++) {
        printf("%d ", L.elem[i]);
    }
    printf("\n");
}

int main() {
    test(3);
    test(2);
    test(1);
    test(0);
}

输出

-------------------
input array:3 2 3 3 1 1 
delete num:3
output array:2 1 1 
-------------------
input array:3 2 3 3 1 1 
delete num:2
output array:3 3 3 1 1 
-------------------
input array:3 2 3 3 1 1 
delete num:1
output array:3 2 3 3 
-------------------
input array:3 2 3 3 1 1 
delete num:0
output array:3 2 3 3 1 1 

还有一个问题应该使用p1<p2;作为判段相交的条件
void Delete(List *L , int item){

             int  *p1,*p2;
             int i=L->length;
              p1= &L->elem[0], p2=&L->elem[L->length];
             //统计顺序表中为item的总共个数;
             while(i!=-1)
              {
                        if(L->elem[i]==item)
                                  {

                                    L->length--;
                                  }
                                    i--;
              }
                 while(p1<p2)
                 {
                                          if(*p1==item)
                                          {

                                                        if(*p2==item)
                                                        while(*p2==item)
                                                        p2--;
                                                      *p1=*p2;
                                                        p2--;
                                                        p1++;
                                          }
                                          else
                                            p1++;

                 }


}

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进