从Linked-list弹出

时间:2013-08-27 02:44:25

标签: c pointers linked-list return pop

我在C:

中实现了一个带有Pop功能的Linked-List
Node * pop (Node * head) {
    Node * temp = head;

    printf("Temp is: %s\n", temp->val);

    if (head->next != NULL) {
        *head = *head->next;
    }

    printf("Temp is: %s\n", temp->val);
    return temp;
}

当我弹出时的输出将是:

Temp is: node1 value
Temp is: node2 value

也就是说,当我指定*head = *head->next时,临时正在变得临时 - >接下来。

那么如何获取当前head的值并将其返回,同时将链接列表的头部移动到head->next

执行head = head->next不会删除对第一个节点的引用。 (即当我打印列表时,第一个节点仍然存在)。

感谢。

5 个答案:

答案 0 :(得分:3)

首先,请注意您的代码(以及一些以前的解决方案)永远不会弹出列表中的最后一个元素。你想要

if (*head != NULL) ...

接下来,将指针传递给指针将起作用。但实际上制作这样的列表标题更好:

typedef struct node_s {
  struct node_s *next;
  ... data declaration here
} Node;

typedef struct list_s {
  struct node_s *head;
} List;

void init_list(List *list) {
  list->head = NULL;
}

现在声明一个这样的列表:

List list[1];

init_list(list);

声明一个元素的数组会自动引用list一个指针,从而消除了代码中的大量&个。然后实现推送和弹出很好很干净:

void push(List *list, Node *node) {
  node->next = list->head;
  list->head = node;
}

Node *pop(List *list) {
  Node *head = list->head;
  if (head) {
    list->head = head->next;
    head->next = NULL;
  }
  return head;
}

为什么这样更好?假设您稍后决定在列表中保留项目数。使用单独的标头节点,这非常简单:

typedef struct list_s {
  struct node_s *head;
  int length;
} List;

void init_list(List *list) {
  list->head = NULL;
  length = 0;
}

void push(List *list, Node *node) {
  node->next = list->head;
  list->head = node;
  ++list->length;
}

Node *pop(List *list) {
  Node *head = list->head;
  if (head) {
    list->head = head->next;
    head->next = NULL;
    --list->length;
  }
  return head;
}

注意不需要更改调用代码。随着指针接近指针,你处于死胡同。还有许多其他用例,其中有一个单独的列表标题可以使您的代码更灵活,以便将来进行更改。

答案 1 :(得分:2)

您需要为您的函数传递head的地址才能对其进行修改。然后你的函数需要取消引用这个地址。此外,最后一个pop()也需要更改* AddressOfHead

Node *pop(Node **AddressOfHead) {
    Node *temp = *AddressOfHead;
    if (temp) {
        *AddressOfHead = temp->next;
    }
    return temp;
}

...

// Usage example
Node *TopOfList = pop(&Head);

答案 2 :(得分:1)

指针按值传递。也就是说,当您将指针传递给堆栈时,调用函数中指针指向的内容的更改不会反映在调用函数中。

为了在调用函数中更改节点指针的值,您需要将堆栈作为指针传递给指针:

Node* pop (Node** head) {

    Node* temp = *head;    

    if (temp) {
       *head = temp->next;    // to update stack in calling function
       temp->next = NULL;     // to detach temp from the rest of the list
    }

    return temp;
}

在更新if ((*head)->next)的值之前,您不需要检查if (temp->next)或本例*head,因为如果您位于堆栈的最后一个节点并且下一个节点是NULL,您希望列表无论如何都是NULL

Karthik T的答案正确解释了为什么temp的价值在原始代码中发生了变化。

答案 3 :(得分:1)

其他人告诉你如何修复它,让我回答为什么temp改变了..

Node * pop (Node * head) {

您正在将head作为指向Node的指针。

因此当你这样做时

*head = *head->next;

我认为它被解析为

 *head = *(head->next);

然后将下一个对象复制到head的对象中,该对象在temp处是同一个对象。

答案 4 :(得分:0)

void pop(struct node** tol) {
  struct node* t = *tol;
  while (t->link->link != NULL){
    t = t->link;    
  }
  t->link = NULL;
}