C中的循环链表没有给出所需的输出

时间:2013-09-20 04:30:06

标签: c pointers linked-list

我想在C中制作循环链表,但我遇到了一些麻烦。我很确定它是一个指针问题(我正在学习C和指针是一个弱点)。这是代码:

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

nodeptr add_to_end(nodeptr head, int val)
{
    if (head == NULL)
    {
        nodeptr new_node = (nodeptr)malloc(sizeof(node));
        new_node->data = val;
        new_node->next = NULL;
        return new_node;
    } else {
        head->next = add_to_end(head->next,val);
        return head;
    }
}


void print_piles(nodeptr nodeHead)
{
    if (nodeHead == NULL)
        return;
    printf("%d\n ",nodeHead->data);
    print_piles(nodeHead->next);
}



int main(int argc, char *argv[])
{
    nodeptr head = NULL;
    nodeptr tail = NULL;
    int i = 0;

    head = add_to_end(head,i);
    i++;
    tail = add_to_end(tail,i);
    head->next = tail;
    i++;
    tail = add_to_end(tail,i);
    tail->next = head;

    printf("%d\n ",head->data);
    printf("%d\n ",tail->data);
    tail = tail->next;
    printf("%d\n ",tail->data);
    return 0;
}

和cl.h:

// create struct for cards in piles
;typedef struct node
{
    int data;
    struct node *next;
}node, *nodeptr;

输出是:

0
1
0

我期望得到的是:

0
1
2

我需要改变什么?

4 个答案:

答案 0 :(得分:5)

不是指针问题!您正在获得定义的行为。但你循环链接的步骤是错误的。阅读下面我在main()函数中解释了您的步骤:

第1步:

i = 0;
head = add_to_end(head,i);

因此创建了一个head节点(假设节点地址为201):

head: 201
[ 0, NULL]

第2步:

i++;
tail = add_to_end(tail,i);

因此创建了一个tail节点(假设节点地址为304):

tail: 304
[ 1, NULL]

<强>步骤-3:
分配后:head->next = tail;:链接列表类似于:

head: 201     tail: 304 
[ 0, 304] --► [1, NULL]

<强>步骤-4: 遵循两个代码序列后:

i++;
tail = add_to_end(tail,i);

您已在链接列表中创建了一个新节点和附加节点,其值为2(假设为地址349),列表如下所示:

head: 201     tail: 304         : 349
[ 0, 304] --► [ 1, 349] --► [ 2, NULL]

<强>步骤5:
现在错误:根据您的添加功能,tail值仍为304,因此在最后一次分配tail->next = head;后,您会得到如下内容:

head: 201     tail: 304         : 349
[ 0, 304] --► [ 1, 349]    [ 2, NULL]
   ▲             |
   +-------------+  

所以 next of tail is head ,这就是为什么你的0, 1, 0作为输出。

另请注意,您有内存泄漏!

为什么会这样? add函数最后会附加一个节点并返回传递给你传递的函数head的{​​{1}}(我正在评论)。

tail

因此,当您调用nodeptr add_to_end(nodeptr head, int val) { // ^ is tail at third call if (head == NULL)// if first node is NULL { nodeptr new_node = (nodeptr)malloc(sizeof(node)); new_node->data = val; new_node->next = NULL; return new_node; <-- "return only if new node is first node" } else { head->next = add_to_end(head->next,val); return head; <--- "Return `head` that is passed to function at calling" } } tail = add_to_end(tail, i);不为NULL时,函数add_to_end将返回较旧的tail(在我的示例地址中为304)。

您应该将tail更正为tail->next = head;,您将获得例外结果。

答案 1 :(得分:0)

您需要添加
tail = tail->next介于这两行之间:

tail = add_to_end(tail,i);
tail->next = head;

并使用tail-&gt; next获取新节点。

因此,将主代码更新为 -

int main(int argc, char *argv[])
{
    nodeptr head = NULL;
    nodeptr tail = NULL;
    int i = 0;

    head = add_to_end(head,i);
    i++;
    tail = add_to_end(tail,i);
    head->next = tail;
    i++;

    // Add new node to current tail's next
    tail->next = add_to_end(tail,i);
    // Change tail to point to latest added node
    tail = tail->next
    tail->next = head;

    printf("%d\n ",head->data);
    printf("%d\n ",tail->data);
    tail = tail->next;
    printf("%d\n ",tail->data);
    return 0;
}

答案 2 :(得分:0)

如果您打算通过实现循环链​​接列表来学习C,那么您应该尝试正确实现它,而不是通过执行tail-&gt; next = header将非循环列表强制转换为循环列表,因为如果你尝试在列表之后添加一个项目,你将获得无限递归,有点无限循环,因为你的算法会检查一个NULL作为终止条件。

圆形列表,有一个指向头部和尾部的指针,当你通过比较当前节点到尾部到达最后一个节点时结束。

答案 3 :(得分:0)

int main(int argc, char *argv[])
{
    nodeptr head = NULL;
    nodeptr tail = NULL;
      nodeptr tail1 = NULL;

    int i = 0;

    head = add_to_end(head,i);
    i++;
    tail = add_to_end(tail,i);
    head->next = tail;
    i++;
    tail1 = add_to_end(tail1,i);
    tail->next = tail1;
    tail1->next= head;

    printf("%d\n ",head->data);
    printf("%d\n ",tail->data);
    tail = tail->next;
    printf("%d\n ",tail->data); 

    return 0;
}