1. 栈类的声明与定义
实现表达式的转换,转换后可以实现计算,此处为实现计算.
如:
1+2, will be changed to 12+, 3*5-1 will be 35*1-, 1+2-3*2-1 will be 12+32*-1-
具体的入栈和出栈过程以及操作符判断参考上一篇”中缀表达式转换为后缀表达式”
即只要有 “数字-数字-操作符”的形式就进行计算,同时将新的数入栈,最终即可得到结果
struct Node {
char entry;
Node *next;
Node() {
next = NULL;
}
Node(char data, Node *add_on = NULL) {
entry = data;
next = add_on;
}
};
class Stack {
public:
Stack();
bool empty() const;
void push(const char item);
void pop();
char top() const;
int size() const;
protected:
Node *top_node;
int count;
};
在这里栈主要用来存储表达式中的操作符
下面是栈的定义
Stack::Stack() {
count = 0;
top_node = NULL;
}
bool Stack::empty() const {
return count == 0;
}
void Stack::push(const char item) {
Node* temp = new Node(item, top_node);
top_node = temp;
count++;
}
void Stack::pop() {
Node* temp = top_node;
top_node = top_node->next;
delete temp;
count--;
}
char Stack::top() const {
return top_node->entry;
}
int Stack::size() const {
return count;
}
2. 表达式的转换, 中缀形式转换为后缀形式
重点和难点在与()处理
下面是实现的代码:
bool isOperator(char ch) {
if (ch == '+'||ch == '-'||ch == '('||ch == ')'||ch == '*'||ch == '/')
return true;
else
return false;
}
// cur大于pre为true, cur小于或者是等pre为false
// bool isHigherPriority(char cur, char pre) {
if (cur == '(' || pre == '(') return true;
else if ((cur == '*' || cur == '/')
&&(pre == '+'||pre == '-'))
return true;
else
return false;
}
bool isNum(char ch) {
if (ch >= '0' && ch <= '9') return true;
else return false;
}
// 重点是括号的处理,左括号直接入栈,知道遇到有括号在出栈
string transfer(string str) {
if (str == "") return "";
int l = str.size();
char* result = new char[l + 1];
Stack stack; // 存放操作符
int j = 0;
for (int i = 0; i < l; ++i) {
if (isNum(str[i])) {
result[j++] = str[i];
}
if (isOperator(str[i])) {
// 最开始为空的情况
if (stack.empty()) {
if (str[i] == ')')
return "";
else
stack.push(str[i]);
// 栈不为空时首先考虑是否遇到括号的情况,遇到有括号首先要判断栈中是否有左括号
} else if (str[i] == ')') {
bool leftBrace = false;
while (!stack.empty()) {
if (stack.top() == '(') {
stack.pop();
leftBrace = true;
break;
}
result[j++] = stack.top();
stack.pop();
}
if (!leftBrace) return "";
} else {
if (isHigherPriority(str[i], stack.top())) {
stack.push(str[i]);
} else {
while (!stack.empty()) {
if (isHigherPriority(str[i], stack.top())) {
break;
}
result[j++] = stack.top();
stack.pop();
}
stack.push(str[i]);
}
}
}
}
while (!stack.empty()) {
result[j++] = stack.top();
stack.pop();
}
// 字符串以'\0'结束
result[j] = '\0';
string conversion(result);
delete []result;
return conversion;
}
(1)注意:char *result = new char[len + 1]而不是new char[len], 因为最后字符串应该以’\0’结束, 若只new了len的内存,则会因为越界而出现内存泄漏
(2)判断操作符的时候简单说有三种情况,首先判断括号的情况,然后是一种情况是优先级比原本的要高(不包括相等的情况),此种情况直接将新的操作符进栈; 另外一种情况是新的操作符与原来相等或者是小的情况,进行同一处理,即原来的操作符出栈,并且输出,同时将新的操作符与此时的stack.top()的优先级进行比较,知道新的优先级比较高或者是栈为空的时候,将新的操作符入栈
(3)测试样例:
input:
This line is pointless, please ignore 9413
(2+1)/(2-1)*(2+2)
output:
i s l i n e i s p o i n t l e s s , p l e a s e i g n o r e 9 4 1 3
0
21+21-/22+*
以下是main函数部分:
int main() {
string str;
string d;
Stack s;
getline(cin, d);
int len = d.length();
for (int i = len - 1; i > 1; i--) {
s.push(d[i]);
}
while (!s.empty()) {
cout << s.top() << " ";
s.pop();
}
cout << endl;
cout << s.size() << endl;
getline(cin, str);
MidToLast mtl;
string strtemp = mtl.transfer(str);
cout << strtemp << endl;
return 0;
}