数据结构
栈
又称堆栈,它是一种运算受限的线性表,其限制是仅允许在表的一端进行插入和删除运算。人们把此端称为栈顶,栈顶的第一个元素被称为栈顶元素,相对地,把另一端称为栈底。向一个栈插入新元素又称为进栈或入栈,它是把该元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称为出栈或退栈,它是把栈顶元素删除掉,使其下面的相邻元素成为新的栈顶元素。
栈的实现:https://blog.csdn.net/wfea_lff/article/details/103343438
逆波兰式
逆波兰式又叫做后缀表达式,我们平时所写的表达式为中缀表达式
逆波兰式作用
中缀表达式是相对人类的思维结构来说比较简单的,对计算机而言中序表达式是非常复杂的结构。相对的,逆波兰式在计算机看来却是比较简单易懂的结构。因为计算机普遍采用的内存结构是栈式结构,它执行先进后出的顺序
例:
中缀表达式 : (1+2)3/4
将上面的中缀表达式转换成逆波兰式
后缀表达式 : 12+34/
后缀表达式的运算过程
从头开始遍历,遇到运算符则将其运算符前面的两个数字进行该运算符操作,算出结果继续向后遍历,同理遇到运算符便进行之前的操作
后缀表达式的实现
转化过程利用了栈的先进后出的特性
1.创建两个栈s1,s2
s1用来存储运算符
s2用来存储中间结果
2.将中缀表达式的字符按照规则存入s1和s2
规则:
1)当遇到数字时,将其存入s2中
2)当遇到表达式的运算符时,让其之前已经存入s1栈顶的运算符比较优先级
(1) 若运算符比栈顶的运算符优先级低或是等于就将栈顶的运算符出栈并入栈到s2中,然后继续比较现在出栈过后的s1的栈顶与表达式运算符的优先级,继续完成同上所述操作;直到遇到了比表达式运算符低的栈顶时,便将表达式的运算符存入s1中,继续遍历表达式的下一个字符
(2)如果s1没有数据元素,则直接将运算符入栈s1
3)处理‘( ’ 和 ‘)’的问题
(1)如果碰见了’( ‘,直接入栈s1
(2)如果碰上了‘ )‘则将s1的栈顶不断的出栈并入栈到s2中,直到遍历到s1栈顶为’( ‘时停止,并将’( ‘出 栈丢弃
(3)’( ‘ 和’ )‘并不能进入s2中,相当于只是一个中间量,
3.重复 2 里面的所有过程,直到表达式遍历结束
4.将s2中的栈顶依次出栈并入栈到s1中
5.将s1中的栈顶依次出栈并输出,即得到后缀表达式(逆波兰式)
代码实现:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
//----------------------栈的实现--------------------------
typedef char ElemType;
#define STACKSIZE 10
typedef struct Stack //定义栈的结构体
{
ElemType *data;
ElemType top;
int stacksize;
}*StackPtr;
int Init_Stack(StackPtr stack) //初始化
{
if(stack == NULL) exit(0);
stack->data = (ElemType*)malloc(sizeof(ElemType)*STACKSIZE);
stack->stacksize = STACKSIZE;
stack->top = 0;
return true;
}
int Push_Stack(StackPtr stack,ElemType val) //入栈
{
if(stack == NULL) exit(0);
stack->data[stack->top] = val;
stack->top++;
return true;
}
int Pop_Stack(StackPtr stack) //出栈
{
if(stack==NULL) exit(0);
stack->top--;
return true;
}
int GetTop(StackPtr stack) //获取栈顶
{
if(stack == NULL) exit(0);
return stack->data[stack->top-1];
}
int Empty_Stack(StackPtr stack) //判空
{
if(stack == NULL) exit(0);
if(stack->top == 0)
{
return true;
}
else
{
return false;
}
}
static int Apply_Stack(StackPtr stack) //申请空间
{
ElemType* p = (ElemType*)malloc(sizeof(ElemType)*stack->stacksize*2);
if(p == NULL) return false;
for(int i=0;i<stack->top;i++)
{
p[i] = stack->data[i];
}
free(stack->data);
stack->data = p;
p = NULL;
stack->stacksize*=2;
return true;
}
static int Full_Stack(StackPtr stack) //判满
{
if(stack->stacksize == stack->top&&stack->top != 0)
{
Apply_Stack(stack);
return true;
}
else
{
return false;
}
}
int Clear_Stack(StackPtr stack) //清空
{
if(stack == NULL) exit(0);
stack->top = 0;
return true;
}
int Destroy_Stack(StackPtr stack) //销毁
{
if(stack == NULL) exit(0);
free(stack->data);
stack->data = NULL;
stack->top = 0;
stack->stacksize = 0;
return true;
}
//------------------------------------------------------
//--------------------逆波兰式实现------------------------
int OperPre(char oper) //处理优先级
{
int tmp;
switch(oper)
{
case '+':
case '-':
tmp = 1; break;
case '*':
case '/':
tmp = 2;break;
default:
tmp = 3;
}
return tmp;
}
void RPNotation(char *buff) //逆波兰式实现
{
Stack s1,s2; //定义两个栈是s1,s2
Init_Stack(&s1); //初始化栈
Init_Stack(&s2);
while(1) //逆波兰实现
{
if(isdigit(*buff)) //将数字存入s2
{
Push_Stack(&s2,*buff);
}
if(!isdigit(*buff))
{
while(OperPre(*buff)<=OperPre(GetTop(&s1)))
{
if(s1.top == 0) break; //若s1没数据则直接入栈
if(GetTop(&s1)=='(') break; //处理‘(’问题
Push_Stack(&s2,GetTop(&s1)); //将s1的栈顶压入s2
Pop_Stack(&s1); //s1出栈
}
if(*buff != ')') //若出现‘)’则交给下一个if条件语句处理
{
Push_Stack(&s1,*buff);
}
}
if(*buff == ')') //处理‘(’,‘)’问题
{
while(GetTop(&s1) != '(') //将‘(’之前的运算符压入s2中
{
Push_Stack(&s2,GetTop(&s1));
Pop_Stack(&s1);
}
Pop_Stack(&s1); //运算符处理完后,将‘(’出栈
}
buff++;
if(*buff == '\n') break; //结束条件
}
while(s2.top != 0) //将(栈)s2压入(栈)s1
{
Push_Stack(&s1,GetTop(&s2));
Pop_Stack(&s2);
}
printf("后缀表达式:\n");
while(s1.top != 0) //输出(栈)s1的值
{
printf("%c",GetTop(&s1));
Pop_Stack(&s1);
}
printf("\n");
}
int main()
{
char buff[128];
printf("中缀表达式:\n");
fgets(buff,127,stdin);
RPNotation(buff);
return 0;
}