- #include <iostream>
- #define MAXSIZE 20
- using namespace std;
- int total = 4;
- typedef char ElemType;
- typedef struct
- {
- ElemType elem[MAXSIZE];
- int top;
- }SqStack;
- typedef struct
- {
- float elem[MAXSIZE];
- int top;
- }FSqStack;
- typedef struct LinkNode
- {
- int data;
- struct LinkNode *next;
- }LinkStack;
- SqStack *pst = NULL;
- template<typename T>
- void InitSqStack(T *&st)
- {
- st->top = -1;
- }
- template<typename T>
- int StackEmpty(T *&st)
- {
- return st->top == -1 ? 1 : 0;
- }
- template<typename T,typename N>
- int Push(T *&st, N e)
- {
- if(st->top >= MAXSIZE - 1)
- return -1;
- st->top++;
- st->elem[st->top] = e;
- return 1;
- }
- template<typename T,typename N>
- int Pop(T *&st, N &e)
- {
- if(st->top < 0)
- return -1;
- e = st->elem[st->top];
- st->top--;
- return 1;
- }
- //一下是链栈的初始化
- int InitLinkStack(LinkStack *&ls)
- {
- ls = (LinkStack *)malloc(sizeof(LinkStack));
- ls->next = NULL;
- return 1;
- }
- int Push(LinkStack *&ls, int e)
- {
- LinkStack *temp = (LinkStack *)malloc(sizeof(LinkStack));
- if(temp == NULL) return -1;
- temp->data = e;
- temp->next = ls;
- ls = temp;
- return 1;
- }
- int Pop(LinkStack *&ls,int &e)
- {
- LinkStack *temp = NULL;
- if(ls == NULL ||ls->next == NULL) //此处应该把ls == NULL 的顺序放在前面, 要不然会发生非法内存访问
- { cout<<"栈已经为空"<<endl;
- return -1;
- }
- else
- {
- temp = ls;
- e = temp->data;
- ls = ls->next;
- free(temp);
- }
- return 1;
- }
- int StackEmpty(LinkStack *<)
- {
- if(lt == NULL || lt->next == NULL)
- return 1;
- else return 0;
- }
- int DelLinkStack(LinkStack *&ls)
- {
- LinkStack *temp = ls;
- if(ls == NULL) return 1;
- while(temp != NULL)
- {
- temp = ls->next;
- free(ls);
- if(temp == NULL){ ls = NULL; return 1; } //此处应该把ls 赋值为NULL 。 有利于其他函数进行判断
- ls = temp;
- }
- ls = NULL;
- return 1;
- }
- void tran(char exp[], char postExp[]) //本函数的目的是把算术表达式转换为后缀表达式(逆波兰表达式),然后根据该后缀表达式求值
- {
- int loop1=0, loop2=0;
- SqStack *op = (SqStack *)malloc(sizeof(SqStack)); //此处定义一个符号栈指针
- char c = exp[loop1++], temp;
- if(op == NULL ) return ;
- InitSqStack(op);
- while(c != '\0') //遍历表达式exp
- { //cout<<c<<endl;
- switch(c)
- {
- case '(': //遇到'('的时候把它进栈
- Push(op,c);
- c = exp[loop1++];
- break;
- case ')': //遇到')'的时候把 '( '以后的符号 出栈,把出栈的符号放进postExp后缀数组中
- if(!StackEmpty(op))
- {
- Pop(op,temp);
- while(temp != '(')
- {
- postExp[loop2++] = temp;
- Pop(op,temp);
- }
- }
- c = exp[loop1++];
- break;
- case '+':
- case '-': //当遇到'+','-' 的时候,如有'('则把其之后的符号出栈,放进postExp数组中,但是'('不出栈, 最后把 '+','-'进栈
- if(!StackEmpty(op)) //如果没有'(' 那么就把全部的符号出栈,放进postExp数组中,最后在把'+','-'进栈
- {// cout<<"if here is running"<<endl;
- Pop(op,temp);
- while(temp != '(' )
- {//&& !StackEmpty(op)
- // cout<<"look - or + value is :"<<temp<<endl;
- // system("pause");
- postExp[loop2++] = temp;
- if(!StackEmpty(op))
- { //cout<<"not empty"<<endl;
- Pop(op,temp);
- }else
- {
- break;
- }
- }
- if(temp == '(') Push(op, '(');
- Push(op,c);
- }else
- {
- Push(op,c);
- }
- c = exp[loop1++];
- break;
- case '*': //当遇到'*','/'的时候, 如栈顶的元素是'*','/'的时候则出栈,一直到遇到'(' 或者栈为空为止, 最后通遇到'+','-'一样把'*','/'进栈
- case '/':
- if(!StackEmpty(op)) //不为空的时候进行操作
- {
- Pop(op, temp);
- if(temp != '*' || temp != '/')
- { Push(op, temp);}
- else
- {
- while(temp == '*' || temp == '/' )
- { postExp[loop2++] = temp;
- if(StackEmpty(op)) break;
- Pop(op,temp);
- }
- // if(!StackEmpty(op)) Push(op, temp);
- Push(op,temp);
- }
- }
- Push(op,c);
- c = exp[loop1++];
- break;
- default : //到遇到数字的时候,就一个个取出来,不进栈,而是直接放入到postExp数组中,直到不是数字为止在postExp中加一个'#'以示区别
- postExp[loop2++] = c;
- c = exp[loop1++];
- while(c <= '9' && c >= '0')
- { postExp[loop2++] = c;
- c = exp[loop1++];
- }
- postExp[loop2++] = '#';
- break;
- }
- }
- while(!StackEmpty(op)) //如果栈中还有符号元素,则把它们全部取出,放入postExp数组中
- {
- Pop(op, temp);
- postExp[loop2++] = temp;
- }
- postExp[loop2] = '\0';
- }
- int compvalue(char postExp[], float &value) //此函数的作用是通过tran求的逆波兰表达式,来计算该表达式的值
- {
- char c;
- int loop1 = 0, IntValue = 0;
- float midValue = 0, tempValue1 = 0, tempValue2 = 0; //此处定义一个数字栈
- FSqStack *fst = (FSqStack *)malloc(sizeof(FSqStack));
- if(fst == NULL)
- return -1;
- InitSqStack(fst);
- c = postExp[loop1++];
- while(c != '\0') //变量postExp数组
- {
- switch(c)
- {
- case '+' : //当遇到'+'的时候,出栈两个数,把出栈的两个数相加,然后入栈
- Pop(fst,tempValue1);
- Pop(fst,tempValue2);
- midValue = tempValue2 + tempValue1;
- Push(fst, midValue);
- c = postExp[loop1++];
- break;
- case '-' : //当遇到'-'的时候,出栈两个数,把出栈的两个数相减,然后入栈
- Pop(fst,tempValue1);
- Pop(fst,tempValue2);
- midValue = tempValue2 - tempValue1;
- Push(fst,midValue);
- c = postExp[loop1++];
- break;
- case '*' : //当遇到'*'的时候,出栈两个数,把出栈的两个数相乘,然后入栈
- Pop(fst,tempValue1);
- Pop(fst,tempValue2);
- midValue = tempValue1 * tempValue2;
- Push(fst,midValue);
- c = postExp[loop1++];
- break;
- case '/' : //当遇到'/'的时候,出栈两个数,把出栈的两个数相除,然后入栈
- Pop(fst,tempValue1);
- Pop(fst,tempValue2);
- if(tempValue2 == 0) { cout<<"发生除零错误"<<endl; exit(0);}
- midValue = tempValue2 / tempValue1;
- Push(fst, midValue);
- c = postExp[loop1++];
- break;
- default : //在此表示遇到了数字, 通过 一定的表达式来求得 该数字的值 ,然后把该数字入栈
- IntValue = 0;
- IntValue = c - '0';
- c = postExp[loop1++];
- while(c != '#')
- {
- IntValue *= 10;
- IntValue += (c - '0');
- c = postExp[loop1++];
- }
- Push(fst,(float)IntValue);
- c = postExp[loop1++];
- break;
- }
- }
- if(!StackEmpty(fst))
- { cout<<"求的值为下:"<<endl;
- Pop(fst,value);
- }
- return 1;
- }
- void process(int pos, int path[], int curp) //此函数中的pos值只能通过恢复到栈原来的环境,来恢复pos的值,本函数中没有直接操作pos值的语句除了递归函数的语句外
- {
- int m,i,x;
- if(pos <= total)
- {
- Push(pst, pos);
- process(pos+1,path,curp);
- Pop(pst,x);
- } //此递归和回代的过程,只改变pos的值,栈中的数据不变
- if(!StackEmpty(pst))
- {
- Pop(pst,m);
- path[curp] = m;
- curp++;
- process(pos,path,curp);
- Push(pst,m);
- }
- if(pos>total && StackEmpty(pst))
- {
- cout<<" ";
- for(i=0; i<curp; i++)
- cout<<path[i]<<" ";
- cout<<endl;
- }
- } //此函数是全排列的一个实现
- void quanpailie(char str[], int begin, int length)
- {
- int loop1 = 0, loop2 = 0;
- char temp;
- if(begin == length - 1)
- cout<<str<<endl;
- for(loop1 = begin; loop1 < length; loop1++)
- {
- temp = str[begin];
- str[begin] = str[begin + loop2];
- str[begin + loop2] = temp;
- quanpailie(str, begin + 1, length);
- temp = str[begin];
- str[begin] = str[begin + loop2];
- str[begin + loop2] = temp; //以下代码是为了恢复之前的环境
- loop2++;
- }
- }
- /*
- begin表示str开始的位置,length表示字符串的长度
- 此算法的思路是 从第一个字符开始, 第一个字符依次与其本身以及其后面的字符交换,每次交换后进行递归操作,是begin+1, 开始操作下一个字符,当操作到最后一个字符的时候
- 进行输出, 并且在递归调用后进行 恢复环境操作
- */
- void quanpailie2(char str[], int end) //此函数的功能与上一个一样
- {
- int loop1 = 0, loop2 = 0;
- char temp;
- if(end == 0)
- cout<<str<<endl;
- for(loop1 = 0; loop1 <= end; loop1++)
- {
- temp = str[end];
- str[end] = str[loop1];
- str[loop1] = temp;
- quanpailie2(str, end - 1);
- temp = str[end];
- str[end] = str[loop1];
- str[loop1] = temp;
- loop2++;
- }
- }
- /*
- 此函数的思想是 先把第一个字符与最后一个字符交换, 然后从最后一个字符向前遍历,直到遇到第一个字符,此函数的思想与上一个不同
- */
- void get_command() {
- cout<<"\n请输入要进行运算的表达式,包括\" +,-,*,/,=,(,)\"和数字,"<<endl
- <<"例如:\" 3+2*(6-25/4)-8 \"."<<endl
- <<"注意: 以数字开头,等号结尾,中间括号要匹配."<<endl;
- }
- int main()
- {
- /* int path[5];
- pst = (SqStack *)malloc(sizeof(SqStack));
- InitSqStack(pst);
- process(1,path,0);
- */
- char exp[80], postExp[100];
- float value;
- while(true)
- {
- // cout<<"输入'q'退出"<<endl<<"输入表达式:"<<endl;
- get_command();
- cin>>exp;
- strcpy(postExp,"\0");
- if(exp[0] == 'q') break;
- tran(exp, postExp);
- // cout<<"fdf"<<endl;
- cout<<postExp<<endl;
- compvalue(postExp,value);
- cout<<value<<endl<<endl;
- }
- /*
- LinkStack *ls = NULL;
- char c[] = "abcd";
- int e;
- InitLinkStack(ls);
- Push(ls,1);
- Push(ls,4);
- cout<<StackEmpty(ls)<<endl;
- Pop(ls,e);
- cout<<e<<endl;
- DelLinkStack(ls);
- // cout<<ls<<endl;
- Pop(ls,e);
- // cout<<e<<endl;
- quanpailie2(c,3 );
- cout<<endl;
- quanpailie(c,0,4);*/
- system("pause");
- return 1;
- }
转载于:https://blog.51cto.com/saibro/1183569