栈是一个线性表,栈元素具有线性关系,即前驱后继关系,但是是一种特殊的线性表,在线性表的表尾进行插入和删除操作,表尾是指栈顶,表头是指栈底。
先进后出的规则

始终只进行栈顶操作,想访问栈底数据,就需要将上面数据一个一个出栈

栈的顺序存储结构简称顺序栈,它是运算受限制的顺序表。顺序栈的存储结构是:利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针 top (只是栈顶元素在顺序表的位置)
- #ifndef SEQSTACK_H
- #define SEQSTACK_H
-
- #define _CRT_SECURE_NO_WARNINGS 1
- #include
- #include
- #include
-
- // 数组模拟栈的顺序存储
- #define MAX_SIZE 1024
- #define SEQSTACK_TURE 1
- #define SEQSTACK_FALSE 0
-
- typedef struct SEQSTACK {
- void* data[MAX_SIZE];
- int size;
- }SeqStack;
-
- // 初始化栈
- SeqStack* Init_Stack();
-
- // 入栈
- void Push_Stack(SeqStack* stack, void* data);
-
- // 返回栈顶元素
- void* Top_Stack(SeqStack* stack);
-
- // 出栈
- void Pop_Stack(SeqStack* stack);
-
- // 判断是否为空
- int IsEmpty_Stack(SeqStack* stack);
-
- // 返回栈中元素个数
- int Size_Stack(SeqStack* stack);
-
- // 清空栈
- void Clear_Stack(SeqStack* stack);
-
- // 销毁
- void FreeSpace_Stack(SeqStack* stack);
-
- #endif
- #include"SeqStack.h"
-
- // 初始化栈
- SeqStack* Init_Stack(){
- //(SeqStack*)Stack = (SeqStack*)malloc(sizeof(SeqStack));
- SeqStack* stack = (SeqStack*)malloc(sizeof(SeqStack));
- for (int i = 0; i < MAX_SIZE; i++) {
- stack->data[i] = NULL;
- }
- stack->size = 0;
- return stack;
- }
-
- // 入栈
- void Push_Stack(SeqStack* stack, void* data){
- if (stack->size == MAX_SIZE) return;
- if (stack == NULL) return;
- if (data == NULL) return;
-
- stack->data[stack->size] = data;
- stack->size++;
- }
-
- // 返回栈顶元素
- void* Top_Stack(SeqStack* stack){
- if (stack == NULL) return NULL;
- if (stack->size == 0) return NULL;
-
- return stack->data[stack->size - 1];
- }
-
- // 出栈
- void Pop_Stack(SeqStack* stack){
- if (stack == NULL) return;
- if (stack->size == 0) return;
-
- stack->data[stack->size - 1] = NULL;
- stack->size--;
- }
-
- // 判断是否为空
- int IsEmpty_Stack(SeqStack* stack){
- if (stack->data == NULL) return -1;
- if (stack->size == 0) return SEQSTACK_TURE;
- return SEQSTACK_FALSE;
- }
-
- // 返回栈中元素个数
- int Size_Stack(SeqStack* stack){
- if (stack == NULL) return 0;
- return stack->size;
- }
-
- // 清空栈
- void Clear_Stack(SeqStack* stack){
- if (stack == NULL) return;
- for (int i = 0; i < stack->size; i++) {
- stack->data[i] = NULL;
- }
- stack->size = 0;
- }
-
- // 销毁
- void FreeSpace_Stack(SeqStack* stack){
- if (stack == NULL) return;
- free(stack);
- }
- #include"SeqStack.h"
-
- typedef struct PERSON {
- char name[64];
- int age;
- }Person;
-
- void test() {
- SeqStack* stack = Init_Stack();
-
- Person p1, p2, p3, p4, p5;
- strcpy(p1.name, "张三");
- strcpy(p2.name, "李四");
- strcpy(p3.name, "王五");
- strcpy(p4.name, "李华");
- strcpy(p5.name, "赵六");
- p1.age = 10;
- p2.age = 20;
- p3.age = 30;
- p4.age = 40;
- p5.age = 50;
-
- // 判断栈是否为空
- if (IsEmpty_Stack(stack)) printf("栈为空\n");
- else printf("栈非空\n");
-
- // 入栈
- Push_Stack(stack, (void*)&p1);
- Push_Stack(stack, (void*)&p2);
- Push_Stack(stack, (void*)&p3);
- Push_Stack(stack, (void*)&p4);
- Push_Stack(stack, (void*)&p5);
-
- // 判断栈是否为空
- if (IsEmpty_Stack(stack)) printf("栈为空\n");
- else printf("栈非空\n");
-
- while (Size_Stack(stack)) {
- // 访问栈顶元素
- Person* person = (Person*)Top_Stack(stack);
- printf("name: %s age: %d\n", person->name, person->age);
- Pop_Stack(stack);
- }
-
- FreeSpace_Stack(stack);
- }
-
- int main() {
- test();
- return 0;
- }
运行结果:

- #ifndef LINKSTACK_H
- #define LINKSTACK_H
-
- #define _CRT_SECURE_NO_WARNINGS 1
-
- #include
- #include
- #include
-
- // 结点
- typedef struct STACKNODE {
- struct STACKNODE* next;
- }StackNode;
-
- // 链式 栈
- typedef struct LINKSTACK {
- StackNode head;
- int size;
- }LinkStack;
-
- // 初始化
- LinkStack* Init_Stack();
-
- // 入栈
- void Push_Stack(LinkStack* stack, StackNode* data);
-
- // 出栈
- void Pop_Stack(LinkStack* stack);
-
- // 返回栈顶
- StackNode* Top_Stack(LinkStack* stack);
-
- // 返回栈中元素个数
- int Size_Stack(LinkStack* stack);
-
- // 清空栈
- void Clear_Stack(LinkStack* stack);
-
- // 释放栈
- void Free_Stack(LinkStack* stack);
-
- #endif // !LINKSTACK_H
- #include "LinkStack.h"
-
- // 初始化
- LinkStack* Init_Stack() {
- LinkStack* stack = (LinkStack*)malloc(sizeof(LinkStack));
- stack->head.next = NULL;
- stack->size = 0;
- return stack;
- }
-
- // 入栈
- void Push_Stack(LinkStack* stack, StackNode* data) {
- if (stack == NULL) return;
- if (data == NULL) return;
-
- data->next = stack->head.next;
- stack->head.next = data;
- stack->size++;
- }
-
- // 出栈
- void Pop_Stack(LinkStack* stack) {
- if (stack == NULL) return;
- if (stack->size == 0) return;
-
- // 第一个有效结点
- StackNode* pNext = stack->head.next;
- stack->head.next = pNext->next;
-
- stack->size--;
- }
-
- // 返回栈顶
- StackNode* Top_Stack(LinkStack* stack) {
- if (stack == NULL) return NULL;
- if (stack->size == 0) return NULL;
-
- return stack->head.next;
- }
-
- // 返回栈元素个数
- int Size_Stack(LinkStack* stack) {
- if (stack == NULL) return 0;
- return stack->size;
- }
-
- // 清空栈
- void Clear_Stack(LinkStack* stack) {
- if (stack == NULL) return;
-
- stack->head.next = NULL;
- stack->size = 0;
- }
-
- // 释放栈
- void Free_Stack(LinkStack* stack) {
- if (stack == NULL) return;
-
- free(stack);
- }
- #include "LinkStack.h"
-
- typedef struct PERSON {
- StackNode node;
- char name[64];
- int age;
- }Person;
-
- void test() {
- // 创建栈
- LinkStack* stack = Init_Stack();
-
- // 创建数据
- Person p1, p2, p3, p4, p5;
- strcpy(p1.name, "aaa");
- strcpy(p2.name, "bbb");
- strcpy(p3.name, "ccc");
- strcpy(p4.name, "ddd");
- strcpy(p5.name, "eee");
- p1.age = 10;
- p2.age = 20;
- p3.age = 30;
- p4.age = 40;
- p5.age = 50;
-
- // 入栈
- Push_Stack(stack, (StackNode*)&p1);
- Push_Stack(stack, (StackNode*)&p2);
- Push_Stack(stack, (StackNode*)&p3);
- Push_Stack(stack, (StackNode*)&p4);
- Push_Stack(stack, (StackNode*)&p5);
-
- // 返回栈中元素个数
- printf("栈中元素个数: %d\n", Size_Stack(stack));
-
- // 出栈
- while (Size_Stack(stack) > 0) {
- Person* p = (Person*)Top_Stack(stack); // 返回栈顶
- printf("name: %s age: %d\n", p->name, p->age);
- Pop_Stack(stack); // 弹出栈顶
- }
- Free_Stack(stack);
- }
-
- int main() {
- test();
- return 0;
- }
运行结果:

匹配左右括号,找到字符串中不匹配的位置

- #ifndef LINKSTACK_H
- #define LINKSTACK_H
-
- #include
- #include
- #include
-
- // 结点
- typedef struct STACKNODE {
- struct STACKNODE* next;
- }StackNode;
-
- // 链式栈
- typedef struct LINKSTACK {
- StackNode head;
- int size;
- }LinkStack;
-
- // 初始化栈
- LinkStack* Init_Stack();
-
- // 入栈
- void Push_Stack(LinkStack* stack, StackNode* data);
-
- // 出栈
- void Pop_Stack(LinkStack* stack);
-
- // 获取栈顶
- StackNode* Top_Stack(LinkStack* stack);
-
- // 返回栈元素个数
- int Size_Stack(LinkStack* stack);
-
- // 清空栈
- void Clear_Stack(LinkStack* stack);
-
- // 释放栈
- void Free_Stack(LinkStack* stack);
-
- #endif // !LINKSTACK_H
- #include "LinkStack.h"
-
- // 初始化栈
- LinkStack* Init_Stack() {
- LinkStack* stack = (LinkStack*)malloc(sizeof(LinkStack));
- stack->head.next = NULL;
- stack->size = 0;
- return stack;
- }
-
- // 入栈
- void Push_Stack(LinkStack* stack, StackNode* data) {
- if (stack == NULL) return;
- if (data == NULL) return;
-
- data->next = stack->head.next;
- stack->head.next = data;
- stack->size++;
- }
-
- // 出栈
- void Pop_Stack(LinkStack* stack) {
- if (stack == NULL) return;
- if (stack->size == 0) return;
-
- // 记录第一个有效的结点
- StackNode* pNext = stack->head.next;
- stack->head.next = pNext;
- stack->size--;
- }
-
- // 获取栈顶
- StackNode* Top_Stack(LinkStack* stack) {
- if (stack == NULL) return NULL;
-
- return stack->head.next;
- }
-
- // 返回栈元素个数
- int Size_Stack(LinkStack* stack) {
- if (stack == NULL) return 0;
- return stack->size;
- }
-
- // 清空栈
- void Clear_Stack(LinkStack* stack) {
- if (stack == NULL) return;
- stack->size = 0;
- }
-
- // 释放栈
- void Free_Stack(LinkStack* stack) {
- if (stack == NULL) return;
- free(stack);
- }
- #include "LinkStack.h"
-
- typedef struct MyChar {
- StackNode node;
- char* str;
- int index;
- }MyChar;
-
- int IsLeft(char c) {
- return c == '(';
- }
-
- int IsRight(char c) {
- return c == ')';
- }
-
- void ShowError(char* str, int pos) {
- printf("%s\n", str);
- for (int i = 0; i < pos; i++) {
- printf(" ");
- }
- printf("A\n");
- }
-
- void test() {
- char* str = "((1+2)+)()(())";
- char* p = str;
-
- int index = 0;
- // 创建栈
- LinkStack* stack = Init_Stack();
- while (*p != '\0') {
- // 左括号 ( 进栈
- if (IsLeft(*p)) {
- // 创建字符数据
- MyChar* mychar = (MyChar*)malloc(sizeof(MyChar));
- mychar->str = p;
- mychar->index = index;
- Push_Stack(stack, (StackNode*)mychar);
- free(mychar);
- }
- // 右括号 ) 出栈
- if (IsRight(*p)) {
- // 栈内要有括号
- if (Size_Stack(stack) > 0) {
- Pop_Stack(stack); // 弹出栈顶元素
- }
- else {
- printf("右括号没有匹配的左括号\n");
- ShowError(str, index);
- break;
- }
- }
- p++;
- index++;
- }
- if (Size_Stack(stack) > 0) {
- MyChar* mychar = (MyChar*)Top_Stack(stack);
- printf("左括号没有匹配的右括号\n");
- ShowError(str, (mychar->index) - Size_Stack(stack) + 1);
- Pop_Stack(stack);
- free(mychar);
- }
- else {
- printf("括号匹配成功\n");
- }
- Free_Stack(stack);
- }
-
- int main() {
- test();
- return 0;
- }
运行结果:

后缀表达式与中缀表达式
- 将运算符放在数字后面叫后缀表达式 ---> 符合及计算机运算
- 平时所写的数学表达式叫中缀表达式 ---> 符合直观思维逻辑
实例(中缀表达式 转化为 后缀表达式)
- 1 + 2 ---> 1 2 +
- 1 + 2 * 3 ---> 1 2 3 * +
中缀表达式算法
遍历中缀表达式中所有的数字和符号
- 对于数字:直接输出
- 对于符号:
- 左括号:直接进栈
- 运算符号:与栈顶符号进行优先级比较
- 该符号优先级高:该运算符入栈(默认栈底为左括号,左括号优先级最低)
- 该符号优先级不高:将栈顶符号弹出并输出(直到满足条件1),之后该符号进栈
- 对于右括号:将栈顶符号弹出并输出,直到匹配左括号
遍历结束:将栈中的所有符号弹出并输出
- #include "LinkStack.h"
-
- typedef struct Mychar {
- StackNode node;
- char* str;
- }MyChar;
-
- // 创建 MyChar
- MyChar* CreateMyChar(char* p) {
- MyChar* mychar = (MyChar*)malloc(sizeof(MyChar));
- if (mychar != NULL) {
- mychar->str = p;
- return mychar;
- }
- else return NULL;
- }
-
- // 数字
- int Is_Number(char c) {
- return (c >= '0' && c <= '9');
- }
-
- // 数字操作
- void Number_Operate(char* p) {
- printf("%c", *p);
- }
-
- // 左括号
- int Is_Left(char c) {
- return (c == '(');
- }
-
- // 左括号操作
- void Left_Operate(LinkStack* stack, char* p) {
- // 进栈
- Push_Stack(stack, (StackNode*)CreateMyChar(p));
- }
-
- // 右括号
- int Is_Right(char c) {
- return (c == ')');
- }
-
- // 右括号操作
- void Right_Operate(LinkStack* stack) {
- // 先判断栈中有没有元素
- while (Size_Stack(stack) > 0) {
- MyChar* mychar = (MyChar*)Top_Stack(stack);
- // 匹配到左括号
- if (Is_Left(*(mychar->str))) {
- // 左括号出栈
- Pop_Stack(stack);
- // 结束
- break;
- }
- // 输出
- printf("%c", *(mychar->str));
- // 弹出
- Pop_Stack(stack);
- }
- }
-
-
- // 运算符
- int Is_Opertaor(char c) {
- return (c == '+' || c == '-' ||
- c == '*' || c == '/');
- }
-
- // 返回运算符优先级
- int GetPriority(char c) {
-
- if (c == '*' || c == '/') {
- return 2;
- }
- if (c == '+' || c == '-') {
- return 1;
- }
- return 0;
- }
-
- // 运算符操作
- void Operator_Operate(LinkStack* stack, char* p) {
- // 取出栈顶符号
- MyChar* mychar = (MyChar*)Top_Stack(stack);
- // 栈顶没有符号,该符号入栈
- if (mychar == NULL) {
- Push_Stack(stack, (StackNode*)CreateMyChar(p));
- return;
- }
-
- // 栈顶优先级低于当前符号优先级,该符号入栈
- if (GetPriority(*(mychar->str)) < GetPriority(*p)) {
- Push_Stack(stack, (StackNode*)CreateMyChar(p));
- return;
- }
-
- // 栈顶优先级不低于当前符号优先级
- else {
- while (Size_Stack(stack) > 0) {
-
- MyChar* mychar2 = (MyChar*)Top_Stack(stack);
-
- // 直到栈顶符号优先级低于该符号,该符号入栈
- if (GetPriority(*(mychar2->str)) < GetPriority(*p)) {
- Push_Stack(stack, (StackNode*)CreateMyChar(p));
- break;
- }
- printf("%c", *(mychar2->str));
- Pop_Stack(stack);
- }
- }
- }
-
- // 弹出剩余的符号
- void Left_Over_Stack(LinkStack* stack) {
- while (Size_Stack(stack) > 0) {
- MyChar* mychar = (MyChar*)Top_Stack(stack);
- printf("%c", *(mychar->str));
- Pop_Stack(stack);
- }
- }
-
- void test() {
- char* str = "3+(2-1)*5/6";
- char* p = str;
-
- LinkStack* stack = Init_Stack();
-
- while (*p != '\0') {
-
- // 数字(输出)
- if (Is_Number(*p)) {
- Number_Operate(p);
- }
-
- // 左括号(入栈)
- if (Is_Left(*p)) {
- Left_Operate(stack, p);
- }
-
- // 右括号(出栈直到左括号)
- if (Is_Right(*p)) {
- Right_Operate(stack);
- }
-
- // 运算符(与栈顶比较)
- if (Is_Opertaor(*p)) {
- Operator_Operate(stack, p);
- }
-
- p++; // 字符指针移动
- }
-
- // 循环结束直接弹出所有符号
- while (Size_Stack(stack) > 0) {
- MyChar* mychar = (MyChar*)Top_Stack(stack);
- printf("%c", *(mychar->str));
- Pop_Stack(stack);
- }
- // 释放栈
- FreeStack(stack);
- }
-
- int main() {
- test();
- return 0;
- }
运行结果:

后缀转中缀
遍历后缀表达式中的数字和符号
- 对于数字:进栈
- 对于符号:
- 从栈中弹出右操作数
- 从栈中弹出左操作数
- 根据符号进行运算
- 将运算结果压入栈中
结束遍历:栈中的唯一数字为计算结果
图方便直接C++的 stack 和 list
- #include
- #include
- #include
- #include
-
- using namespace std;
-
- int isNumber(char c) {
- return (c >= '0' && c <= '9');
- }
-
- int isOperate(char c) {
- return (c == '+' || c == '-' || c == '*' || c == '/');
- }
-
- int priorityOperate(char c) {
- if (c == '*' || c == '/') return 2;
- if (c == '+' || c == '-') return 1;
- return 0;
- }
-
- int isLeft(char c) {
- return (c == '(');
- }
-
- int isRight(char c) {
- return (c == ')');
- }
-
- void printList(const list<char>& clist) {
- for (list<char>::const_iterator it = clist.begin(); it != clist.end(); it++) {
- cout << *it;
- }
- cout << endl;
- }
-
- int main() {
- char str[] = "3+(2-1)*5/6";
- char* p = str;
-
- list<char>cList;
- stack<char>cStack;
-
- while (*p != '\0') {
- // 数字
- if (isNumber(*p)) {
- cList.push_back(*p);
- }
- // 操作符
- if (isOperate(*p)) {
- if (cStack.size() == 0) {
- cStack.push(*p);
- }
- else {
- if (priorityOperate(*p) > priorityOperate(cStack.top())) {
- cStack.push(*p);
- }
- else {
- while (cStack.size() > 0) {
- if (priorityOperate(*p) > priorityOperate(cStack.top())) {
- cStack.push(*p);
- break;
- }
- cList.push_back(cStack.top());
- cStack.pop();
- }
- }
- }
- }
- // 左括号
- if (isLeft(*p)) {
- cStack.push(*p);
- }
- // 右括号
- if (isRight(*p)) {
- // 出栈直到遇到左括号
- while (cStack.size() > 0) {
- if (cStack.top() == '(') {
- cStack.pop();
- break;
- }
- cList.push_back(cStack.top());
- cStack.pop();
- }
- }
-
- p++;
- }
- while (cStack.size() > 0) {
- cList.push_back(cStack.top());
- cStack.pop();
- }
- printList(cList);
-
- // 波兰表达式处理完
-
- // 对 cList 中处理
-
- // 数字压栈
- // 运算符,将栈顶数字弹出,先弹出右操作数再弹出左操作数
-
- // 遍历
- for (list<char>::const_iterator cit = cList.begin(); cit != cList.end(); cit++) {
- if (isNumber(*cit)) {
- cStack.push(*cit);
- }
- else {
- char right = cStack.top();
- cStack.pop();
- char left = cStack.top();
- cStack.pop();
- switch (*cit) {
- case '+':
- cStack.push(left + right);
- break;
- case '-':
- cStack.push(left - right);
- break;
- case '*':
- cStack.push(left * right);
- break;
- case '/':
- cStack.push(left / right);
- break;
- default:
- break;
- }
- }
- }
- if (cStack.size() == 1) {
- printf("ret = %c", cStack.top());
- cStack.pop();
- }
- else {
- printf("error");
- printf("%zu", cStack.size());
- }
- system("pause");
- return 0;
- }
