【问题标题】:Linked List in c add to frontc中的链表添加到前面
【发布时间】:2015-06-01 20:43:35
【问题描述】:

所以我真的很困惑。我正在尝试编写一个 c 方法,该方法允许我将新的“节点”添加到链表的前面。我以前在 C++ 中做过这个,没问题。我很沮丧,因为在编写代码后我很确定我是对的变量的值。代码如下:

真正的功能是:

void addToBeginning(int value, struct node* root){
    struct node* newNode;
    newNode = malloc( sizeof(struct node));
    newNode->value = value;
    newNode->next = root;
    root = newNode;
}

但这里是完整的代码。我删除了一些内容以使其更简洁(回答此问题不需要的内容,例如 getLength(...) 和 addToPos(...))

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

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

void printLinkedList(struct node* root);

void addToEnd(int value, struct node* root);

void addToBeginning(int value, struct node* root);

void addToPos(int pos, int value, struct node* root);

int getLength(struct node* root);


int main(){        
    /**
     TESTING addToBeginning (I know addToEnd works)
     **/

    struct node *root2;
    root2 = malloc( sizeof(struct node));
    root2->value = 4;
    root2->next = NULL;

    /*
     root2 = 4 -> 0 -> 0 -> 0 -> 0 -> 0 -> 0
     */
    i = 0;
    while (i < 5){
        addToEnd(0,root2);
        i++;
    }

    printLinkedList(root2);
    //printf("Length : %d\n",getLength(root2));

    /*
     expected root2 = 2 -> 4 -> 0 -> 0 -> 0 -> 0 -> 0
     */
    addToBeginning(2, root2);
    printLinkedList(root2);
    /*
     obtained root2 = 4 -> 0 -> 0 -> 0 -> 0 -> 0 -> 0
     */
    //printf("Length : %d\n",getLength(root2));

    return(0);
}

void printLinkedList(struct node* root){
    while(root != NULL){
        if (root->next != NULL){
            printf("%d, ",root->value);
            root=root->next;
        } else {
            printf("%d\n",root->value);
            root=root->next;
        }
    }

}

void addToEnd(int value, struct node* root){
    /*
     Set up new node
     */
    struct node* newNode = malloc( sizeof(struct node));
    newNode->value = value;
    newNode->next = NULL;

    /*
     Check if empty linked list first
     */
    if (root->next == NULL){
        root->next = newNode;
    } else {
        /*
         Find the last node
         */
        struct node* current = root;
        while(current->next != NULL){
            current = current->next;
        }
        current->next = newNode;
    }
}

void addToBeginning(int value, struct node* root){
    struct node* newNode;
    newNode = malloc( sizeof(struct node));
    newNode->value = value;
    newNode->next = root;
    root = newNode;
}

令人困惑的是,我觉得在

newNode->next = root;
root = newNode;

lines...所以我包括在调试步骤中获得的地址: 所以...在addToBeginning(int value, struct node* root){...} 函数中,我将逐步完成:

执行后:

struct node* newNode;
newNode = malloc( sizeof(struct node));

root和newNode的地址和值是:

root = 0x0000000100103c60
root->next = 0x0000000100103c70
root->value = 4
newNode = 0x0000000100103cc0
newNode->next = NULL
newNode->value = 0

执行后:

newNode->value = value;

root和newNode的地址和值是:

root = 0x0000000100103c60
root->next = 0x0000000100103c70
root->value = 4
newNode = 0x0000000100103cc0
newNode->next = NULL
newNode->value = 2

执行后:

newNode->next = root;

root和newNode的地址和值是:

root = 0x0000000100103c60
root->next = 0x0000000100103c70
root->value = 4
newNode = 0x0000000100103cc0
newNode->next = 0x0000000100103c60
newNode->value = 2

执行后:

root = newNode;

root和newNode的地址和值是:

root = 0x0000000100103cc0
root->next = 0x0000000100103c60
root->value = 2
newNode = 0x0000000100103cc0
newNode->next = 0x0000000100103c60
newNode->value = 2

我意识到问题在于 *root 是通过引用传递的,所以我需要做的是更改存储在位置 0x0000000100103c60 中的对象的值,因此任何有关如何做到这一点的建议将不胜感激。

【问题讨论】:

  • 你在insert函数中修改了root的本地副本;您不修改调用代码中的相应值。要么从函数返回列表的新头,要么将指向根节点的指针传递给函数,以便可以在函数中修改指向根节点的指针。在 SO 上有很多很多类似的问题与相同的基本问题。
  • 宾果游戏。谢谢@JonathanLeffler,我只需要听到一个指向指针的指针!
  • 天啊!!!一个带有调试步骤的链表问题解释!投赞成票。我得买一张彩票。
  • 请注意,main() 中用于创建节点的代码是 struct node *root2; root2 = malloc( sizeof(struct node)); root2-&gt;value = 4; root2-&gt;next = NULL;,并且您的 addToBeginning()addToEnd() 代码中的代码几乎相同。这可能应该被抽象成一个struct node *newElement(int value); 函数。然后,您可以在一处添加对 malloc() 故障的错误检查,而不必在三个不同的地方进行。

标签: c pointers linked-list singly-linked-list


【解决方案1】:

在函数中

void addToBeginning(int value, struct node* root){
    struct node* newNode;
    (...)
    root = newNode;
}

struct node *root2;
addToBeginning(2, root2);

您将新地址分配给本地根指针。该指针与原始根指针具有相同的值,但它是它的副本。因此,在函数返回后更改函数内部的变量对原始根没有影响。

相反,您必须逐个指针传递:

void addToBeginning(int value, struct node **root){
    struct node* newNode;
    (...)
    *root = newNode;
}

struct node *root2;
addToBeginning(2, &root2);

其他信息

这可能会令人惊讶。当您想更改原始变量时,您不是总是将指针传递给函数吗?好吧,是的,但是指向的是变量-而不是指针本身。在这里,假设您的原始函数采用指针(不是指向指针的指针),您仍然可以将 root2 指向的原始节点更改为 *root2 = x 或将该节点的成员更改为 root2-&gt;member = y。它会起作用,因为您更改了指向的变量(即使它们是指针 - 您可以更改这些指针 [它们指向的地址],因为您有一个指向它们的指针并且您取消引用该指针)。

这同样适用于作为变量的指针。如果要更改原始指针,则必须指向它并更改指向的变量,在这种情况下为原始指针。

【讨论】:

  • 完全正确并将root作为&root传递
【解决方案2】:

你需要

void addToBeginning(int value, struct node** root)

注意两个* 代表root

这允许您在此函数之外修改root

【讨论】:

    猜你喜欢
    • 2016-09-05
    • 2011-06-20
    • 1970-01-01
    • 2016-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-16
    • 1970-01-01
    相关资源
    最近更新 更多