1

我是一个新学习者,正在尝试建立链表。我可以这样做,但我试图保留根节点或第一个节点的指针,因此在构建链表后,我可以读取列表或执行模式匹配,但我无法成功。你能在这里帮忙吗?

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

struct node {    
    int x;
    struct node *next;
};

int main(){

    int d;
    struct node *linked;
    struct node *head;

    linked = malloc (sizeof(struct node));

    head = linked;   <<<< As this is pointer, in while loop whenever malloc executes it changes the value of head as well.
    printf ("Location of head %p \n", head->next);

    d = 1;
    while (d>0){

        printf ("Enter the value of X: ");
        scanf ("%d", &linked->x);

        linked->next = malloc (sizeof(struct node));
        printf ("Location of linked %p \n", linked->next);

        printf ("Location of head %p \n", head->next);

        printf ("To enter further value enter non zero: ");
        scanf ("%d", &d);

        if (d==0)
            linked->next = NULL;
    }

    //linked->next = NULL;

    printf("Value of Next is %p\n", linked->next);        
    printf ("Location of head %p \n", head->next);        
}

输出:

MacBook-Air:cprog jimdev$ ./a.out

头部位置 0x7fff90ab952c <<<< 这个值不应该改变,但在随后的输出中它是。

输入 X 的值:0

链接 0x7ff0624039c0 ​​的位置

头部位置 0x7ff0624039c0 ​​<<<< 与前一个不同的值

要输入更多值,请输入非零:3

输入 X 的值:3

链接 0x7ff0624039d0 的位置

头部位置 0x7ff0624039d0 <<<< 与前一个不同的值

要输入更多值,请输入非零:0

Next 的值为 0x0

头 0x0 的位置

我刚刚尝试了这个新的,它也执行链表元素的 printf,如果你们想到任何改进,请告诉我。我知道递归是实现它的快速而简洁的方法,但我想用 while 循环尝试一些东西。

包括

包括

结构节点{

    int x;
    struct node *next;
    };

诠释主要(){

    int d, hold, i;
    struct node *list;
    struct node *head;
    struct node *current;



    list = (node *)malloc(sizeof(struct node));
    head = list;
    printf ("Location of list is %p \n", head);
    d = 1;

而(d>0){

    printf ("Enter the value of X: ");
    scanf ("%d", &list->x);
    printf ("Location of list is %p\n", list);
    current = (node *)malloc (sizeof (struct node));
    list->next = current;
    list = current;

    printf ("Location of head is %p\n", head);


    printf ("Enter zero to terminate the loop: ");
    scanf ("%d", &d);

    }
    list->next = NULL;
    printf ("Value of last next is %d\n", list->next);

    current = head;

    i = 1;
    while (current->next != 0){
          printf ("Location of list is %p \n", current);
          printf ("Value of linked list %d elements %d \n", i, current->x);
          current = current->next;
          i++;
          }

    scanf ("%d", &hold);

}

4

4 回答 4

2

2件事:

  1. 你正在输出head->next而不是仅仅head

  2. 你没有更新linkedlinked->next

链表的头节点是链表的第一个元素。head->next,当链表格式正确时,是第二个元素。无论哪种方式,它都不应该改变,因为列表是在创建后创建的。

如果您没有更新linked,那么linked->next您只是在丢弃刚刚分配的内存linked->next而不是创建列表。

这有效:

int d;
struct node *linked;
struct node *head;

linked = malloc(sizeof(struct node));

head = linked;
printf ("Location of head %p \n", head);//changed head->next to head

d = 1;
while (d>0){

    printf ("Enter the value of X: ");
    scanf ("%d", &linked->x);

    linked->next = malloc (sizeof(struct node));
    printf ("Location of linked %p \n", linked->next);

    printf ("Location of head %p \n", head);// changed head->next to head

    printf ("To enter further value enter non zero: ");
    scanf ("%d", &d);

    linked = linked->next; //this was added
    if (d==0)
        linked->next = NULL;
}

您的代码,因为它没有更新,所以linked保持不变。您的列表如下所示:headlinked

节点 {x:next}

           -> {x2:NULL}
           -> {x3:NULL}
{x1:node2} -> {x4:NULL}
    ^^            ^^
(head and linked)   you're outputing this node both times  

由于您没有任何指向 node2 或 node3 的指针,因此您会丢失这些节点(内存泄漏)。

你几乎是对的。这是使用此代码生成的列表的样子:

{x1:node2} -> {x2:node3} -> {x3:node4} -> {x4:node5}
   ^^           ^^                           ^^
  head        head->next                   linked

更新:

我为您的代码更改了图表,以更好地反映正在发生的事情。

ptr->varname运算符在 指向的位置查找的ptrvarname。因此,如果指针的值相同,那么您将在相同的空间中查找变量。在您的情况下,head=linked意味着如果您设置linked->next = ptrthen head->next = ptr,并且因为linked从未更新为linked->next(因此head->next),那么您只是在分配和重新分配linked->next

于 2013-02-08T04:40:54.183 回答
1

head 的值只能在使用链表时设置并且永远不要更改。如果你改变 head 的值,那么所有的链接都会“脱落”并且垃圾收集器会吃掉它们。链表应该遵循这种格式。

第一个节点是头,设置为当前节点

节点二设置为头节点的下一个指针INSIDE,节点二也设置为当前节点

节点三设置为节点二的下一个指针INSIDE,节点三设置为当前节点指针。

洗涤/漂洗/重复

永远不要改变头节点

于 2013-02-08T04:12:18.597 回答
1

你并不是真的在这里“建立”一个链表,原因我将在下一段解释......至于你关于head指针的问题,你一直在打印与指针不同的head->nexthead。如果您打印出 的值head,您会发现它从未随着时间的推移而改变,因为您从未明确修改过它。

我可以看到您犯的最大错误是,在分配内存并将指针值分配linked给. 所以发生的事情是你不断地为 分配新的内存块,这与 的值相同,反过来又造成内存泄漏,因为你失去了对先前分配的由 指向的内存块的引用。所以你会想要这样的东西:linked->nextlinked->nextlinked->nexthead->nextlinked->next

linked->next = malloc(sizeof(struct node));
linked = linked->next;

使用这种方法,您将保持循环不变,其中linked始终指向列表中的最后一个节点,因此,您将新节点附加到列表的末尾,并且不会丢失对节点的引用。此外,您将能够从head指针遍历列表,因为它从未更改过(它指向列表中的第一个节点)。

于 2013-02-08T04:16:01.063 回答
1

这是我为想要编写双向链表程序的新手编写的示例。您可以参考它。正如 AMR 已经正确指出的那样,您的 Head 应该保持不变(假设您在列表的末尾而不是在前面插入元素)。

这里 head 被实现为 global 。拥有全局变量可能并不总是一个好主意。在这种情况下,将头传递给您的 insert_element_into_list 函数(),例如

插入元素(头部,项目)

struct node {
    int d;
    node *llink;
    node *rlink;
};
typedef struct node* Node;
Node head = NULL;

void linked_list_init(int);
void linked_list_print();

void linked_list_init(int data) {

    Node newnode = (Node) malloc(sizeof (Node));
    newnode->d = data;

    Node curr;

    if (head == NULL) {

        newnode->llink = NULL;
        newnode->rlink = NULL;
        head = newnode;

    } else {
        curr = head;
        while (curr->rlink) {
            curr = curr->rlink;
        }
        curr->rlink = newnode;
        newnode->rlink = NULL;
        newnode->llink = curr;       
    }
}

void linked_list_print() {
    Node curr;
    curr = head;
    while (curr) {
        printf("Element Data : %d", curr->d);
        curr = curr->rlink;
    }
}
于 2013-02-08T04:51:24.933 回答