我已经尝试了一段时间让我的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);
答案 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
,最新编辑中的*l
。 stack
中main
变量的值未更改,现在无效 - 不再分配该地址的内存。因此,下次您致电push
时,会看到*l
不是NULL
,并尝试遍历(不存在的)列表。
此时行为未定义;字面上任何都可能发生。在第一个push
之后的系统中,stack
的值为0x501010
。我做了一个pop
free
的记忆,但没有改变stack
的值。在下一个push
,*l
不是NULL
,因此我将(*l)->next
设置为malloc
返回的任何内容,在我的情况下是{{1}再次。因此0x501010
为*l
,0x501010
为(*l)->next
。如果我尝试推送另一个项目,我会陷入无限循环(0x501010
== p
)。
要解决此问题,您需要在p->next
之后将列表指针设置为NULL
:
free