实验报告
实验五:实现用波兰表达式(先序)和逆波兰表达式(后序)求算术表达式的值
要求:仅用一个栈实现(并且用原生单链表实现)
测试用例:4+2*3-10/5
交作业时间:5月14日
思路
两个步骤:
- 将给定的表达式转换为波兰表达式/逆波兰表达式
- 对转换后的式子进行计算
学习遍历二叉树,利用前序/中序/后序表达式的时候,经常有一个问题就是:
- 给出中缀表达式,【写出&&编程出】后序(逆波兰)表达式


上面的是课堂上在纸上的书写,那么如何将其用编程语言实现呢?思路应该是这样的:
- 遍历表达式:对遍历的元素进行判断
- 是运算符?操作数?还是括号呢?对其相应的判断
- 操作数
- 运算符:+-*/
- 括号
[x] 个位数/双位数……的字符处理
[x] 给出中缀表达式,【写出&&编程出】前序(波兰)表达式
如果写出了逆波兰表达式,转换为波兰表达式只需要将(变为),同时遍历从后往前遍历即可
最后的结果逆置
/**
- 波兰表达式/逆波兰表达式求解运算表达式
- */
/**
- 单链表的存储结构 / typedef struct LNode { string data; //数据域 struct LNode next; //指针域 }Lnode, *LinkList; //LinkList为指向结构体LNode的指针类型
/ 初始化链表 / void InitList(LinkList &L) { L = new LNode; L->next = NULL; }
/ 打印 / void TraverseList(LinkList & L){ LNode *p = new LNode; p = L->next; // cout << “此中缀表达式链表打印的结果为:”; while (p != NULL) { cout << p->data; p = p->next; } cout << “\n”; }
/ 逆置 /
void ReverseList(LinkList &L) {
LNode p = L->next;
L->next = NULL;
while(p)
{
LNode q = p->next;
p->next = L->next;
L->next = p;
p = q;
}
}
/**
- 初始化用户输入的链表
*/
void Center(LinkList &L,string s) {
InitList(L);
LinkList p = L;
string temp = “”;
for (int i = 0; i < s.length();i++){
}// 处理双位数字情况if (isdigit(s[i])) {// 该字符为数字temp = temp + s[i];if (!isdigit(s[i+1])) {// 下一个不是数字,而是字符,将temp后插LinkList node = new LNode;node->data = temp;node->next = NULL;p->next = node;p = node;// 将temp重置temp = "";continue;}continue;}// 后插到L尾巴上LinkList node = new LNode;node->data = s[i];node->next = NULL;p->next = node;p = node;
}
/**
- 将表达式转换为波兰表达式/逆波兰表达式
- 第二个参数对逆波兰而言是左括号,第三个参数对逆波兰而言是右括号
对波兰而言反过来 */ void Transition(LinkList &L, string l, string r){ // 定义一个栈用来处理 stack
stack; LinkList p = L->next; LinkList result = new LNode; InitList(result); LinkList result_a = result; while(p != NULL) {
if (p->data == l) {stack.push(p->data);} else if(p->data == r) {while(stack.top() != l){LinkList temp = new LNode;temp->data = stack.top();temp->next = NULL;result_a->next = temp;result_a = temp;stack.pop();}if (stack.top() == l){stack.pop();}} else if(p->data == "+" || p->data == "-") {if (stack.size() != 0) {if (stack.top() == "*" || stack.top() == "/"){for (int i = 0; i < stack.size();i++) {if (stack.top() == l) {break;}LinkList temp = new LNode;temp->data = stack.top();temp->next = NULL;result_a->next = temp;result_a = temp;stack.pop();}}}stack.push(p->data);} else if(p->data == "*" || p->data == "/") {stack.push(p->data);} else {LinkList temp = new LNode;temp->data = p->data;temp->next = NULL;result_a->next = temp;result_a = temp;}p = p->next;
} // TraverseList(result); for (int i = 0; i < stack.size();i++) {
LinkList temp = new LNode;temp->data = stack.top();temp->next = NULL;result_a->next = temp;result_a = temp;stack.pop();
} // 上一个操作总是不能清空栈的最后一个元素 LinkList temp = new LNode; temp->data = stack.top(); temp->next = NULL; result_a->next = temp; result_a = temp; stack.pop();
L = result; }
/**
- 计算 */
void EvaulTree(LinkList &L) {
// 定义一个栈用来处理
stack
void EvaulTree_polish(LinkList &L) {
// 定义一个栈用来处理
stack
int main () { cout << “——————————————————“<<”\n”; string s; cout << “请输入运算表达式:”<<”\n”; cin >> s; LinkList test_reversepolish = new LNode; InitList(test_reversepolish); LinkList test_polish = new LNode; InitList(test_polish);
Center(test_reversepolish, s);Center(test_polish, s);cout << "------------------------------------"<<"\n";// 波兰表达式ReverseList(test_polish);Transition(test_polish, ")", "(");cout << "波兰表达式为:";ReverseList(test_polish);TraverseList(test_polish);cout << "波兰表达式计算结果为:";ReverseList(test_polish);EvaulTree_polish(test_polish);cout << "\n"<<"------------------------------------"<<"\n";// 逆波兰表达式Transition(test_reversepolish, "(", ")");cout << "逆波兰表达式为:";TraverseList(test_reversepolish);cout << "逆波兰表达式计算结果为:";EvaulTree(test_reversepolish);cout << "\n"<<"------------------------------------"<<"\n";
} ```

```cpp