C中的堆栈Pop()函数

时间:2016-06-22 18:22:08

标签: c pointers stack

我已经尝试了一段时间让我的pop()函数正常工作但是一些奇怪的原因它所做的一切都是......没有。 这是我的Stack声明& function.L.E。我还添加了推送功能。

typedef struct node
{
    int v;
    struct node* next;
}Node;

void push(Node **l,int val)
{
    Node *p = (Node *)calloc(1,sizeof(Node));
    p->v = val;
    Node *aux=*l;
    if(aux == NULL)
    {
        *l = p;
        return;
    }
    while(aux->next != NULL)
        aux = aux->next;
    aux->next = p;
}

void pop(Node **l)
{
  if(*l != NULL)
  {
    Node *aux,*prev;
    prev = *l;
    aux = prev->next;
    if(aux == NULL)
      free(prev);
    else
    {
      while(aux->next != NULL)
      {
         prev = aux;
         aux = aux->next;
      }
      prev->next = NULL;
      free(aux);
    }
  }
}

我用

来称呼它
Node *stack = NULL;
pop(&stack);

1 个答案:

答案 0 :(得分:1)

将有助于了解如何将项目推送到堆栈中。如果您首先在没有pop的情况下真正打电话给push,那么它不会假设做任何事情,是吗?

这一点让我感到紧张:

Node *aux,*prev;
prev = *stack;
aux = prev->next;
if(aux == NULL)
{
    free(prev);
    return;
}

您将prev设置为*stack,如果prev后面没有任何内容,则将其释放。请注意,自prev == *stack起,您还释放了*stack,因此指针现在无效。如果您尝试在调用者中访问该指针,则会调用未定义的行为。

看起来你正在使你的列表尾部成为堆栈顶部;我现在要告诉你,如果你把列表 head 放在堆栈的顶部,你就会让生活变得更简单,这样你就可以推动pops看起来如下:

bool push( Node **l, int val )
{
  Node *p = calloc( 1, sizeof *p );
  if ( p )
  {
    p->v = val;
    p->next = *l;   // set p to point to the current head of the list
    *l = p;         // make p the new head of the list
  }
  return p != NULL;  // will return false if the calloc (and by extenion,
}                    // the push operation) fails.  

bool pop( Node **l, int *v )
{
  Node *p = *l;      // p points to head of list
  if ( !p )
    return false;

  *v = p->val;     // get value in current node
  *l = p->next;    // make the next element the new list head
  p->next = NULL;  // sever the old list head
  free( p );       // and deallocate it

  return true;
}

没有列表遍历,无需跟踪当前节点和先前节点。你关心的只是头节点。声明p->next = NULL;并非严格必要,因为我们之后会立即释放p。我喜欢它,因为它很明显我们从列表中删除了 {/ em> p,但是如果你不想节省周期,你可以省略它。

修改

我对这段代码感到紧张是对的。

所以这里基本上发生了什么 - 当你在堆栈中只有一个项目时,你释放了列表的头部,但是你没有更新它的值列表指针(原始代码中的*stack,最新编辑中的*lstackmain变量的值未更改,现在无效 - 不再分配该地址的内存。因此,下次您致电push时,会看到*l不是NULL,并尝试遍历(不存在的)列表。

此时行为未定义;字面上任何都可能发生。在第一个push之后的系统中,stack的值为0x501010。我做了一个pop free的记忆,但没有改变stack的值。在下一个push*l不是NULL,因此我将(*l)->next设置为malloc返回的任何内容,在我的情况下是{{1}再次。因此0x501010*l0x501010(*l)->next。如果我尝试推送另一个项目,我会陷入无限循环(0x501010 == p)。

要解决此问题,您需要在p->next之后将列表指针设置为NULL

free