鱼C论坛

 找回密码
 立即注册
查看: 1737|回复: 16

[已解决]删除重复数据的节点,删除不干净

[复制链接]
发表于 2021-11-8 10:06:54 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
void deleteIdentica_ListNode(PLIST list) {//删除重复数据的节点
        if (list == NULL) {
                perror("链表地址是NULL,即将退出程序!\n");
                exit(-1);
        }

        PNODE pFirst = list->Head.next; //指向链表第一个有真实数据的节点
        PNODE pindex = list->Head.next; //指向链表第一个有真实数据的节点
        PNODE pSecond = pFirst->next; //指向链表第二个有真实数据的节点
        PNODE delete = NULL;           //指向待删除的重复数据的节点

        for (int i = 0; i < list->M_size - 1; i++) { // list->M_size 链表的有效节点
               
                for (int j = i + 1; j < list->M_size; j++) {
                        if (pindex->data == pSecond->data) {
                                delete = pSecond;
                                pFirst->next = pSecond->next;
                                pSecond = pSecond->next;
                                free(delete);
                                list->M_size--;
                        }
                        else {
                                pSecond = pSecond->next;
                                pFirst = pFirst->next;
                        }
                       
                }
               
                pindex = pindex->next;
                pFirst = pindex;
                pSecond = pFirst->next;
        }
        return;
}

//  哪位大佬给看看程序有没有什么问题,为什么程序
运行后重复数据节点没有删除干净?
14592 1774 12583 32215 26879 1688 2288 2288 2288 2288 2288 2288 2288 2288 2288 2
288 8259 857 4989 11010
__________________________________
14592 1774 12583 32215 26879 1688 2288 2288 8259 857 4989 11010
__________________________________
程序运行了:30 毫秒!
系统日期:2021-11-8
系统时间:9-57-51
请按任意键继续. . .
最佳答案
2021-11-8 10:40:50
本帖最后由 jackz007 于 2021-11-8 17:25 编辑

        试试这个代码呢
  1. void deleteIdentica_ListNode(PLIST list)
  2. {
  3.         PLIST p1 , p2 , p3                                       ;
  4.         if(list) {
  5.                 for(p1 = list ; p1 && p1 -> next ; p1 = p1 -> next) {   
  6.                         for(p3 = p1 , p2 = p3 -> next ; p2 ; p2 = p3 -> next) {
  7.                                 if(p2 -> data == p1 -> data) {
  8.                                         p3 -> next = p2 -> next  ;
  9.                                         free(p2)                 ;
  10.                                 } else {
  11.                                         p3 = p2                  ;
  12.                                 }
  13.                         }
  14.                 }
  15.         } else {
  16.                 fprintf(stderr , "Error : Empty Data Link !\n" ) ;
  17.         }
  18. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-11-8 10:40:50 | 显示全部楼层    本楼为最佳答案   
本帖最后由 jackz007 于 2021-11-8 17:25 编辑

        试试这个代码呢
  1. void deleteIdentica_ListNode(PLIST list)
  2. {
  3.         PLIST p1 , p2 , p3                                       ;
  4.         if(list) {
  5.                 for(p1 = list ; p1 && p1 -> next ; p1 = p1 -> next) {   
  6.                         for(p3 = p1 , p2 = p3 -> next ; p2 ; p2 = p3 -> next) {
  7.                                 if(p2 -> data == p1 -> data) {
  8.                                         p3 -> next = p2 -> next  ;
  9.                                         free(p2)                 ;
  10.                                 } else {
  11.                                         p3 = p2                  ;
  12.                                 }
  13.                         }
  14.                 }
  15.         } else {
  16.                 fprintf(stderr , "Error : Empty Data Link !\n" ) ;
  17.         }
  18. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-8 13:34:06 | 显示全部楼层
非常感谢!你的这个确实是精妙,可以删除干净,
这个代码我还是有些不太看得懂,需要些时间去消化;
可是我还是搞不明白我的那个代码问题出在哪里了;
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-8 14:03:40 | 显示全部楼层
本帖最后由 zhenhaowa66 于 2021-11-8 14:05 编辑

for(p1 = list ; p1 -> next ; p1 = p1 -> next) {   //这里p1->next 怎么理解啊
                        for(p3 = p1 , p2 = p3 -> next ; p2 ; p2 = p3 -> next) {//这个p2有什么作用,后面这个不是重复了吗?可以省略吗
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-8 14:52:20 | 显示全部楼层
本帖最后由 jhq999 于 2021-11-8 15:00 编辑
zhenhaowa66 发表于 2021-11-8 14:03
for(p1 = list ; p1 -> next ; p1 = p1 -> next) {   //这里p1->next 怎么理解啊
                        ...


第一个p1->next 判断条件,最后一个的next是NULL,就是假退出循环;
p2=p3->next和上面p1->next一样做为是否到了最后的循环条件,而且而循环体里p2和p1重复后,把p3和p2的next联系起来,然后释放p2


小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-8 15:11:58 | 显示全部楼层

你这个代码好像还有点问题,我换了数据就行不通,崩了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-8 16:14:57 | 显示全部楼层
本帖最后由 jhq999 于 2021-11-8 16:22 编辑
zhenhaowa66 发表于 2021-11-8 15:11
你这个代码好像还有点问题,我换了数据就行不通,崩了

  1. for(p3 = p1 , p2 = p3 -> next ; p3->next ;p2 = p3 -> next)//试试,他没考虑到最后一个重复,这时p3->next=p2->next=NULL,而p2只是释放不为NULL,p2= p3 -> next=NULL再进入循环体必然崩
复制代码

编程就是不断的调试
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-8 16:35:43 | 显示全部楼层
本帖最后由 jackz007 于 2021-11-8 17:26 编辑
zhenhaowa66 发表于 2021-11-8 15:11
你这个代码好像还有点问题,我换了数据就行不通,崩了

  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. typedef struct node {
  4.         int data           ;
  5.         struct node * next ;
  6. } * PLIST                  ;

  7. void show(PLIST head)
  8. {
  9.         if(head) {
  10.                 for(int c = 0 ; head ; head = head -> next) {
  11.                         if(c && ! (c % 8)) printf("\n")                          ;
  12.                         else if(c) printf(" , ")                                 ;
  13.                         printf("%5d" , head -> data)                             ;
  14.                         c ++                                                     ;
  15.                 }
  16.         } else {
  17.                 fprintf(stderr , "错误:链表为空!\n")                           ;
  18.         }
  19.         printf("\n")                                                             ;
  20. }

  21. PLIST add(PLIST * head)
  22. {
  23.         PLIST p , p1 , p2                                                        ;
  24.         int d                                                                    ;
  25.         if(* head) for(p1 = * head , p2 = NULL ; p1 ; p2 = p1 , p1 = p1 -> next) ;
  26.         else p1 = p2 = NULL                                                      ;
  27.         printf("输入节点数据 :\n ")                                              ;
  28.         for(;; p2 = p) {
  29.                 scanf("%d" , & d)                                                ;
  30.                 if(d > 0) {                        
  31.                         if(p = (PLIST) malloc(sizeof(struct node))) {
  32.                                 p -> data = d                                    ;
  33.                                 p -> next = NULL                                 ;
  34.                                 if(p2) p2 -> next = p                            ;
  35.                                 else * head = p                                  ;
  36.                         } else {
  37.                                 fprintf(stderr , "内存分配失败!\n")             ;
  38.                                 * head = p                                       ;
  39.                                 break                                            ;
  40.                         }
  41.                 } else {
  42.                         break                                                    ;
  43.                 }
  44.         }
  45.         return * head                                                            ;
  46. }

  47. void deleteIdentica_ListNode(PLIST list)
  48. {
  49.         PLIST p1 , p2 , p3                                       ;
  50.         if(list) {
  51.                 for(p1 = list ; p1 && p1 -> next ; p1 = p1 -> next) {   
  52.                         for(p3 = p1 , p2 = p3 -> next ; p2 ; p2 = p3 -> next) {
  53.                                 if(p2 -> data == p1 -> data) {
  54.                                         p3 -> next = p2 -> next  ;
  55.                                         free(p2)                 ;
  56.                                 } else {
  57.                                         p3 = p2                  ;
  58.                                 }
  59.                         }
  60.                 }
  61.         } else {
  62.                 fprintf(stderr , "Error : Empty Data Link !\n" ) ;
  63.         }
  64. }

  65. void destroy(PLIST head)
  66. {
  67.         PLIST p1 , p2           ;
  68.         for(p2 = NULL , p1 = head ; p1 ; p1 = p2) {
  69.                 p2 = p1 -> next ;
  70.                 free(p1)        ;
  71.         }
  72. }

  73. int main(void)
  74. {
  75.         PLIST head = NULL             ;
  76.         add(& head)                   ;
  77.         printf("\n")                  ;
  78.         printf("去除重复前:\n")      ;
  79.         show(head)                    ;
  80.         deleteIdentica_ListNode(head) ;
  81.         printf("去除重复后:\n")      ;
  82.         show(head)                    ;
  83.         destroy(head)                 ;
  84. }
复制代码

        编译、运行实况:
  1. D:\0002.Exercise\C>g++ -o x x.c

  2. D:\0002.Exercise\C>x
  3. 输入节点数据 :
  4. 14592 1774 12583 32215 26879 1688 2288 2288 2288 2288 2288 2288 2288 2288 2288
  5. 2288 8259 857 4989 11010 0

  6. 去除重复前:
  7. 14592 ,  1774 , 12583 , 32215 , 26879 ,  1688 ,  2288 ,  2288
  8. 2288 ,  2288 ,  2288 ,  2288 ,  2288 ,  2288 ,  2288 ,  2288
  9. 8259 ,   857 ,  4989 , 11010
  10. 去除重复后:
  11. 14592 ,  1774 , 12583 , 32215 , 26879 ,  1688 ,  2288 ,  8259
  12.   857 ,  4989 , 11010

  13. D:\0002.Exercise\C>
复制代码

        这个代码在输入的节点数据值小于 1 时结束输入。
        用这个代码测试你的数据,我倒是想知道,什么样的数据能让它崩溃!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-8 16:42:36 | 显示全部楼层
jackz007 发表于 2021-11-8 16:35
编译、运行实况:

        这个代码在输入的节点数据值小于 1 时结束输入。

谢谢你了,我开始测试了个极端的例子,山到只剩最后一个才崩掉的,只要有2个节点就不会崩
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-8 16:52:30 | 显示全部楼层
本帖最后由 jackz007 于 2021-11-8 16:55 编辑
zhenhaowa66 发表于 2021-11-8 16:42
谢谢你了,我开始测试了个极端的例子,山到只剩最后一个才崩掉的,只要有2个节点就不会崩

  1.                 for(p1 = list ; p1 -> next ; p1 = p1 -> next) {   
  2.                         for(p3 = p1 , p2 = p3 -> next ; p2 ; p2 = p3 -> next) {
复制代码

        第一句位于两个分号中间的 p1 -> next 等价于 p1 -> next != NULL,下面 for 语句中位于两个分号中间的 p2 同样是这个意思。
        指针的 NULL 就是指针 0 值,对应的逻辑值为 false。只要指针不是 NULL,就一定是 true。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-8 17:04:09 | 显示全部楼层
本帖最后由 jhq999 于 2021-11-8 17:05 编辑
jackz007 发表于 2021-11-8 16:52
第一句位于两个分号中间的 p1 -> next 等价于 p1 -> next != NULL,下面 for 语句中位于两个 ...


14592 1774 12583 32215 26879 1688 2288 2288 2288 2288 2288 2288 2288 2288 2288
2288 8259 857 4989 11010 11010 0
  1. for(p1 = list ; p1  ; p1 = p1 -> next) {   
  2.                         for(p3 = p1 , p2 = p3 -> next ; p3->next ; p2 = p3 -> next)
  3. {
  4. .........
  5. }
  6. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-8 17:27:15 | 显示全部楼层
jhq999 发表于 2021-11-8 17:04
14592 1774 12583 32215 26879 1688 2288 2288 2288 2288 2288 2288 2288 2288 2288
2288 8259 857 49 ...

     2、8 楼的代码已经修正,请你再测。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-8 17:33:12 | 显示全部楼层
zhenhaowa66 发表于 2021-11-8 16:42
谢谢你了,我开始测试了个极端的例子,山到只剩最后一个才崩掉的,只要有2个节点就不会崩

      2、8 楼的代码已经修改了,就用你先前的极端例子测。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-8 17:41:05 | 显示全部楼层
本帖最后由 jhq999 于 2021-11-8 17:42 编辑
jackz007 发表于 2021-11-8 17:27
2、8 楼的代码已经修正,请你再测。


献丑了,基本功比较差,居然以为赋初值后先条件后运算
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-8 18:18:17 | 显示全部楼层
jackz007 发表于 2021-11-8 17:33
2、8 楼的代码已经修改了,就用你先前的极端例子测。

厉害了!确实是这样怎么搞都行
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-8 18:23:54 | 显示全部楼层
jackz007 发表于 2021-11-8 16:52
第一句位于两个分号中间的 p1 -> next 等价于 p1 -> next != NULL,下面 for 语句中位于两个 ...

感谢耐心讲解!现在基本看明白了,之前没要见过这样的for语句,不知道还可以这样搞for语句
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-11-8 19:04:45 | 显示全部楼层
jackz007 发表于 2021-11-8 17:27
2、8 楼的代码已经修正,请你再测。

现在我也搞清楚了我的代码为什么删不干净就是不应该j=i+1;直接j=0;就没有问题了
就用排序里面的冒泡法就可以解决了,
void deleteIdentica_ListNode(PLIST list) {//删除重复数据
        if (list == NULL) {
                perror("链表地址是NULL,即将退出程序!\n");
                exit(-1);
        }
        PNODE pFirst = list->Head.next; //指向链表第一个有真实数据的节点
        PNODE pSecond = pFirst->next; //指向链表第二个有真实数据的节点
        PNODE delete = NULL;           //指向待删除的重复数据的节点
        for (int i = 0; i < list->M_size - 1; i++) {
                for (int j = 0; j < list->M_size - i; j++); {
                        if (pFirst->data == pSecond->data) {
                                delete = pSecond;
                                pFirst->next = pSecond->next;
                                free(delete);
                                pSecond = pFirst->next;
                        }
                }

        }
        return;
}
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-25 21:22

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表