鱼C论坛

 找回密码
 立即注册
查看: 1013|回复: 5

[已解决]一个单链表demo求助

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

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

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

x
一个单链表demo.c


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

  3. struct LinkList
  4. {
  5.     int num;
  6.     struct LinkList *next;
  7. };

  8. struct LinkList * initLinkList(struct LinkList **pHeader, struct LinkList **pTail)
  9. {
  10.     struct LinkList *newNode;
  11.    
  12.     newNode = malloc(sizeof(struct LinkList));
  13.     if(newNode == NULL)
  14.     {
  15.         perror("Memory failure\n");
  16.         exit(EXIT_FAILURE);
  17.     }
  18.     newNode->num = -1;
  19.     newNode->next = NULL;
  20.    
  21.     *pHeader = newNode;
  22.     *pTail = newNode;
  23.    
  24.     return newNode;
  25. }


  26. void inserNode(struct LinkList* pTail)
  27. {
  28.     int newNodeNum;
  29.     struct LinkList *newNode;   
  30.    
  31.     while (1)
  32.     {
  33.         printf("input a number(-1 to quit): ");
  34.         scanf("%d", &newNodeNum);
  35.         
  36.         if (newNodeNum == -1)
  37.         {
  38.             return;
  39.         }
  40.         
  41.         newNode = malloc(sizeof(struct LinkList));
  42.         newNode->num = newNodeNum;
  43.         newNode->next = NULL;
  44.         
  45.         pTail->next = newNode;
  46.         pTail = newNode;
  47.     }
  48. }

  49. void forEachNode(struct LinkList *pHeader)
  50. {
  51.     if ( !pHeader->next )
  52.     {
  53.         return;
  54.     }
  55.    
  56.     struct LinkList *pCurrent = pHeader->next;
  57.     do
  58.     {
  59.         printf("%d\n", pCurrent->num);
  60.         pCurrent = pCurrent->next;
  61.     }while (pCurrent);
  62. }


  63. void test01()
  64. {
  65.     struct LinkList *pHeader = NULL;
  66.     struct LinkList *pTail = NULL;
  67.    
  68.     initLinkList(&pHeader, &pTail);
  69.    
  70.     //第一次插入
  71.     inserNode(pTail);
  72.     forEachNode(pHeader);
  73.    
  74.     //第二次插入
  75.     inserNode(pTail);
  76.     forEachNode(pHeader);

  77. }

  78. int main(void)
  79. {
  80.     test01();
  81.    
  82.     return 0;
  83. }
复制代码


现在问题是第二次插入后再遍历链表时只会打印第二次插入的数据,  不会把两次的数据都打印出来, 问题出在哪?
最佳答案
2023-12-16 20:16:30
问题出在`inserNode()`函数中。在第一次插入节点后,虽然我们将尾节点`pTail`更新为新插入的节点,但是头节点`pHeader`仍然指向原来的头节点。所以在第二次插入节点时,是从原来的头节点开始遍历的,而没有遍历到新插入的节点。

解决这个问题可以修改`inserNode()`函数,让它返回新插入的节点,并在每次插入节点后更新尾节点`pTail`为新插入的节点。同时,在`test01()`函数中,第一次插入后,将头节点`pHeader`更新为第一个插入的节点。这样在第二次插入时,就会从第一个插入的节点开始遍历。

修改后的代码如下:


#include
#include

struct LinkList
{
    int num;
    struct LinkList *next;
};

struct LinkList * initLinkList(struct LinkList **pHeader, struct LinkList **pTail)
{
    struct LinkList *newNode;
   
    newNode = malloc(sizeof(struct LinkList));
    if(newNode == NULL)
    {
        perror("Memory failure\n");
        exit(EXIT_FAILURE);
    }
    newNode->num = -1;
    newNode->next = NULL;
   
    *pHeader = newNode;
    *pTail = newNode;
   
    return newNode;
}


struct LinkList* inserNode(struct LinkList* pTail)
{
    int newNodeNum;
    struct LinkList *newNode;   
   
    while (1)
    {
        printf("input a number(-1 to quit): ");
        scanf("%d", &newNodeNum);
        
        if (newNodeNum == -1)
        {
            return pTail; // 返回最新的尾节点
        }
        
        newNode = malloc(sizeof(struct LinkList));
        newNode->num = newNodeNum;
        newNode->next = NULL;
        
        pTail->next = newNode;
        pTail = newNode;
    }
   
    return pTail; // 没有插入时,返回原来的尾节点
}

void forEachNode(struct LinkList *pHeader)
{
    if ( !pHeader->next )
    {
        return;
    }
   
    struct LinkList *pCurrent = pHeader->next;
    do
    {
        printf("%d\n", pCurrent->num);
        pCurrent = pCurrent->next;
    }while (pCurrent);
}


void test01()
{
    struct LinkList *pHeader = NULL;
    struct LinkList *pTail = NULL;
   
    pTail = initLinkList(&pHeader, &pTail); // 初始化链表
   
    //第一次插入,并更新头节点
    pTail = inserNode(pTail);
    pHeader = pHeader->next;
    forEachNode(pHeader);
   
    //第二次插入
    pTail = inserNode(pTail);
    forEachNode(pHeader);

}

int main(void)
{
    test01();
   
    return 0;
}

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-12-16 20:16:30 | 显示全部楼层    本楼为最佳答案   
问题出在`inserNode()`函数中。在第一次插入节点后,虽然我们将尾节点`pTail`更新为新插入的节点,但是头节点`pHeader`仍然指向原来的头节点。所以在第二次插入节点时,是从原来的头节点开始遍历的,而没有遍历到新插入的节点。

解决这个问题可以修改`inserNode()`函数,让它返回新插入的节点,并在每次插入节点后更新尾节点`pTail`为新插入的节点。同时,在`test01()`函数中,第一次插入后,将头节点`pHeader`更新为第一个插入的节点。这样在第二次插入时,就会从第一个插入的节点开始遍历。

修改后的代码如下:


#include
#include

struct LinkList
{
    int num;
    struct LinkList *next;
};

struct LinkList * initLinkList(struct LinkList **pHeader, struct LinkList **pTail)
{
    struct LinkList *newNode;
   
    newNode = malloc(sizeof(struct LinkList));
    if(newNode == NULL)
    {
        perror("Memory failure\n");
        exit(EXIT_FAILURE);
    }
    newNode->num = -1;
    newNode->next = NULL;
   
    *pHeader = newNode;
    *pTail = newNode;
   
    return newNode;
}


struct LinkList* inserNode(struct LinkList* pTail)
{
    int newNodeNum;
    struct LinkList *newNode;   
   
    while (1)
    {
        printf("input a number(-1 to quit): ");
        scanf("%d", &newNodeNum);
        
        if (newNodeNum == -1)
        {
            return pTail; // 返回最新的尾节点
        }
        
        newNode = malloc(sizeof(struct LinkList));
        newNode->num = newNodeNum;
        newNode->next = NULL;
        
        pTail->next = newNode;
        pTail = newNode;
    }
   
    return pTail; // 没有插入时,返回原来的尾节点
}

void forEachNode(struct LinkList *pHeader)
{
    if ( !pHeader->next )
    {
        return;
    }
   
    struct LinkList *pCurrent = pHeader->next;
    do
    {
        printf("%d\n", pCurrent->num);
        pCurrent = pCurrent->next;
    }while (pCurrent);
}


void test01()
{
    struct LinkList *pHeader = NULL;
    struct LinkList *pTail = NULL;
   
    pTail = initLinkList(&pHeader, &pTail); // 初始化链表
   
    //第一次插入,并更新头节点
    pTail = inserNode(pTail);
    pHeader = pHeader->next;
    forEachNode(pHeader);
   
    //第二次插入
    pTail = inserNode(pTail);
    forEachNode(pHeader);

}

int main(void)
{
    test01();
   
    return 0;
}

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-16 20:37:28 | 显示全部楼层
FishC 发表于 2023-12-16 20:16
问题出在`inserNode()`函数中。在第一次插入节点后,虽然我们将尾节点`pTail`更新为新插入的节点,但是头节 ...

第二次的数据是能接上了, 不过有个bug, 第一次输入的第一个数据不在了.
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-12-16 20:37:51 | 显示全部楼层
七彩云南 发表于 2023-12-16 20:37
第二次的数据是能接上了, 不过有个bug, 第一次输入的 ...

抱歉,我之前的回答有误。问题出在`inserNode()`函数中,在插入第一个节点时并没有更新头节点`pHeader`,导致第一个节点丢失。要解决这个问题,需要在`inserNode()`函数中判断链表是否为空,如果为空则更新头节点。修改后的代码如下:
  1. #include #include struct LinkList{ int num; struct LinkList *next;};struct LinkList * initLinkList(struct LinkList **pHeader, struct LinkList **pTail){ struct LinkList *newNode; newNode = malloc(sizeof(struct LinkList)); if(newNode == NULL) { perror("Memory failure\n"); exit(EXIT_FAILURE); } newNode->num = -1; newNode->next = NULL; *pHeader = newNode; *pTail = newNode; return newNode;}void inserNode(struct LinkList** pHeader, struct LinkList** pTail){ int newNodeNum; struct LinkList *newNode; printf("input a number(-1 to quit): "); scanf("%d", &newNodeNum); while (newNodeNum != -1) { newNode = malloc(sizeof(struct LinkList)); newNode->num = newNodeNum; newNode->next = NULL; if (*pHeader == NULL) { *pHeader = newNode; *pTail = newNode; } else { (*pTail)->next = newNode; *pTail = newNode; } printf("input a number(-1 to quit): "); scanf("%d", &newNodeNum); }}void forEachNode(struct LinkList *pHeader){ if ( !pHeader ) { return; } struct LinkList *pCurrent = pHeader; do { printf("%d\n", pCurrent->num); pCurrent = pCurrent->next; }while (pCurrent);}void test01(){ struct LinkList *pHeader = NULL; struct LinkList *pTail = NULL; pTail = initLinkList(&pHeader, &pTail); // 初始化链表 inserNode(&pHeader, &pTail); forEachNode(pHeader);}int main(void){ test01(); return 0;}
复制代码
在`inserNode()`函数中,添加了两个指针的指针作为参数,以便可以修改头节点和尾节点的指针。同时,在每次插入节点前,先判断链表是否为空,如果为空则更新头节点。这样就可以正确插入节点,并打印出所有节点的数据了。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-16 20:42:53 | 显示全部楼层
FishC 发表于 2023-12-16 20:16
问题出在`inserNode()`函数中。在第一次插入节点后,虽然我们将尾节点`pTail`更新为新插入的节点,但是头节 ...

找到原因了~
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-12-16 20:43:05 | 显示全部楼层

太棒了!如果你还有任何其他问题,都可以随时向我提问。我会尽力帮助你。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-4-19 11:05

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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