#include
#include
#include
#include
#include
#include //gcc6.3可不加
#include
#include
using namespace std;
typedef int Rank;
#define DEFAULT_CAPACITY 3
#define N_OPTR 9
const char OPSET[N_OPTR] = { '+', '-', '*', '/', '^', '!', '(', ')', '\0' };
const char pri[N_OPTR][N_OPTR] = {
//横当前运算符,竖栈顶运算符
// + - * / ^ ! ( ) \0
/* +*/'>', '>', '<', '<', '<', '<', '<', '>', '>',
/* -*/'>', '>', '<', '<', '<', '<', '<', '>', '>',
/* **/'>', '>', '>', '>', '<', '<', '<', '>', '>',
/* /*/'>', '>', '>', '>', '<', '<', '<', '>', '>',
/* ^*/'>', '>', '>', '>', '>', '<', '<', '>', '>',
/* !*/'>', '>', '>', '>', '>', '>', ' ', '>', '>',
/* (*/'<', '<', '<', '<', '<', '<', '<', '=', ' ',
/* )*/' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
/*/0*/'<', '<', '<', '<', '<', '<', '<', ' ', '=',
};
template
class Stack {
private:
Rank _top;
Rank _buttom;
int _capacity;
T *_elem;
protected:
void expand();
void shrink();
public:
Stack(int c = DEFAULT_CAPACITY);
~Stack();
Rank GetSize();
bool isEmpty();
void push(T const &e);
T pop();
T &top();
void show();
};
template
Stack::Stack(int c)
{
_elem = new T[_capacity = c];
_buttom = 0;
_top = 0;
}
template
Stack::~Stack()
{
delete[] _elem;
}
template
Rank Stack::GetSize()
{
return _top - _buttom;
}
template
bool Stack::isEmpty()
{
return (_top == _buttom) ? true : false;
}
template
void Stack::expand()
{
_capacity = max(_capacity, DEFAULT_CAPACITY);
T *oldelem = _elem;
_elem = new T[_capacity <<= 1];
for (int i = 0; i < GetSize(); ++i)
_elem[i] = oldelem[i];
delete[] oldelem;
}
template
void Stack::push(T const &e)
{
if (GetSize() >= _capacity) expand();
_elem[_top++] = e;
}
template
T &Stack::top()
{
return _elem[_top - 1];
}
template
void Stack::shrink()
{
//cout<<"start shrink"<
T Stack::pop()
{
_top--;
if (GetSize() * 2 < _capacity) shrink();
return _elem[_top];
}
template
void Stack::show()
{
cout << "top: " << _top << "\tbuttom: " << _buttom << endl;
cout << "size: " << GetSize() << "\tcapacity: " << _capacity << endl;
for (int i = 0; i < GetSize(); ++i)
cout << _elem[i] << "\t";
cout << endl;
}
//进制转换n进制转b进制(逆序输出)
void convert(Stack &s, int n, int b)
{
static char digit[] = { '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
while (n > 0)
{
s.push(digit[n%b]);
n /= b;
}
}
//括号匹配
bool paren(const char exp[])
{
Stack s;
for (int i = 0; i < strlen(exp); ++i)
{//左括号入栈,遇到右括号pop。栈空还能遇到右括号则不匹配
if ('(' == exp[i])s.push(exp[i]);
else if (!s.isEmpty() && ')' == exp[i])s.pop();
else if (s.isEmpty() && ')' == exp[i])return false;
}
return s.isEmpty();//栈空匹配,不空失配
}
//栈混洗的种数为(2n)!/((n+1)!n!)
//对于任意三个元素123出312必非栈混洗(充要条件)
template
bool permutation(Stack &s, const T exp[], int expSize)
{//s.pop() -> exp[] s是倒序的,先出栈的后push入
if (expSize != s.GetSize()) return false;
Stack t;
for (int i = 0, j = 0; i < expSize; ++i)
{
t.push(s.pop());
while (t.GetSize() > 0 && t.top() == exp[j])
{
t.pop();
j++;
}
}
return (t.isEmpty() == true) ? true : false;
}
//读入数据,处理多位数,(从属于evaluate)
void readNumber(char *&p, Stack& stk)
{
stk.push(float(*p - '0'));
while (isdigit(*(++p))) stk.push(stk.pop() * 10 + (*p - '0'));
if ('.' != *p)return;
float fraction = 1;
while (isdigit(*(++p)))stk.push(stk.pop() + (*p - '0')*(fraction /= 10));
}
//判断优先级(从属于evaluate)
char orderBetween(char &e, char &s)
{
int i, j;
for (i = 0; i < N_OPTR; ++i)
if (e == OPSET[i])break;
for (j = 0; j < N_OPTR; ++j)
if (s == OPSET[j])break;
return pri[i][j];
}
//一二元运算计算(从属于evaluate)
float calcu(float p1, char op, float p2 = 0)
{
switch (op) {
case '+':return p1 + p2;
case '-':return p1 - p2;
case '*':return p1 * p2;
case '/':return p1 / p2;
case '^': {
float c = 1;
while (p2--) c = c * p1;
return c;
}
case '!': {
if (p1 == 0)return 1;
else return p1 * calcu(p1 - 1, '!');//递归求阶乘
}
}
}
//将数字写入逆波兰
void append(char *&rpn, float opnd)
{
int n = strlen(rpn);
char buf[64];
if (opnd != float(int(opnd)))sprintf(buf, "%.2f \0", opnd); //小数
else sprintf(buf, "%d \0", int(opnd)); //整数
rpn = (char*)realloc(rpn, sizeof(char)*(n + strlen(buf) + 1)); //扩展空间,需要stdlib.h malloc.h
strcat(rpn, buf); //RPN加长
}
//将运算符写入逆波兰
void append(char *& rpn, char optr) { //将运算符接至RPN末尾
int n = strlen(rpn); //RPN当前长度(以'\0'结尾,长度n + 1)
rpn = (char*)realloc(rpn, sizeof(char) * (n + 3)); //扩展空间
sprintf(rpn + n, "%c ", optr); rpn[n + 2] = '\0'; //接入指定的运算符
}
//中缀表达式求值的主体部分
float evaluate(char *S, char *& rpn)//*&意为数组引用
{
Stack opnd;//运算数栈
Stack optr;//运算值栈
optr.push('\0');//头哨兵,和字符串结尾的'\0'匹配
int i = 0;
while (!optr.isEmpty())
{
if (isdigit(*S))//当前字符为操作数,isdigit判断是否为10进制数
{
readNumber(S, opnd);//读入数字
append(rpn, opnd.top());
}
else switch (orderBetween(optr.top(), *S))//当前字符为运算符
{
case '<': {
optr.push(*S);
S++;
break;
}
case '=': {
optr.pop();
S++;
break;
}
case '>': {
char op = optr.pop();
append(rpn, op);
if (op == '!') {
float temp = calcu(opnd.top(), op);//一元运算的情况
opnd.pop();
opnd.push(temp);
}
else {
float pOpnd2 = opnd.top();
opnd.pop();
float pOpnd1 = opnd.top();
opnd.pop();
opnd.push(calcu(pOpnd1, op, pOpnd2));//二元运算的情况
}
break;
}
}
}
return opnd.top();
}
int main()
{
Stack s;
s.push(1);
s.push(2);
s.push(3);
s.push(4);
s.show();
cout << s.isEmpty() << endl;
cout << s.top() << endl;
cout << s.pop() << endl;
s.show();
cout << s.top() << endl;
cout << s.pop() << endl;
s.show();
cout << s.top() << endl;
cout << s.pop() << endl;
s.show();
cout << s.top() << endl;
cout << s.pop() << endl;
cout << s.isEmpty() << endl;
s.show();
cout << endl;
Stack c;
convert(c, 2013, 2);
while (!c.isEmpty())cout << c.pop();
cout << endl;
char a[] = "adwasfweef";
cout << paren(a);
char b[] = "(!c.isEmpty())cout< si;
for (int i = 5; i > 0; i--) si.push(i);
int arri[] = { 4, 5, 3, 2, 1 };
cout << permutation(si, arri, 5);
Stack s2;
for (int i = 5; i > 0; i--) s2.push(i);
int arr2[] = { 1, 5, 3, 2, 4 };
cout << permutation(s2, arr2, 5) << endl;
char *r = (char*)malloc(sizeof(char) * 1);
r[0] = '\0';
char exp1[] = "2+2";
char exp2[] = "20*(4.5-3)";
char exp3[] = "5!-6.7";
char exp4[] = "(1+2^3!-4)*(5!-(6-(7-(89-0!))))";
cout << evaluate(exp1, r) << endl;
cout << r << endl;
r[0] = '\0';
cout << evaluate(exp2, r) << endl;
cout << r << endl;
r[0] = '\0';
cout << evaluate(exp3, r) << endl;
cout << r << endl;
r[0] = '\0';
cout << evaluate(exp4, r) << endl;
cout << r << endl;
return 0;
}