逆波兰式 栈实现

因为做二叉树非递归的前后中遍历,用到栈的方法。xpp说那就干脆把四则运算,逆波兰式 栈的实现做了。

这是参考别人的程序写的,注释比较乱。而且这个是直接实现计算机计算的四则运算,没有将逆波兰的表达式打印出来。今天腰太酸了,明天改一改,把逆波兰式打印出来噻333333.栈还有迷宫算法是不是???现在脑子里之前看的非递归遍历都想不起来了我擦

#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
#include"string.h"


#define MAX_OPE_LEN 10
#define MAX_STRING_LEN 100
#define MAX_STACK_LEN 100

//
typedef struct operater
{
	char name;
	int pior;
	int opernum;
}Operater;


Operater opStack[MAX_OPE_LEN];
int opStacktop=-1;//外加一个指示栈顶的数,这也挺奇葩的

double   numStack[MAX_STACK_LEN];
int numStacktop=-1;

int getPior(char name)
{
	if (name=='('||name==')')//注意括号的优先级
	{	return 0;}
	if (name=='+'||name=='-')
	{	return 1;}
	if(name=='*'||name=='/')
	{	return 2;}
	if(name=='!')
	{	return 3;}
	exit(1);//其他情况则直接退出
}

int getopernum(char name)
{
	if(name=='+'||name=='-'||name=='*'||name=='/')
	{	return 2;}
	if(name=='!')
	{	return 1;}
	if(name=='('||name==')')//特别注意括号的操作数为0;
	{	return 0;}
	exit(1);
}

void pushoperater(Operater op)//入栈操作的是一个 运算符
{
	if (opStacktop<MAX_OPE_LEN-1 )
	{opStack[++opStacktop]=op;}
	else
	{exit(1);}
}

Operater popoperater()
{
	if(opStacktop!=-1)
	{return opStack[opStacktop--];}
	else
	{exit(1);}
}


void pushnum(double num)
{
	if (numStacktop<MAX_STACK_LEN-1)
	{numStack[++numStacktop]=num;}
	else
	{exit(1);}
}

double popnum()
{
	if (numStacktop!=-1)
	{return numStack[numStacktop--];}
	else
	{exit(1);}
}

//将输入的浮点数字符转化为double
//这个部分也是难点之一

double getNumfromString(char *s,int *i)//char *s是char类型的字符输入开始
{
	static char string[MAX_STRING_LEN];
	int j=0;
	while (*s>='0'&&*s<='9')
	{
		string[j++]=*s;
		s++;
	}
	if (*s=='.')
	{
		string[j++]=*s;
		s++;
		while(*s>='0'&&*s<='9')
		{
			string[j++]=*s;
		    s++;
		}

	}
	(*i)=(*i)+j;
	string[j]='\0';//表示字符结束
	return atof(string);//将这个字符转化为num
}

double operater2num(Operater op)
{
	double num2=popnum();
	double num1=popnum();
	if (op.name=='+')
	{return num1+num2;}
	if (op.name=='-')
	{return num1-num2;}
	if(op.name=='*')
	{return num1*num2;}
	if(op.name=='/')
	{return num1/num2;}
	{exit(1);}
}
//=============这部分也是比较难的,暂时可以不看啊===========
double operater1num(Operater op)//非操作?为何是这样??
{
    double num = popnum();
    if (op.name == '!')
    {
        double result = 1;
        while (num > 1)
        {
            result *= num;
            num--;
        }
        return result;
    }
    exit(1);
}

double operater(Operater op)
{
	if (op.opernum==2)
	{return operater2num(op);}
	if (op.opernum==1)
	{return operater1num(op);}
	exit(1);
}

//进入复杂的主函数操作
int main()
{
	char string[MAX_STRING_LEN ];
	printf("输入中缀运算表达式:\n");
	scanf("%s",string);//注意scanf的用法,输入到string中。%S表明输入的是字符串啊啊啊啊啊啊,%f,输入的是float型啊啊啊啊,并且没有该死的\n

	Operater op,opTop;//后者为栈顶运算符,这个用来表示操作符到了最底部
	opTop.name='#';
	opTop.opernum=0;
	opTop.pior=0;

    pushoperater(opTop);

	int i=0;
	for(i;string[i]!='\0'&&string[i]!='=';)
	{
		if (string[i]>='0'&&string[i]<='9')
		pushnum(getNumfromString(&string[i],&i));//把从i开始的数字都取完,转成num压入栈
    	else
     	{
	    	op.name=string[i];
	    	op.opernum=getopernum(op.name);
	    	op.pior=getPior(op.name);
	    	opTop=popoperater();//把操作符的栈顶操作符与 新发现的操作符对比

			if (op.name=='(')
				{
					pushoperater(opTop);
				    pushoperater(op);
			}
			else if (op.name==')')
			{
				while(opTop.name!='(')//只要没到左括号,将这之间的操作数 与numStack中的Num取出来实行运算,运算结果压入numStack

				{
					pushnum(operater(opTop));
					opTop=popoperater();
				}

			}
			else
			{
				if (opTop.name!='#'&&op.pior<=opTop.pior)
				{
					pushnum(operater(opTop));
					
				}
				else
				{
					pushoperater(opTop);
				}
				pushoperater(op);
			}
				
			i++;//因为操作符是一个一个的字符,上面字符与数字转换的时候,可能不是一个一个的加的
     	}   
		
   //string已经转换完了,这个时候操作符栈还有剩,则全部取出来操作
		
       }
       while((opTop = popoperater()).name != '#')
		{
			pushnum(operater(opTop));
			
		}
		 printf("%f\n", popnum());
	     system("pause");
	return 0;
}
逆波兰式 栈实现_第1张图片

你可能感兴趣的:(逆波兰式 栈实现)