文章目录
栈的顺序存储及其应用
这里是数据结构个人学习的笔记记录,如有问题欢迎指正说明
一、栈的顺序存储
栈是仅能在表尾进行插入和删除操作的线性表,遵循先进后出。
先来定义结构体变量,它类似于顺序表,不过结构体中记录长度的变量改为top来记录栈顶,具体定义如下
结构体的定义:
typedef struct CharStack{
int top;
int data[MAXSIZE];
}*CharStackPtr;
相关操作实现
1.初始化
定义一个栈,且将此时的top值定义为-1
/* 初始化 */
CharStackPtr charStackInit(){
CharStackPtr resultPtr=(CharStackPtr)malloc(sizeof(struct CharStack));
resultPtr->top=-1;
return resultPtr;
}
2.依次对栈中的每个数据元素输出
void outputStack(CharStackPtr paraStack){
for(int i=0;i<=paraStack->top;i++)
{
printf("%c ",paraStack->data[i]);
}
printf("\r\n");
}
3.进栈(push)
改变top值

void push(CharStackPtr paraStackPtr,int paraValue){
if(paraStackPtr->top>=MAXSIZE-1){
printf("Cannot push element:stack full.\r\n");
return ;
}
paraStackPtr->top++;
paraStackPtr->data[paraStackPtr->top]=paraValue;
}
4.出栈(pop)
char pop(CharStackPtr paraStackPtr){
if(paraStackPtr->top<0)
{
printf("Cannot pop element:stack empty.\r\n");
return '\0';
}
paraStackPtr->top--;
return paraStackPtr->data[paraStackPtr->top+1];
}
5.栈中元素个数
因为pop记录栈顶元素下标,所以求栈中元素的个数就十分容易了
int stackLength(CharStackPtr paraStackPtr)
{
return paraStackPtr->top+1;
}
6.具体代码实现
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 10
typedef struct CharStack{
int top;
int data[MAXSIZE];
}*CharStackPtr;
void outputStack(CharStackPtr paraStack){
for(int i=0;i<=paraStack->top;i++)
{
printf("%c ",paraStack->data[i]);
}
printf("\r\n");
}
CharStackPtr charStackInit(){
CharStackPtr resultPtr=(CharStackPtr)malloc(sizeof(struct CharStack));
resultPtr->top=-1;
return resultPtr;
}
void push(CharStackPtr paraStackPtr,int paraValue){
if(paraStackPtr->top>=MAXSIZE-1){
printf("Cannot push element:stack full.\r\n");
return ;
}
paraStackPtr->top++;
paraStackPtr->data[paraStackPtr->top]=paraValue;
}
char pop(CharStackPtr paraStackPtr){
if(paraStackPtr->top<0)
{
printf("Cannot pop element:stack empty.\r\n");
return '\0';
}
paraStackPtr->top--;
return paraStackPtr->data[paraStackPtr->top+1];
}
int stackLength(CharStackPtr paraStackPtr)
{
return paraStackPtr->top+1;
}
void pushPopTest(){
char ch;
printf("---Begin---\r\n");
CharStackPtr tempStack=charStackInit();
printf("After initialization,the stack is: ");
outputStack(tempStack);
for(ch='a';ch<'m';ch++){
printf("Pushing %c.\r\n",ch);
push(tempStack,ch);
outputStack(tempStack);
}
printf("The length of the stack is %d\n",stackLength(tempStack));
for(int i=0;i<3;i++){
ch=pop(tempStack);
printf("Pop %c.\r\n",ch);
outputStack(tempStack);
}
printf("---End---");
}
int main(){
pushPopTest();
return 0;
}
7.样例输出
—Begin—
After initialization,the stack is:
Pushing a.
a
Pushing b.
a b
Pushing c.
a b c
Pushing d.
a b c d
Pushing e.
a b c d e
Pushing f.
a b c d e f
Pushing g.
a b c d e f g
Pushing h.
a b c d e f g h
Pushing i.
a b c d e f g h i
Pushing j.
a b c d e f g h i j
Pushing k.
Cannot push element:stack full.
a b c d e f g h i j
Pushing l.
Cannot push element:stack full.
a b c d e f g h i j
The length of the stack is 10
Pop j.
a b c d e f g h i
Pop i.
a b c d e f g h
Pop h.
a b c d e f g
—End—
Finish.
二、栈的应用之括号匹配
1.匹配函数
实现原理:另外生成一个栈,遇到括号的的前半部分则压栈,遇到后半部分就与与新生成的栈的栈顶来匹配,如果不匹配则说明该式子的等号不匹配,直接返回false;否则匹配,继续执行。
bool bracketMatching(char* paraString, int paraLength) {
CharStackPtr tempStack = charStackInit();
push(tempStack, '#');
char tempChar, tempPopedChar;
for (int i = 0; i < paraLength; i++) {
tempChar = paraString[i];
switch (tempChar) {
case '(':
case '[':
case '{':
push(tempStack, tempChar);
break;
case ')':
tempPopedChar = pop(tempStack);
if (tempPopedChar != '(') {
return false;
} // Of if
break;
case ']':
tempPopedChar = pop(tempStack);
if (tempPopedChar != '[') {
return false;
} // Of if
break;
case '}':
tempPopedChar = pop(tempStack);
if (tempPopedChar != '{') {
return false;
} // Of if
break;
default:
// Do nothing.
break;
}// Of switch
} // Of for i
tempPopedChar = pop(tempStack);
if (tempPopedChar != '#') {
return true;
} // Of if
return true;
}
2.输出样例
Is the expression ‘[2 + (1 - 3)] * 4’ bracket matching? 1
Is the expression ‘( ) )’ bracket matching? 0
Is the expression ‘()()(())’ bracket matching? 1
Is the expression ‘({}[])’ bracket matching? 1
Is the expression ‘)(’ bracket matching? 0
三、表达式求值
1.C++闵版复刻
#include<iostream>
#include<cstring>
#include<algorithm>
#include<stack>
#include<unordered_map>
using namespace std;
stack<int> num;
stack<char> op;
void eval()
{
auto b=num.top();
num.pop();
auto a=num.top();
num.pop();
auto c=op.top();
op.pop();
int x;
if(c=='+')
x=a+b;
else if(c=='-')
x=a-b;
else if(c=='*')
x=a*b;
else
x=a/b;
num.push(x);
}
int main()
{
unordered_map<char,int> pr{{'+',1},{'-',1},{'*',2},{'/',2}};
string str;
cin >> str;
for(int i=0;i<str.size();i++)
{
auto c=str[i];
if(isdigit(c))
{
int x=0,j=i;
while(j<str.size()&&isdigit(str[j]))
x=x*10+str[j++]-'0';
i=j-1;
num.push(x);
}else if(c=='(')
op.push(c);
else if(c==')')
{
while(op.top()!='(')
eval();
}else{
while(op.size()&&op.top()!='('&&pr[op.top()]>=pr[c])
eval();
op.push(c);
}
}
while(op.size())
eval();
cout << num.top()<<endl;
return 0;
}
2.C版
实现思路:
(一)中缀表达式 -> 后缀表达式
从左到右遍历中缀表达式中的每个数字和符号,若是数字则输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级不高于栈顶符号则栈顶元素依次出栈并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。
(二)后缀表达式 -> 求值
从左到右遍历后缀表达式的每个数字和符号,遇到是数字就进栈,遇到是符号就将处于栈顶两个数字出栈,进行计算,运算结果进栈,一直到得到最终结果。
结构体的定义
一个存数字,一个存运算符
typedef struct
{
char *ch;
int top;
}CharStack;
typedef struct
{
int *num;
int top;
}NumStack;
初始化
void InitCharStack(CharStack &S)
{
S.ch = (char *)malloc(MAXSIZE * sizeof(char));
if (S.ch == NULL)
{
printf("内存分配失败\r\n");
return;
}
S.top = -1;
return;
}
void InitNumStack(NumStack &St)
{
St.num = (int *)malloc(MAXSIZE * sizeof(int));
St.top = -1;
return;
}
进栈
//字符进栈
void PushCharStack(CharStack &S, char c)
{
if (S.top >= MAXSIZE-1)
{
printf("栈已满\r\n");
return;
}
S.top ++;
* ++S.ch = c;
return;
}
//数字进栈
void PushNumStack(NumStack &St, int n)
{
if (St.top == MAXSIZE)
{
printf("栈已满\r\n");
}
St.top ++;
* ++St.num = n;
return;
}
出栈
char PopCharStack(CharStack &S)
{
if (S.top == -1)
{
printf("栈为空\r\n");
exit(1);
}
S.top --;
char c = *S.ch --;
return c;
}
int PopNumStack(NumStack &St)
{
if (St.top == -1)
{
printf("栈为空\r\n");
}
St.top --;
int num = *St.num --;
return num;
}
获取字符栈栈顶元素
char GetStackTop(CharStack &S)
{
char c = *S.ch;
return c;
}
优先级判断
bool PriorJudge(char c1, char c2)
{
if (c1 == '*' || c1 == '/')
if (c2 == '+' || c2 == '-' || c2 == '(')
return true;
if (c1 == '+' || c1 == '-')
if (c2 == '(') return true;
return false;
}
得到后缀表达式
char *InfixToSuffex(char *a, char *b)//infix中缀 suffex后缀
{
fgets(a, MAXSIZE-1, stdin);//从输入流中读取字符串
printf("中缀表达式为:%s\r\n",a);
int t = strlen(a);
int k = 0;
for (int i = 0; i < t; ++ i)
{
if (a[i] >= '0' && a[i] <= '9')
{
b[k ++] = a[i];
if (a[i+1] < '0' || a[i+1] > '9')
b[k ++] = '#';
}
else if (a[i] == ' ' || a[i] == '=') continue;
else
{
if(S.top == -1 || a[i] == '(')
PushCharStack(S, a[i]);
else if (a[i] == ')')
{
while (S.top != -1 && GetStackTop(S) != '(')
b[k ++] = PopCharStack(S);
if (S.top != -1) PopCharStack(S);
}
else
{
while (S.top != -1 && !PriorJudge(a[i], GetStackTop(S)))
b[k ++] = PopCharStack(S);
PushCharStack(S, a[i]);
}
}
}
return b;
}
核心计算得到最终结果
int CaculatValue(char *b, NumStack &St)
{
InitNumStack(St);
int t = strlen(b);
int num = 0;
for (int i = 0; i < t; ++ i)
{
if (b[i] >= '0' && b[i] <= '9')
{
num = 10 * num + b[i] - '0';
if (b[i+1] == '#') PushNumStack(St, num), num = 0;
}
else
{
if (b[i] == '#') continue;
int n = PopNumStack(St);
int m = PopNumStack(St);
if (b[i] == '+') PushNumStack(St, m + n);
else if (b[i] == '-') PushNumStack(St, m - n);
else if (b[i] == '*') PushNumStack(St, m * n);
else PushNumStack(St, m / n);
}
}
return PopNumStack(St);
}
完整代码实现
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXSIZE 100
typedef struct
{
char *ch;
int top;
}CharStack;
typedef struct
{
int *num;
int top;
}NumStack;
CharStack S;
NumStack St;
void InitCharStack(CharStack &S)
{
S.ch = (char *)malloc(MAXSIZE * sizeof(char));
if (S.ch == NULL)
{
printf("memory allocation failed\r\n");
return;
}
S.top = -1;
return;
}
void PushCharStack(CharStack &S, char c)
{
if (S.top >= MAXSIZE-1)
{
printf("Stack is full!\r\n");
return;
}
S.top ++;
* ++S.ch = c;
return;
}
char PopCharStack(CharStack &S)
{
if (S.top == -1)
{
printf("Stack is empty!\r\n");
exit(1);
}
S.top --;
char c = *S.ch --;
return c;
}
char GetStackTop(CharStack &S)
{
char c = *S.ch;
return c;
}
bool PriorJudge(char c1, char c2)
{
if (c1 == '*' || c1 == '/')
if (c2 == '+' || c2 == '-' || c2 == '(')
return true;
if (c1 == '+' || c1 == '-')
if (c2 == '(') return true;
return false;
}
char *InfixToSuffex(char *a, char *b)
{
fgets(a, MAXSIZE-1, stdin);//从输入流中读取字符串
printf("Infix expression is:%s\r\n",a);
int t = strlen(a);
int k = 0;
for (int i = 0; i < t; ++ i)
{
if (a[i] >= '0' && a[i] <= '9')
{
b[k ++] = a[i];
if (a[i+1] < '0' || a[i+1] > '9')
b[k ++] = '#';
}
else if (a[i] == ' ' || a[i] == '=') continue;
else
{
if(S.top == -1 || a[i] == '(')
PushCharStack(S, a[i]);
else if (a[i] == ')')
{
while (S.top != -1 && GetStackTop(S) != '(')
b[k ++] = PopCharStack(S);
if (S.top != -1) PopCharStack(S);
}
else
{
while (S.top != -1 && !PriorJudge(a[i], GetStackTop(S)))
b[k ++] = PopCharStack(S);
PushCharStack(S, a[i]);
}
}
}
return b;
}
void InitNumStack(NumStack &St)
{
St.num = (int *)malloc(MAXSIZE * sizeof(int));
St.top = -1;
return;
}
void PushNumStack(NumStack &St, int n)
{
if (St.top == MAXSIZE)
{
printf("Stack is full!\r\n");
}
St.top ++;
* ++St.num = n;
return;
}
int PopNumStack(NumStack &St)
{
if (St.top == -1)
{
printf("Stack is empty!\r\n");
}
St.top --;
int num = *St.num --;
return num;
}
int CaculatValue(char *b, NumStack &St)
{
InitNumStack(St);
int t = strlen(b);
int num = 0;
for (int i = 0; i < t; ++ i)
{
if (b[i] >= '0' && b[i] <= '9')
{
num = 10 * num + b[i] - '0';
if (b[i+1] == '#') PushNumStack(St, num), num = 0;
}
else
{
if (b[i] == '#') continue;
int n = PopNumStack(St);
int m = PopNumStack(St);
if (b[i] == '+') PushNumStack(St, m + n);
else if (b[i] == '-') PushNumStack(St, m - n);
else if (b[i] == '*') PushNumStack(St, m * n);
else PushNumStack(St, m / n);
}
}
return PopNumStack(St);
}
int main()
{
InitCharStack(S);
char a[MAXSIZE]={0};
char b[MAXSIZE]={0};
InfixToSuffex(a,b);
printf("The suffix expression is:%s\r\n",b);
int ans=CaculatValue(b,St);
printf("The value of the expression is:%d\r\n",ans);
return 0;
}
样例输出
9+(3-1)*3+10/2
Infix expression is:9+(3-1)*3+10/2The suffix expression is:9#3#1#-3#*+10#2#/+
The value of the expression is:20
四、写在最后
希望我们都能学好数据结构。
本文详细介绍了栈的顺序存储结构,包括初始化、输出、进栈、出栈、获取栈中元素个数等操作,并通过代码实现。接着,展示了栈在括号匹配中的应用,以及如何利用栈进行表达式求值。最后,提供了C++和C语言版本的表达式求值算法,以及对应的样例输出。


394

被折叠的 条评论
为什么被折叠?



