顺序栈和链栈,代码实现一些基本操作
栈是一种受限的线性表,其特点是栈中元素先进后出(或者说后进先出,Last In First Out,LIFO),栈只允许在一端进行插入或者删除操作。
本人使用Visual Stdio 2019作为编译器
以下代码为利用线性结构(逻辑结构)实现的栈(物理结构)
#define _CRT_SECURE_NO_WARNINGS //解决VS2019的scanf编译报错问题 #include<stdio.h> #include<stdlib.h> #include<string.h> //多行文字注释,用"——"表示接续上一行 //今天看见一个笑话 //——我最讨厌的4件事情 // 1.写注释,2.写文档,3.别人不写注释,4.别人不写文档 //用静态数组实现栈 #define MaxSize 10 typedef int ElemType; typedef struct { ElemType data[MaxSize]; //定义静态数组 ElemType top; //定义栈顶指针,这个指针只是一个名字,不是我们说的定义上的指针,这个指针相当于标记 //栈中元素压(压栈)到哪里了 }SqStack; //初始化栈空间 void InitStack(SqStack& S) { S.top = -1; //将栈顶指针设置为-1,即表示栈空 } //判空操作 bool EmptyStack(SqStack S) { if (S.top == -1) //栈顶指针为1,即表示栈空 return false; else return true; } //判断栈满————下面这个函数(FillStack(S))是有问题的,它只能判断栈慢,没法判断栈不满 //——因为当栈不满,且不为空时,没法返回false,也没法返回true;但是这个 //——程序在VS2019里貌似是默认返回的true bool FillStack(SqStack S) { if (S.top == -1) return false; else if (S.top == MaxSize - 1) return true; } //判断栈满——改进的代码 bool FillStack_modify(SqStack S) { if (S.top == MaxSize - 1)//如果栈顶指针+1=MaxSize,则表示栈满,因为栈顶指针,其实表示的是数组下标 return true; else return false; } //压栈 bool Push(SqStack& S, ElemType x) { if (S.top == MaxSize - 1) return false; S.top++; //先把栈顶指针上移一位 S.data[S.top] = x; //再将元素填入栈顶指针指向的地方 //S.data[++S.top] = x; return true; } //弹栈,返回弹出元素 bool Pop(SqStack& S, ElemType& x) { if (S.top == -1) return false; x = S.data[S.top--]; //先读出栈顶指针此时指向的元素,再将栈顶指针减一 return true; } //读栈顶 bool GetTop(SqStack& S, ElemType& x) { if (S.top == -1) return false; x = S.data[S.top]; return true; } //遍历栈中元素(自顶向下) void Print_SqStack(SqStack S) { while (S.top != -1) //当S.top==-1时表示读取结束 { printf("%3d", S.data[S.top--]);//从栈顶至栈底读取打印栈中元素 } printf("\n"); } //主函数 int main() { SqStack S; //新定义一个栈空间 ElemType x; //定义一个x,用于后续接受被删除的元素,以及栈顶元素 bool ret; InitStack(S); //初始化栈空间 EmptyStack(S); //判空操作 Push(S, 1); //向栈中压入10个元素 Push(S, 2); Push(S, 3); Push(S, 4); Push(S, 5); Push(S, 6); Push(S, 7); Push(S, 8); Push(S, 9); Push(S, 10); Print_SqStack(S);//打印压栈后的栈 ret = FillStack(S);//判断栈满与否 if (ret) printf("栈满\n"); else printf("栈未满\n"); ret = Pop(S, x);//弹出栈顶元素,用x接收弹出的元素 if (ret) printf("弹出栈顶的元素是%d\n", x); else printf("弹出失败\n"); ret = GetTop(S, x);//读栈顶,用x接收读取的栈顶元素 if (ret) printf("栈顶元素为%d\n", x); else printf("读栈顶失败\n"); bool rettt; rettt = FillStack_modify(S);//再次判断栈满与否 if (rettt) printf("栈满\n"); else printf("栈未满\n"); Print_SqStack(S); return 0; }
以下为链式结构实现的栈的一些操作(只写了一些,没写全)
#define _CRT_SECURE_NO_WARNINGS //解决VS2019的scanf编译报错问题 #include<stdio.h> #include<stdlib.h> #include<string.h> //多行文字注释,用"——"表示接续上一行 //定义链栈结点 //链栈链栈,虽然是链式存储实现,但它仍是一个栈,栈底的下一个元素还是应该设为-1, //——我一开始琢磨着把栈底元素的next指针设为NULL,但是我目前做不出来。 typedef int ElemType; typedef struct LinkNode { ElemType data; struct LinkNode* next;//有没有双向链栈呢? }LinkNode,*LinkStack; //初始化链栈,不带头结点 LinkStack Init_LinkStck(LinkStack& L) { L = (LinkStack)malloc(sizeof(LinkNode));//为链栈定义第一个结点(LinkStck体现这是一个链栈) L->data= -1; return L; } //将元素压入链栈 LinkStack Push(LinkStack& L, ElemType e) { LinkNode* p_first = L; LinkNode*s;//用于存放要压入的元素 LinkNode* p_tail; if (L->data == -1) { //s = (LinkNode*)sizeof(LinkNode);//这段程序一开始搞错了,老是提醒我s是0x8,我没有搞懂咋回事 //——通过调试发现这里少了一个malloc函数 s = (LinkNode*)malloc(sizeof(LinkNode)); s->data = e; s->next = p_first; p_first = s; } else { s = (LinkNode*)malloc(sizeof(LinkNode)); s->data = e; s->next = p_first; p_first = s; } L = p_first; return L; //相当于头插法压入元素 } //遍历链栈中的元素 void Print_LinkStack(LinkStack L) { LinkNode* j = Init_LinkStck(j); j = L; while (j->data != -1) { printf("%3d", j->data); j = j->next; } printf("\n"); } //主函数 int main() { LinkStack L; L=Init_LinkStck(L); Push(L, 1); Push(L, 2); Push(L, 3); Push(L, 4); Push(L, 5); Print_LinkStack(L); }