鱼C论坛

 找回密码
 立即注册
查看: 1915|回复: 4

[已解决]爱学习的我又来啦!麻烦大佬帮忙看看!谢谢

[复制链接]
发表于 2023-4-11 20:53:53 | 显示全部楼层 |阅读模式

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

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

x
此代码中去重返回出来的链表有问题 好像头节点变成了最后尾节点
比如链表1 1 2 2 3 4 5
返回出只有一个5
看了答案去重函数中应该是return head;
但是我想知道 因为x是指向了*head的地址 他们是一个链表
为什么返回x是尾节点 返回head是头节点呢?
(我有尝试去理解 因为在去重函数中  head一直没有产生变化 只在最开始被x指向了一次  所以一直是头节点
然后x节点位置 也就是每次循环x当前节点在向后推,推移到最后一个节点 所以返回出去的是最后一个节点
return出去的x也只是这个单链表的最后一个节点的指针地址? 最开始我一直想成return出去的x是一个单链表。。所以我最开始的想法是错误的,现在的理解正确吗)



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

  3. struct Node
  4. {
  5.         int value;
  6.         struct Node *next;
  7. };

  8. void printNode(struct Node *head);
  9. void insertNode(struct Node **head, int value);
  10. struct Node *deleteNode(struct Node *head);


  11. void insertNode(struct Node **head, int value)
  12. {
  13.         struct Node *previous;//current上一个节点的指针
  14.         struct Node *current;//当前位置   指向比value大的节点指针
  15.         struct Node *new;
  16.        
  17.         current = *head;
  18.         previous = NULL;
  19.        
  20.         while(current != NULL && current->value < value)
  21.         {
  22.                 previous = current;
  23.                 current = current->next;
  24.         }
  25.         new = (struct Node *)malloc(sizeof(struct Node));
  26.         if(new == NULL)
  27.         {
  28.                 printf("内存分配失败!\n");
  29.                 exit(1);
  30.         }
  31.        
  32.         new->value = value;
  33.         //previous->next = new;  这个先不用写 后面要判断他是不是为NULL
  34.         new->next = current;
  35.        
  36.         if(previous == NULL)//previous为NULL只有一种情况(因为把current赋值给previous 且current不为NULL才能赋值)
  37.                             //所以current本身一进来就为NULL 空的单链表
  38.         {
  39.                 *head = new;//所以将*head指针修改为new    这个new是唯一一个节点

  40.         }
  41.         else
  42.         previous->next = new;


  43. }

  44. void printNode(struct Node *head)
  45. {
  46.         struct Node *current;
  47.        
  48.         current = head;
  49.         while(current != NULL)
  50.         {
  51.                 printf("%d ",current->value);
  52.                 current = current->next;

  53.         }
  54.         putchar('\n');

  55. }

  56. struct Node *deleteNode(struct Node *head)
  57. {
  58.        
  59.          if(head == NULL)
  60.         {
  61.             return head;
  62.         }
  63.         
  64.         struct Node *x = head;

  65.        
  66.         while(x->next != NULL)
  67.         {
  68.                 if(x->value == x->next->value)
  69.                 {
  70.                         x->next = x->next->next;
  71.                 }
  72.                 else
  73.                 {
  74.                         x = x->next;
  75.                 }
  76.         }
  77.        
  78.         return x;

  79. }


  80. int main(void)
  81. {
  82.         struct Node *head = NULL;
  83.         int input;
  84.        
  85.         while(1)
  86.         {
  87.                 printf("请输入一个整数(输入-1表示结束):");
  88.                 scanf("%d",&input);
  89.                 if(input == -1)
  90.                 {
  91.                         break;       
  92.                 }
  93.                 insertNode(&head, input);
  94.                
  95.         }  
  96.         printf("输入的单链表是:");
  97.         printNode(head);
  98.         printf("去重之后的单链表是:");
  99.         printNode(deleteNode(head));
  100.        
  101.         return 0;
  102. }



复制代码
最佳答案
2023-4-11 20:56:41
您目前的理解是正确的。在deleteNode函数中,x和head指向同一个链表。

x在函数中用于遍历和更新链表,当遍历完成时,x指向链表的尾节点。所以在函数中返回x时,实际上返回的是链表尾节点的指针地址。

而head始终指向链表的头节点,所以正确的返回值应该是head。

为了修复deleteNode函数,您应该在函数最后返回head,而不是x:

  1. struct Node *deleteNode(struct Node *head)
  2. {
  3.     if(head == NULL)
  4.     {
  5.         return head;
  6.     }
  7.    
  8.     struct Node *x = head;

  9.     while(x->next != NULL)
  10.     {
  11.         if(x->value == x->next->value)
  12.         {
  13.             x->next = x->next->next;
  14.         }
  15.         else
  16.         {
  17.             x = x->next;
  18.         }
  19.     }
  20.    
  21.     return head;
  22. }
复制代码


这样修改后,您的程序将能够正确地去除链表中的重复元素并输出结果。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-4-11 20:56:41 | 显示全部楼层    本楼为最佳答案   
您目前的理解是正确的。在deleteNode函数中,x和head指向同一个链表。

x在函数中用于遍历和更新链表,当遍历完成时,x指向链表的尾节点。所以在函数中返回x时,实际上返回的是链表尾节点的指针地址。

而head始终指向链表的头节点,所以正确的返回值应该是head。

为了修复deleteNode函数,您应该在函数最后返回head,而不是x:

  1. struct Node *deleteNode(struct Node *head)
  2. {
  3.     if(head == NULL)
  4.     {
  5.         return head;
  6.     }
  7.    
  8.     struct Node *x = head;

  9.     while(x->next != NULL)
  10.     {
  11.         if(x->value == x->next->value)
  12.         {
  13.             x->next = x->next->next;
  14.         }
  15.         else
  16.         {
  17.             x = x->next;
  18.         }
  19.     }
  20.    
  21.     return head;
  22. }
复制代码


这样修改后,您的程序将能够正确地去除链表中的重复元素并输出结果。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-4-11 21:32:06 | 显示全部楼层
isdkz 发表于 2023-4-11 20:56
您目前的理解是正确的。在deleteNode函数中,x和head指向同一个链表。

x在函数中用于遍历和更新链表,当 ...

那如果这个题不是开始让我以顺序录入链表,如果是随机的链表值 如
1 2 1 2 5 8 5 8 1 2 3 这样不是相邻的 该如何去重呢?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-4-11 21:37:16 | 显示全部楼层
a905448839 发表于 2023-4-11 21:32
那如果这个题不是开始让我以顺序录入链表,如果是随机的链表值 如
1 2 1 2 5 8 5 8 1 2 3 这样不是相邻 ...

如果链表中的元素是无序的,您可以使用双重循环遍历链表以去除重复元素。

下面是一个修改后的 deleteNode 函数,它可以处理无序链表中的重复元素:

  1. struct Node *deleteNode(struct Node *head)
  2. {
  3.     if(head == NULL)
  4.     {
  5.         return head;
  6.     }
  7.    
  8.     struct Node *current = head;
  9.     struct Node *inner_current, *prev;

  10.     while (current != NULL)
  11.     {
  12.         inner_current = current->next;
  13.         prev = current;
  14.         while (inner_current != NULL)
  15.         {
  16.             if (current->value == inner_current->value)
  17.             {
  18.                 prev->next = inner_current->next;
  19.                 free(inner_current);
  20.                 inner_current = prev->next;
  21.             }
  22.             else
  23.             {
  24.                 prev = inner_current;
  25.                 inner_current = inner_current->next;
  26.             }
  27.         }
  28.         current = current->next;
  29.     }
  30.    
  31.     return head;
  32. }
复制代码


这个函数使用双重循环遍历链表。外层循环 (current) 从头节点开始,内层循环 (inner_current) 从 current 的下一个节点开始。

在内层循环中,如果找到与 current 节点值相同的 inner_current 节点,就将其从链表中删除并释放内存。外层循环继续处理下一个节点,直到遍历完整个链表。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-4-12 00:29:22 From FishC Mobile | 显示全部楼层
isdkz 发表于 2023-4-11 21:37
如果链表中的元素是无序的,您可以使用双重循环遍历链表以去除重复元素。

下面是一个修改后的 deleteN ...

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-10 01:42

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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