一.先说顺序栈
- /**********************************************************
- 顺序栈的各种操作13-5-1.cpp
- 1.初始化栈
- 2.判断栈空
- 3.入栈
- 4.出栈
- 5.取栈顶元素
- 6.主函数测试以上功能
- ***********************************************************/
- #include<stdio.h>
- #include<stdlib.h>
- #define MAX 1000
- typedef struct
- {
- int data[MAX];
- int top;
- }SeStack;
- void InitStack(SeStack *S)
- {
- S->top=-1;
- }
- int EmptyStack(SeStack *S)
- {
- return ((S->top==-1)?1:0);
- }
- int Push(SeStack *S, int x)
- {
- if(S->top==MAX-1)
- {
- printf("栈满!\n");
- return 0;
- }
- S->data[++S->top]=x;
- return 1;
- }
- int Pop(SeStack *S, int *x)
- {
- if(EmptyStack(S))
- {
- printf("栈空!\n");
- return 0;
- }
- *x=S->data[S->top--];
- return 1;
- }
- int GetTop(SeStack *S, int *x)
- {
- if(EmptyStack(S))
- {
- printf("栈空!\n");
- return 0;
- }
- *x=S->data[S->top];
- return 1;
- }
- int main()
- {
- SeStack *S=(SeStack *)malloc(sizeof(SeStack));
- int n, x, fx, j;
- InitStack(S);
- printf("输入入栈元素个数:\n");
- scanf("%d",&n);
- for(int i=1; i<=n; i++)
- {
- Push(S, i);
- }
- GetTop(S, &fx);
- printf("栈顶元素:%d\n", fx);
- printf("栈中元素:\n");
- for(j=S->top; j>-1; j--)
- {
- printf("%3d",S->data[j]);
- }
- for(int i=1; i<=n; i++)
- {
- Pop(S, &x);
- printf("\n出栈元素为:%d\n", x);
- }
- system("pause");
- return 0;
- }
二.再说链栈
- /**********************************************************
- 链栈的各种操作13-5-2.cpp和13-5-3.cpp
- 1.初始化栈
- 2.判断栈空
- 3.入栈
- 4.出栈
- 5.取栈顶元素
- 6.主函数测试以上功能
- ***********************************************************/
- #include<stdio.h>
- #include<stdlib.h>
- typedef struct Lnode
- {
- int data;
- struct Lnode *next;
- }LinkList;
- typedef LinkList LinkStack;
- void InitStack(LinkStack *top)
- {
- /*
- top=(LinkStack *)malloc(sizeof(LinkStack));//(1)
- if(top==NULL)
- {
- printf("分配空间失败!\n");
- return 0;
- }
- */
- //printf("(InitStack)top addr:%x\n", top);
- top->next=NULL;
- //return 1;
- }
- int EmptyStack(LinkStack *top)
- {
- return ((top->next==NULL)?1:0);
- }
- int Push(LinkStack *top, int x)
- {
- LinkStack *s=(LinkStack *)malloc(sizeof(LinkStack));
- if(s==NULL)
- {
- printf("分配空间失败!\n");
- return 0;
- }
- s->data=x;
- s->next=top->next;
- top->next=s;
- //printf("(Push)top addr:%x\n", top);
- return 1;
- }
- int Pop(LinkStack *top, int *x)
- {
- LinkStack *p;
- if(EmptyStack(top))
- {
- printf("栈空!\n");
- return 0;
- }
- *x=top->next->data;
- p=top->next;
- top->next=p->next;
- //printf("(Pop)top addr:%x\n", top);
- free(p);
- return 1;
- }
- int GetTop(LinkStack *top, int *x)
- {
- if(EmptyStack(top))
- {
- printf("栈空!\n");
- return 0;
- }
- *x=top->next->data;
- return 1;
- }
- int main()
- {
- LinkStack *top=(LinkStack *)malloc(sizeof(LinkStack));
- //printf("(main)top addr:%x\n", top);
- LinkStack *p;
- int n, x, fx;
- InitStack(top);
- printf("输入入栈元素个数n:\n");
- scanf("%d", &n);
- for(int i=1; i<=n; i++)
- {
- Push(top, i);
- }
- GetTop(top, &fx);
- printf("栈顶元素:%d\n", fx);
- printf("栈中元素:\n");
- for(p=top->next; p!=NULL; p=p->next)//(2)
- {
- printf("%3d", p->data);
- }
- for(int i=1; i<=n; i++)
- {
- Pop(top, &x);
- printf("\n出栈元素为:%d\n", x);
- }
- system("pause");
- return 0;
- }
- /*************************************************************************************
- 注意:(1)注意这段注释掉的代码,我习惯性的按照链队列里面初始化队列的方式来初始化
- 链栈,结果导致运行(2)处,发生地质访问错误。仔细分析一下:(2)处的p移动到最后一个
- 节点的时候,再往后移动一个就出问题了。按理说最后一个节点的next应该是NULL,看
- InitStack函数,确实应该在一开始就给top->next=NULL,但是我在InitStack函数里面却
- 又申请了一个内存空间,实际上就是给top又赋了一个新的地址,相当于传个参数(指针top)
- 进去又在函数里面改变了它的地址(给to赋了一个新地址),但是根据函数改变参数的机制,
- 只有使用二重指针做参数或者传递引用的时候,才能实际的改变参数。如果仅传一个一维指
- 针,只能改变指针里存的值,不能改变指针本身。这个和p65页面试题很像。可以看验证
- 截图。main中开辟的空间的首地址是x714e38赋给top,IintStack函数中又给top一个新地
- 址x714e80,但是IintStack结束之后,到了Push, Pop函数,地址皆为x714e38,和main
- 中的一样。也就验证了地址在InitStack结束之后根本木有改变。既然这样,在InitStack中给
- top->next赋值为NULL,InitStack结束之后,top还是x714e38,这个top的next根本不知
- 道是什么,所以Push到最后一个的时候,最后一个元素的next就不知道是什么了,因为是由
- top->next觉定的,所以也就发生了内存错误。所以再说一点就是建立栈操作时候,想在main函数中给top赋个NULL,然后在Init中开辟空间的,是不行了,要么在主函数中开辟空间给指针赋值,然后到init中直接传过去,注意,通过传参,在别的函数体力就改变不了指针值了。如果习惯在主函数中不管,赋值的活交给Init函数的话,就是用二重指针方式了。
- ***************************************************************************************/
先看验证注释(1)的运行结果截图
如果按照之前说的,将Init函数改成传二重指针的方式,在main里面仅仅给top=NULL,z Init里面再给top换个值,也就是开辟一段内存。这样就可以了,后面的(2)就可以正常运行了。
具体改动:
1.InitStack中
- int InitStack(LinkStack **top)
- {
- *top=(LinkStack *)malloc(sizeof(LinkStack));//(1)
- if(*top==NULL)
- {
- printf("分配空间失败!\n");
- return 0;
- }
- printf("(InitStack)top addr:%x\n", *top);
- (*top)->next=NULL;
- return 1;
- }
2.main中
- int main()
- {
- //LinkStack *top=(LinkStack *)malloc(sizeof(LinkStack));
- LinkStack *top=NULL;
- …
- InitStack(&top);
- …
- }//去掉上面的,不用给top赋实际地址了,在调用InitStack(&top)的
- //时候传递top的地址过去就行了,改到InitStack里面来改变top的值。
看一下运行结果截图:
最后看正常情况下程序的运行结果的图