a905448839 发表于 2023-4-11 20:53:53

爱学习的我又来啦!麻烦大佬帮忙看看!谢谢

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



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

struct Node
{
        int value;
        struct Node *next;
};

void printNode(struct Node *head);
void insertNode(struct Node **head, int value);
struct Node *deleteNode(struct Node *head);


void insertNode(struct Node **head, int value)
{
        struct Node *previous;//current上一个节点的指针
        struct Node *current;//当前位置   指向比value大的节点指针
        struct Node *new;
       
        current = *head;
        previous = NULL;
       
        while(current != NULL && current->value < value)
        {
                previous = current;
                current = current->next;
        }
        new = (struct Node *)malloc(sizeof(struct Node));
        if(new == NULL)
        {
                printf("内存分配失败!\n");
                exit(1);
        }
       
        new->value = value;
        //previous->next = new;这个先不用写 后面要判断他是不是为NULL
        new->next = current;
       
        if(previous == NULL)//previous为NULL只有一种情况(因为把current赋值给previous 且current不为NULL才能赋值)
                            //所以current本身一进来就为NULL 空的单链表
        {
                *head = new;//所以将*head指针修改为new    这个new是唯一一个节点

        }
        else
        previous->next = new;


}

void printNode(struct Node *head)
{
        struct Node *current;
       
        current = head;
        while(current != NULL)
        {
                printf("%d ",current->value);
                current = current->next;

        }
        putchar('\n');

}

struct Node *deleteNode(struct Node *head)
{
       
       if(head == NULL)
      {
            return head;
      }
      
        struct Node *x = head;

       
        while(x->next != NULL)
        {
                if(x->value == x->next->value)
                {
                        x->next = x->next->next;
                }
                else
                {
                        x = x->next;
                }
        }
       
        return x;

}


int main(void)
{
        struct Node *head = NULL;
        int input;
       
        while(1)
        {
                printf("请输入一个整数(输入-1表示结束):");
                scanf("%d",&input);
                if(input == -1)
                {
                        break;       
                }
                insertNode(&head, input);
               
        }
        printf("输入的单链表是:");
        printNode(head);
        printf("去重之后的单链表是:");
        printNode(deleteNode(head));
       
        return 0;
}



isdkz 发表于 2023-4-11 20:56:41

您目前的理解是正确的。在deleteNode函数中,x和head指向同一个链表。

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

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

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

struct Node *deleteNode(struct Node *head)
{
    if(head == NULL)
    {
      return head;
    }
   
    struct Node *x = head;

    while(x->next != NULL)
    {
      if(x->value == x->next->value)
      {
            x->next = x->next->next;
      }
      else
      {
            x = x->next;
      }
    }
   
    return head;
}

这样修改后,您的程序将能够正确地去除链表中的重复元素并输出结果。

a905448839 发表于 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 这样不是相邻的 该如何去重呢?

isdkz 发表于 2023-4-11 21:37:16

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

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

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

struct Node *deleteNode(struct Node *head)
{
    if(head == NULL)
    {
      return head;
    }
   
    struct Node *current = head;
    struct Node *inner_current, *prev;

    while (current != NULL)
    {
      inner_current = current->next;
      prev = current;
      while (inner_current != NULL)
      {
            if (current->value == inner_current->value)
            {
                prev->next = inner_current->next;
                free(inner_current);
                inner_current = prev->next;
            }
            else
            {
                prev = inner_current;
                inner_current = inner_current->next;
            }
      }
      current = current->next;
    }
   
    return head;
}

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

在内层循环中,如果找到与 current 节点值相同的 inner_current 节点,就将其从链表中删除并释放内存。外层循环继续处理下一个节点,直到遍历完整个链表。

a905448839 发表于 2023-4-12 00:29:22

isdkz 发表于 2023-4-11 21:37
如果链表中的元素是无序的,您可以使用双重循环遍历链表以去除重复元素。

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

感谢!
页: [1]
查看完整版本: 爱学习的我又来啦!麻烦大佬帮忙看看!谢谢