您现在的位置是:首页 >技术交流 >顺序栈的入栈与出栈-----(c语言)网站首页技术交流
顺序栈的入栈与出栈-----(c语言)
栈:是限定仅在表尾进行插入和删除操作的线性表(顺序结构)
栈顶:允许插入跟删除的一端
栈底:固定的一端,不允许在栈底进行插入跟删除
入栈:栈的插入操作
出栈:栈的删除操作
目录
定义栈
#include<stdio.h>
#include<malloc.h>
#define ok 1
#define error 0
#define sizemax 10
typedef int ElemType;
typedef struct {
ElemType *base;//栈底
ElemType *top;//栈顶
int sizestack;//分配栈的值
}Sqstack;//定义栈
此处定义栈的最大值为10,当然如果需要后续分配更大的内存空间,可以使用realloc函数增加新的空间(作者还没学会使用)。
创建空栈
int initstack(Sqstack* s) {
s->base = (ElemType*)malloc(sizeof(ElemType) * SIZEMAX);//给base分配内存空间,返回base的首地址
if (!s->base) {
return error;
}
s->top = s->base;//出发点为base的首地址,栈顶从底地址开始
s->sizestack = SIZEMAX;//最大空间
return ok;
}//创建空栈
创建空栈,就需要给栈底分配一块内存空间,将栈底的首地址返回,就可以通过栈底首地址对栈进行修改。所以将栈底的首地址赋值给栈底(s->top),就可以对栈底进行修改了。
图解:
值得注意的是,栈底的首地址不一定是从0开始的,而是这里为了方便图片的展示而写成0。由于用了malloc函数,编译器给s->base的地址是随机分配的,如果需要查看真正的地址,可以调试监控窗口查看。
入栈
int push(Sqstack* s, ElemType e) {
if (s->top - s->base == SIZEMAX ) {
printf("栈满,无法入栈
");
return error;
}
*(s->top) = e;//(由于s是指针,想要将里面的值赋值,需要带上*号)
s->top++;
return ok;
}//入栈
入栈前首先要判断栈是否满了,这里可以用s->top-s->base的值判断是否满了(地址的分配原理),将输入的值赋值给栈顶,用指针对地址里面的值修改,必须要用上星号(指针的原理)。那么问题就来了,是先插入在进行栈顶指针的自增呢,还是先栈顶指针自增在插入呢?动动小脑袋瓜来思考一下,在定义栈的时候,博主将栈底的地址赋值给栈顶指针,入栈时,将e的值赋值给此处栈顶指针,如果先进行指针自增,那么执行到插入时,他后面的那一个空栈就会跳过了,此时插入的空间是自增后的那个空间,造成空间浪费,不理解的同学可以上机实践,看看调换这个语句的顺序会发生什么。
正确的做法是先插入,栈顶指针在自增。
出栈
int pop(Sqstack* s, ElemType *e) {
if (s->top == s->base) {
return error;
}
s->top--;//先--是因为输入的最后一个值是非整形的,需要忽略非整形的字符
*e = *(s->top);
return ok;
}//出栈
出栈前要判断栈是否为空,判断条件是s->top=s->base 在动动小脑瓜思考,这里为什么又要先栈顶指针自减在赋值给*e,这就涉及到另一个模块的代码了
int creatstack(Sqstack* s) {
int e;
if (initstack(s)) {
printf("栈创建成功!
");
}
else {
printf("栈创建失败
");
return error;
}
printf("请输入数据
");
while (scanf("%d", &e))
push(s, e);
return ok;
}//创建并输入
在这个函数中,我们调用创建栈的函数,创建成功后进行入栈操作
while (scanf("%d", &e))
push(s, e);
我们使用scanf输入要入栈的值,由于我们定义的是整形,输入的也是整形,这里介绍一下scanf的返回值,是成功读入参数的个数,我们都知道,判定条件,0为假,非0为真。当输入多组整数时,按下回车后,这些整数会进入缓冲区中,然后scanf函数会一个个读取缓冲区中的数据,当读取到一个整数时返回值是1,当读到非整数的值时,返回值是0,因此在while中,想要让这个输入循环停止,就要输入一个非整数的值,比如字母a,但是在入栈的时候,输入非整数的值仍然会保持在栈中,因此在出栈中,要错开这个值,所以在出栈函数中,首先要栈顶指针先自减,在将栈存储的值赋值给指针*e。
如果先赋值在自减出栈时就会造成如下错误:
输出了非整数的值,并且还造成了栈里面的内容丢失
正确操作是先自减在赋值:
图解:
源代码
#include<stdio.h>
#include<malloc.h>
#define ok 1
#define error 0
#define SIZEMAX 10
typedef int ElemType;
typedef struct {
ElemType *base;//栈底
ElemType *top;//栈顶
int sizestack;//分配栈的值
}Sqstack;//定义栈
int initstack(Sqstack* s) {
s->base = (ElemType*)malloc(sizeof(ElemType) * SIZEMAX);//给base分配内存空间,返回base的首地址
if (!s->base) {
return error;
}
s->top = s->base;//出发点为base的首地址,栈顶从底地址开始
s->sizestack = SIZEMAX;//最大空间
return ok;
}//创建空栈
int push(Sqstack* s, ElemType e) {
if (s->top - s->base == SIZEMAX ) {
printf("栈满,无法入栈
");
return error;
}
*(s->top) = e;//(由于s是指针,想要将里面的值赋值,需要带上*号)
s->top++;
return ok;
}//入栈
int pop(Sqstack* s, ElemType *e) {
if (s->top == s->base) {
return error;
}
s->top--;//先--是因为输入的最后一个值是非整形的,需要忽略非整形的字符
*e = *(s->top);
return ok;
}//出栈
int creatstack(Sqstack* s) {
int e;
if (initstack(s)) {
printf("栈创建成功!
");
}
else {
printf("栈创建失败
");
return error;
}
printf("请输入数据
");
while (scanf("%d", &e))
push(s, e);
return ok;
}//创建并输入
int printstack(Sqstack* s) {
ElemType e;
while (pop(s, &e))
printf("%3d", e);
return ok;
}//出栈并且输出
int main() {
Sqstack s;
printf("创建并输出
");
creatstack(&s);
printf("出栈并且输出
");
printstack(&s);
return 0;
}