这篇文章收录了王道考研课程中涉及的数据结构的所有代码。此外,本博客可能会添加一些额外的代码(不仅限于王道考研),因为408考试中会频繁考察一些冷门的知识点,所以这篇博客会涵盖所有相关的代码。这也是我数据结构的第一轮复习,希望能与大家共同进步。由于博客篇幅的限制,可能无法一次性包含所有内容,欢迎指出代码错误部分!!!
// @FileName :07BiaoDaShi.c
// @Time :2023/8/15 14:57
// @Author :YKW
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
#define MaxSize 50
//表达式求值(波兰式/逆波兰式,前缀/后缀表达式)
//后缀表达式 5 7 1 1 + - / 3 * 2 1 1 + + -
//A B + C D * E / - F +
typedef struct Calc {//计算结构体
char num[MaxSize];
int top;
} calc;
typedef struct Revert{//转换结构体
char data;
struct revert*next;
}revert;
void cInitStack(calc *C) {
C->top = -1;
}
bool cPop(calc *C, char *e) {
*e = C->num[C->top];
(C->top)--;
}
bool cPush(calc *C, char e) {
C->num[++(C->top)] = e;
}
void rInitStack(revert *S) {
S->next=NULL; //刚开始没有结点
}
bool StackEmpty(revert* S){
return S->next==NULL;
}
bool rPop(revert *S, char *e) {
if(S->next==NULL)//空栈
return false;
*e=S->data;
revert *p=S;
S=S->next;
free(p);
return true;
}
bool rPush(revert *S, char e) {
revert *s=(revert*)malloc(sizeof(revert));
if(s==NULL)//内存不足,分配失败
return false;
s->data=e;
s->next=S;
S=s;
return true;
}
//计算逆波兰(后缀)
int CRP() {
calc C;
cInitStack(&C);
char s;
char ans = 0;
char num1, num2;
printf("输入后缀表达式:");
//scanf( "%[^\n]",str); %[^\n] 的意思就是“遇到换行才结束”
while (scanf("%c", &s) != EOF) {
if (isdigit(s) && s != 0) {//扫到符号开始算,算到没有符号
cPush(&C, s);
} else if (s == '+' || s == '-' || s == '*' || s == '/') {
cPop(&C, &num1);
cPop(&C, &num2);
int n1=num1-'0',n2=num2-'0';
if (s == '+')
ans = n2 + n1;
else if (s == '-')
ans = n2 - n1;
else if (s == '*')
ans = n2 * n1;
else if (s == '/')
ans = n2 / n1;
cPush(&C, ans+'0');
}else if(s=='\n'){
return C.num[C.top]-'0';
}
}
}
//转化为中缀
char RRP() {
char temp,a[MaxSize],b[MaxSize]; //静态数组a、b分别存放要转换的中缀表达式和转换后的后缀表达式,字符变量temp存放弹出的栈顶元素
scanf("%s",&a); //需要您输入中缀表达式
revert *S;//初始化一个栈,用于保存括号和暂时还不能确定运算顺序的运算符
rInitStack(S); //初始化链栈
int i,j,length=strlen(a); //length为输入的中缀表达式的总长度,i、j分别为静态数组a、b的索引下标
for(i=j=0;i<length;i++){
if(a[i]>='0' && a[i]<='9'){ //若当前字符是数字,字符0-9的ACSII码范围是[48,57]
b[j++]=a[i];
if(a[i+1]=='+'||a[i+1]=='-'||a[i+1]=='*'||a[i+1]=='/') //若下一个字符是运算符,即+、-、*、/,则b加一个空格,以免不同的操作数混在一起
b[j++]=' ';
}
else if(a[i]=='(')
rPush(S,a[i]); //若当前字符是左括号则直接入栈
else if(a[i]==')'){ //若当前字符是右括号
while(StackEmpty(S)==0){ //栈非空则不断弹出栈内字符并加入后缀表达式
rPop(S,&temp);
if(temp=='(') //直到弹出左括号停止,注意这个(不加入后缀表达式
break;
b[j++]=temp;
b[j++]=' '; //加一个空格,从而将字符隔开
}
}
else switch(a[i]){ //若当前字符是运算符
case '*': case '/':{
while(StackEmpty(S)==0){ //若栈非空,则弹出栈中优先级高于或等于当前运算符的所有运算符,并将这些运算符加入后缀表达式
rPop(S,&temp);
if(temp=='/'||temp=='*'){
b[j++]=temp;
b[j++]=' '; //加一个空格,从而将字符隔开
}
else if(temp=='('||temp=='-'||temp=='+'){//若栈顶元素是左括号或者是优先级低于当前字符的运算符,则将栈顶元素入栈
rPush(S,temp);
break;
}
}
rPush(S,a[i]); //把当前字符入栈
break;
}
case '-': case '+':{
while(StackEmpty(S)==0){ //若栈非空,则弹出栈中优先级高于或等于当前运算符的所有运算符,并将这些运算符加入后缀表达式
rPop(S,&temp);
if(temp=='('){//若栈顶元素是左括号,则将栈顶元素入栈
rPush(S,temp);
break;
}
else if(temp=='/'||temp=='*'||temp=='-'||temp=='+'){
b[j++]=temp;
b[j++]=' '; //加一个空格,从而将字符隔开
}
}
rPush(S,a[i]); //把当前字符入栈
break;
}
}
}
while(StackEmpty(S)==0){ //栈非空时依次弹出栈顶元素并加入后缀表达式
rPop(S,&temp);
b[j++]=temp;
b[j++]=' '; //加一个空格,从而将字符隔开
}
printf("结果是:\n");
for(i=0;i<j;i++) //j是数组中下一个可以插入元素的位置下标,因此b中存放字符的索引区间为[0,j-1]
printf("%c",b[i]); //输出b中的元素
printf("\n");
return 0;
}
int main() {
// printf("%d", CRP());
RRP();
}