【C++数据结构实验】基于双端队列的头插、头删操作,完成栈的应用:逆波兰表达式求值,测试和调试程序。

基于双端队列的头插、头删操作,完成栈的应用:逆波兰表达式求值,测试和调试程序。
此实验主要是编写栈的应用calc.cpp:只使用头删和头插或只使用尾删和尾插完成逆波兰式的计算。双端队列相关内容请查看:双端队列

将中缀表达式翻译成后缀表达式(逆波兰表达式)时,可以去掉中缀表达式中出现的括号,简化表达式。如中缀表达式“(2 + 3) * 6”被转成后缀表达式“2 3 + 6 *”后,可以借助于栈对表达式求值,完成运算。

规则大致如下:

  • 遇到操作数,则入栈;
  • 遇到二元运算符,则连续从栈中弹出两个操作数,先弹出的做第二操作数,后弹出的做第一操作数,与该二元运算符作用后,将得到的结果再存入栈中;
  • 遇到一元运算符,则从栈中弹出一个操作数,与该一元运算符作用后,将得到的结果再存入栈中;

按照上面的规则,扫描后缀表达式(由键盘读到):2、3 是操作数,依次入栈;之后碰到加号“+”这个二元运算符,则3、2 依次出栈,2 为第一操作数,3 为第二操作数,执行加法,和为5,入栈;加号后面的6 是操作数入栈;之后的乘号“*”是二元运算符,则6、5 依次出栈,5 为第一操作数,6 为第二操作数,执行乘法,积为30,入栈;之后可以使用打印栈顶元素的操作(该次实验中使用命令“p”),将最后结果在屏幕上输出。

程序要求从键盘接收字符串,然后按照上面的思想,求解该字符串对应的逆波兰式表达式的值。参与计算的操作数是实数或整数,可以是负数(将负号“n”当做是一元运算符),为了便于解析,从键盘输入的内容被分成很多行,
如上面的例子在

本次实验中输入是:

2
3
+
6
*
P
输出结果是:
30

程序应该提供下面的合法命令:
+:弹出栈中两项元素,相加后和入栈。
-:弹出栈中两项元素,相减后差入栈。
*:弹出栈中两项元素,相乘后积入栈。
/:弹出栈中两项元素,相除后商入栈,注意如果除数为0,系统应该通过下面的方式输出信息:
cout << “Divide by zero\n”;
同时,栈恢复到该操作之前,程序不退出。
n:表示相反数操作,弹出一项栈中元素,乘以(-1)后入栈。
d:表示复制栈顶元素操作,取出栈中一项元素,然后两次入栈。
r:表示栈顶元素与次栈顶元素交换次序,即连续出栈两项元素,再交错入栈,先出栈元素先入栈,后出栈元素后
入栈。
p:打印栈顶元素后换行,但栈中内容不变。
a:打印栈中所有元素,各元素输出时不换行,最先输出栈顶元素,最后输出栈底元素,全部输完后换一行,任务
完成后,栈中数据要维护成与操作前一致的内容。
c:清空栈中所有元素。
q:退出逆波兰式求值的程序。
注意,如果用户输入了错误的命令,则程序通过下面的方式输出信息:
cout << “Bad input\n”;
栈不发生任何变化,程序不退出。
如果程序扫描碰到运算符,而栈中不存在足够的操作数弹出时,程序通过下面的方式输出信息:
cout << “Not enough operands\n”;
栈恢复到该操作之前,程序不退出。

实现完后,可以执行类似下面的程序,检验自己的双端队列是否满足上面的要求,运行正常。
本实验输出结果如下:

2
3
4
+
*
p
14 <------这一行是程序输出的结果
+ 
Not enough operands <------这一行是程序输出的提示信息
d
+
p
28 <------这一行是程序输出的结果
2
-
p
26 <------行是程序输出的结果
q

关于双端队列内容请查看:双端队列
具体代码如下:

#include"Dlist.h"
#include<iostream>
#include<stdlib.h>
#include<string>
#include<math.h>
#include<exception>
#define max_num 10
using namespace std;
int operands[2];
template <typename T>
int* opEnough(Dlist<T> &list) {
	int *first, *second;
	first = list.removeFront();
	second = list.removeFront();
	if (first == NULL || second == NULL) {
		cout << "Not enough operands\n";
		if (first != NULL)
			list.insertFront(first);
		return 0;
	}
	else {
		operands[0] = *second;
		operands[1] = *first;
		return operands;
	}
}

int main() {
	Dlist<int> data;
	Dlist<char> chars;
	string ch;
	cin >> ch;
	while (ch.compare("q")) {
		if (ch.size() > 1) {
			int tem = 0;
			bool flag = true;
			for (int i = 0; i < ch.size(); i++) {
				if (ch[i] >= 48 && ch[i] <= 57) {
					tem += (ch[i] - 48) * pow(10, (ch.size() - i - 1));
				}else {
					cout << "Bad input\n";
					flag = false;
					break;
				}
			}
			if (flag) {
				data.insertFront(&tem);
			}
			cin >> ch;
		}
		else {
			if (ch[0] >= 48 && ch[0] <= 57) {
				int *da = new int(ch[0] - 48);
				data.insertFront(da);
				cin >> ch;
			}
			else if (ch[0] == '+') {
				int *oprand = opEnough(data);
				if (oprand != NULL) {
					int *calculate = new int(oprand[0] + oprand[1]);
					data.insertFront(calculate);
				}
				cin >> ch;
			}
			else if (ch[0] == '-') {
				int *oprand = opEnough(data);
				if (oprand != NULL) {
					int *calculate = new int(oprand[0] - oprand[1]);
					data.insertFront(calculate);
				}
			}
			else if (ch[0] == '*') {
				int *oprand = opEnough(data);
				if (oprand != NULL) {
					int *calculate = new int(oprand[0] * oprand[1]);
					data.insertFront(calculate);
				}
			}
			else if (ch[0] == '/') {
				int *oprand = opEnough(data);
				if (oprand != NULL) {
					if (oprand[1] != 0) {
						int *calculate = new int(oprand[0] / oprand[1]);
						data.insertFront(calculate);
					}
					else {
						cout << "Divide by zero\n";
					}

				}
			}
			else if (ch[0] == 'n') {
				int *oprand = data.removeFront();
				if (oprand != NULL) {
					int *calculate = new int((-1)*(*oprand));
					data.insertFront(calculate);
				}
				else {
					cout << "Not enough operands\n";
				}
			}
			else if (ch[0] == 'd') {
				int *oprand = data.removeFront();
				if (oprand != NULL) {
					data.insertFront(oprand);
					data.insertFront(oprand);
				}
				else {
					cout << "Not enough operands\n";
				}
			}
			else if (ch[0] == 'p') {
				int *op;
				if ((op = data.removeFront()) != NULL) {
					cout << *op << endl;
					data.insertFront(op);
				}

				else
					cout << "Not enough operands\n";
			}
			else if (ch[0] == 'r') {
				int *first, *second;
				first = data.removeFront();
				second = data.removeFront();
				if (first != NULL && second != NULL) {
					data.insertFront(first);
					data.insertFront(second);
				}
				else {
					cout << "Not enough operands\n";
				}
			}
			else if (ch[0] == 'a') {
				if (!data.isEmpty()) {
					int *temp[max_num], i = 0;
					while (!data.isEmpty()) {
						temp[i] = data.removeFront();
						cout << *temp[i] << "\t";
						i++;
					}
					cout << endl;
					for (int j = i-1; j >= 0; j--) {
						data.insertFront(temp[j]);
					}
				}
				else {
					cout << "There have no oprands in data stack!";
				}
			}
			else if (ch[0] == 'c') {
				while (!data.isEmpty()) {
					data.removeFront();
				}
			}
			else {
			cout<< "Bad input\n";
			}
		}
		cin >> ch;
	}		
	system("pause");
}

运行结果

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

輕塵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值