//目前它不是一个非常成熟的LINK-Stack,我会稍后更新。
当我遇到这个错误时,我试图释放linklist-style
堆栈中的每个节点:
根据解决方案1,这是一个可编译但不可执行的脚本。当我想为(* S)分配一个地址时,我的问题可能发生了,BUT(* S)被释放了ALREADY?
关于destroy函数,我想释放之前分配给(S)的RAM中的每个节点,使RAM可重用。
那么为什么第一个功能不可用????
PS:我不知道在C中删除变量,删除的意思是删除它的地址。也许通常的变量不能被FREE()释放? PPS:当我使用free()时,我认为它只是释放RAM,但保留变量的名称或标识符可能指向NULL或somwhere,这是危险的,但在Solution1中,似乎我必须这样做。//IDE:Dev C++ 5.11
#include<stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct Stack
{
struct Stack *next;
ElemType data;
} Stack,*LinkStack;
int InitStack(LinkStack *S) {
*S = (LinkStack)malloc(sizeof(struct Stack));
if(!*S) return -1;
(*S)->next=NULL;
(*S)->data =0;
printf("Maybe successfully initialized.\n");
return 0;
}
int Push(LinkStack *S, ElemType e)
{
LinkStack pt = (LinkStack)malloc(sizeof(struct Stack));
LinkStack newpt = (LinkStack)malloc(sizeof(struct Stack));
newpt->data = e;
pt = (*S)->next;
int number = 0;
if (!pt)
{
printf("#a one time \n");
(*S)->next = newpt;
(*S)->data++;
return 1;
}
else
{
while (number < (*S)->data)
{
pt = pt->next;
number++;
}
pt->next = newpt;
newpt->next = NULL;
(*S)->data++;
return 0;
}
}
int StackTraverse(LinkStack S)
{
LinkStack pt = (LinkStack)malloc(sizeof(struct Stack));
pt = (S)->next;
while (pt)
{
printf("%d__", pt->data);
pt = pt->next;
}
return 0;
}
Solution1: //unavailable
void DestroyStack(LinkStack *S)
{
while (*S)
{
LinkList pt = (*S)->next;
free(*S);
(*S) = pt;
}
printf("Node destroyed!\n");
}
int main()
{
LinkStack Sb;
InitStack(&Sb);
ElemType *e = (ElemType *)malloc(sizeof(ElemType));
while (scanf("%d", e))
{
Push(&Sb, *e);
printf("you have entered : %d.\n", *e);
}
free(e);
printf("%d\n", Sb->next->next->data);
StackTraverse(Sb);
DestroyStack(&Sb);
if (!Sb)
{
printf("succeed\n");
}
return 0;
}
所以我提出了另一个函数!使用递归,但是当我向linklist-style
堆栈插入3个节点时,似乎“ LinkStack销毁”被打印6次。当我插入4个节点时,它会打印7次。
solution2: //available ,but not work well
void DestroyStack(LinkStack *S) {
while(*S){
LinkStack pt=(*S);
(*S)=(*S)->next;
printf("#a\n");
DestroyStack(S);
}
printf("LinkStack Destroyed!");
}
感谢您的帮助!
答案 0 :(得分:0)
你的解决方案1是错误的。
void DestroyStack(LinkStack *S){
if(S){
LinkStack pt = S;
S = S->next;
free(pt);
printf("#a\n");
DestroyStack(S);
printf("LinkStack Destroyed!");
}
}
请注意您传递指针*S
,因此请勿混淆->
和解除引用操作符(一元*
)。另请记住free
与malloc
分配的任何内容。
对于解决方案2,正确的代码应如下所示:
void DestroyStack(LinkStack *S){
while(S){
LinkStack pt = S->next;
free(S);
S = pt;
}
printf("Node destroyed!\n");
}
请记住,S->next
相当于(*S).next
,不要混淆它们。也不要混淆指针((*S)=pt
肯定是错误的)。 S
是一个指针,*S
是用户定义的结构。您无法指定结构的指针。
答案 1 :(得分:0)
您的整个代码存在问题,可能是因为您不了解malloc
和free
真正做了什么。
malloc
分配一定大小的块,并为您提供该内存的句柄。该句柄是一个指针。这意味着您只在创建对象时调用malloc
。在您的代码中,您应该调用它的唯一位置是Push
,因为您创建了一个新节点。您不需要为仅遍历堆栈的指针分配内存。特别是这样的事情:
LinkStack pt = malloc(sizeof(struct Stack));
pt = (S)->next;
错误:您通过分配pt
来分配内存并立即丢失其句柄。抛弃malloc
并仅保留第二行。
free
给出之前分配回系统的内存。每个malloc
都需要相应的free
。如果不这样做会被称为内存泄漏。free
后,您可能无法再访问其背后的数据。系统函数free
不会将指针设置为NULL
,因此您必须注意这一点。空堆栈是没有节点的堆栈。因此,分配虚节点是没有意义的。您的堆栈由指向其头节点的指针定义。您可以将此节点初始化为NULL
:
Stack *Sb = NULL;
同样,您可以检查堆栈中是否还有项目:
if (Sb) ...
这更像是一个风格问题:typedef
远离指针性质被认为是不好的做法。您可以typedef
结构,而不是LinkStack
,只需使用Stack *
,这样一眼就能明白您在这里处理指针。
在main
中,您可以执行以下操作:
printf("%d\n", Sb->next->next->data);
这很危险,因为您不知道用户是否输入了至少三个项目。在解除引用之前,您必须检查NULL
的指针。
让我们付诸实践:推动意味着创建一个新节点并将其插入头部,以便新头部是新节点:
typedef int ElemType;
typedef struct Stack Stack;
struct Stack {
Stack *next;
ElemType data;
};
void Push(Stack **S, ElemType e)
{
Stack *newpt= malloc(sizeof(*newpt));
newpt->data = e;
newpt->next = (*S);
*S = newpt;
}
你的代码实现了对堆栈的破坏,但更常见的是,堆栈耗尽了弹出的项目。所以,让我们感到:
ElemType Pop(Stack **S)
{
ElemType res;
Stack *rem = *S;
if (*S == NULL) {
fprintf(stderr, "Stack underflow\n");
exit(1);
}
res = (*S)->data;
*S = (*S)->next;
free(rem);
return res;
}
请注意我们必须保留数据和旧指针的副本,因为free
数据使其无法访问。
现在我们可以重写销毁功能:我们从堆栈中弹出项目,直到用完为止。
void DestroyStack(Stack **S)
{
while (*S) Pop(S);
}
最后,一个没有分配任何内容的遍历函数:
void StackTraverse(const Stack *S)
{
while (S) {
printf("%d ", S->data);
S = S->next;
}
puts("");
}
此功能仅检查堆栈;它没有它,所以它足以通过恒定的头部poiner。最后,主要功能:
int main(){
Stack *Sb = NULL;
ElemType e;
while (scanf("%d", &e) == 1){
Push(&Sb, e);
}
StackTraverse(Sb);
DestroyStack(&Sb);
return 0;
}
元素类型只是int
,因此为它动态分配内存有点过分。使用自动变量更容易。
此程序完成后,将释放所有已分配的块。
答案 2 :(得分:0)
在soluting1中,无论是真还是假,你的代码都会打印“destory”,因此你插入的次数不等于你失去的次数。这是一个逻辑错误,你也需要自由,你几乎完成了它。 我不擅长英语,希望你能理解我
答案 3 :(得分:-1)
你没有在解决方案1中调用free(pt)
,它会进入所有节点的循环,并且不会释放任何内容。
C中的free()
释放了指针指向的内存,指针仍然存在于内存中,因此程序员通常会编写一个包装器函数来释放内存并将指针指向NULL。