c中的链接列表添加到前面

时间:2015-03-28 15:38:39

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

所以我真的很困惑。我正在尝试编写一个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;

行...所以我包括在调试步骤中获得的地址: 所以...在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中存储的对象的值,所以任何关于如何做的建议都会不胜感激。

2 个答案:

答案 0 :(得分:3)

在功能中

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->member = y指向该节点的成员。它会起作用,因为你改变了被指向的变量(即使它们是指针 - 你可以改变这些指针[它们指向的地址]因为你有一个指向它们的指针而你取消引用那个指针)。

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

答案 1 :(得分:1)

你需要

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

请注意*

的两个root

这允许您在此功能之外修改root