C++ 直接计算多项式的值

在数据结构上遇到了这个题...但是觉得麻烦没写,想想还是要学的,特此记录下来。

以下是代码:

#include <Windows.h>
#include <iostream>
#include <vector>
#include <String>
#include <stack>
#include <cstdlib>
using namespace std;

/*
第一步,转换成后缀表达式
第二部,利用后缀表达式求解

如何转化为后缀表达式:

顺序扫描中序表达式
a) 是数字, 直接输出
b) 是运算符
i : “(” 直接入栈
ii : “)” 将符号栈中的元素依次出栈并输出, 直到 “(“, “(“只出栈, 不输出
iii: 其他符号, 将符号栈中的元素依次出栈并输出, 直到 遇到比当前符号优先级更低的符号或者”(“。 将当前符号入栈。
扫描完后, 将栈中剩余符号依次输出

*/
int main()
{
	string str_in;
	
	vector<string> houzhuibiaodashi;			//后缀表达式
	stack<char> CStack;
	string temp;			//临时
	stack <float> NStack;
	while (1)
	{
		houzhuibiaodashi.clear();			//后缀表达式向量清空
		while (!CStack.empty())				//运算符栈清空
		{
			CStack.pop();
		}
		temp = "";							//表达式清空
		while (!NStack.empty())				//数值栈清空
		{
			NStack.pop();
		}


		cout << "请输入多项式:";
		cin >> str_in;
		for (int i = 0; i < str_in.length(); i++)
		{

			if (str_in[i] >= '0' && str_in[i] <= '9')			//处理数字
			{
				temp = str_in[i];
				while (str_in[i + 1] >= '0' && str_in[i + 1] <= '9' && i<str_in.length())
				{
					temp += str_in[++i];
				}

				houzhuibiaodashi.push_back(temp);				//数字推入后缀表达式

			}

			else if ((str_in[i] == '-' && i == 0) || (str_in[i] == '-'&& str_in[i - 1] == '('))		//处理负数,不能处理-(3+2)这种
			{
				temp = "";

				temp = str_in[i++];
				while (str_in[i] >= '0' && str_in[i] <= '9' && i<str_in.length())
				{
					temp += str_in[i];
					i++;
				}

				houzhuibiaodashi.push_back(temp);				//数字推入后缀表达式
			}

			if (str_in[i] == '(')		//小括号直接入运算符栈
			{
				CStack.push(str_in[i]);				//运算符入栈
			}

			else if (str_in[i] == ')')
			{
				temp = "";
				while (!CStack.empty() && CStack.top() != '(')
				{
					temp = CStack.top();
					houzhuibiaodashi.push_back(temp);
					CStack.pop();
				}
				CStack.pop();			//(出栈
			}

			else if (str_in[i] == '+' || str_in[i] == '-' || str_in[i] == '*' || str_in[i] == '/')
			{
				temp = "";
				if (str_in[i] == '+' || str_in[i] == '-')
				{
					while (!CStack.empty() && (CStack.top() == '+' || CStack.top() == '-' || CStack.top() == '*' || CStack.top() == '/'))
					{
						temp = CStack.top();
						CStack.pop();
						houzhuibiaodashi.push_back(temp);
					}
					CStack.push(str_in[i]);
				}
				else if (str_in[i] == '*' || str_in[i] == '/')
				{
					while (!CStack.empty() && (CStack.top() == '*' || CStack.top() == '/'))
					{
						temp = CStack.top();
						CStack.pop();
						houzhuibiaodashi.push_back(temp);
					}
					CStack.push(str_in[i]);
				}

			}




		}


		while (!CStack.empty())
		{
			temp = CStack.top();
			CStack.pop();
			houzhuibiaodashi.push_back(temp);
		}


		/*完成后缀表达式,下边是李用后缀表达式求值*/

		

		int i = 0;
		float num1, num2;
		while (!houzhuibiaodashi.empty() && i<houzhuibiaodashi.size())
		{
			if (houzhuibiaodashi[i] == "+")
			{
				num1 = NStack.top();
				NStack.pop();
				num2 = NStack.top();
				NStack.pop();
				NStack.push(num1 + num2);
			}
			else if (houzhuibiaodashi[i] == "-")
			{
				if (i == 0)				//检测到负号时可能是负数
				{
					char * data = new char[houzhuibiaodashi.size()];
					for (int t = 1; t < houzhuibiaodashi[i].size(); t++)
					{
						data[t] = houzhuibiaodashi[i][t];
					}

					NStack.push(0 - atoi(data));
				}
				else
				{
					num1 = NStack.top();
					NStack.pop();
					num2 = NStack.top();
					NStack.pop();
					NStack.push(num2 - num1);
				}
			}
			else if (houzhuibiaodashi[i] == "*")
			{
				num1 = NStack.top();
				NStack.pop();
				num2 = NStack.top();
				NStack.pop();
				NStack.push(num1 * num2);
			}
			else if (houzhuibiaodashi[i] == "/")
			{
				num1 = NStack.top();
				NStack.pop();
				num2 = NStack.top();
				NStack.pop();
				NStack.push(num1 / num2);
			}
			else
			{
				char * data = new char[houzhuibiaodashi.size()];
				for (int t = 0; t < houzhuibiaodashi[i].size(); t++)
				{
					data[t] = houzhuibiaodashi[i][t];
				}

				NStack.push(atoi(data));
			}

			i++;
		}


		cout <<  "等式的值为" <<NStack.top() << endl;

	}
	

	system("pause");
}

更新后的代码:

#include <Windows.h>
#include <iostream>
#include <vector>
#include <String>
#include <stack>
#include <cstdlib>
using namespace std;
/*
第一步,转换成后缀表达式
第二部,利用后缀表达式求解
如何转化为后缀表达式:
顺序扫描中序表达式
a) 是数字, 直接输出
b) 是运算符
i : “(” 直接入栈
ii : “)” 将符号栈中的元素依次出栈并输出, 直到 “(“, “(“只出栈, 不输出
iii: 其他符号, 将符号栈中的元素依次出栈并输出, 直到 遇到比当前符号优先级更低的符号或者”(“。 将当前符号入栈。
扫描完后, 将栈中剩余符号依次输出
*/
int main()
{
	string str_in;
	vector<string> houzhuibiaodashi;			//后缀表达式
	stack<char> CStack;
	string temp;			//临时
	stack <float> NStack;
	while (1)
	{
		houzhuibiaodashi.clear();			//后缀表达式向量清空
		while (!CStack.empty())				//运算符栈清空
		{
			CStack.pop();
		}
		temp = "";							//表达式清空
		while (!NStack.empty())				//数值栈清空
		{
			NStack.pop();
		}
		cout << "请输入多项式:";
		cin >> str_in;
		for (int i = 0; i < str_in.length(); i++)
		{
			if (str_in[i] == '(')		//小括号直接入运算符栈
			{
				CStack.push(str_in[i]);				//运算符入栈
			}
			else if (str_in[i] >= '0' && str_in[i] <= '9')			//处理数字
			{
				temp = str_in[i];
				while (str_in[i + 1] >= '0' && str_in[i + 1] <= '9' && i<str_in.length())
				{
					temp += str_in[++i];
				}
				houzhuibiaodashi.push_back(temp);				//数字推入后缀表达式
			}

			else if (
				(str_in[i] == '-'
				&&( i > 0 && !(str_in[i-1] >= '0' && str_in[i-1] <= '9'&& str_in[i + 1] >= '0' && str_in[i + 1] <= '9'))	//排除num-num型减法
				&&( i > 0 && !(str_in[i - 1] == ')' && str_in[i + 1] >= '0' && str_in[i + 1] <= '9'))	//排除()-num型减法
				&&( i > 0 && !(str_in[i + 1] == ')' && str_in[i - 1] >= '0' && str_in[i - 1] <= '9')))	//排除num-()型减法
				|| (str_in[i] == '-'&& i == 0)										//加入负数在多项式开头的情况
				)//处理负数,不能处理-(3+2)这种
			{
				temp = "";

				temp = str_in[i++];
				while (str_in[i] >= '0' && str_in[i] <= '9' && i<str_in.length())
				{
					temp += str_in[i];
					i++;
				}

				houzhuibiaodashi.push_back(temp);				//数字推入后缀表达式

				i--;			//防止指针过度移动。上一个版本的下一个分支直接用了if,不是else if , 虽然能解决这个问题但是不严谨

			}
			else if (str_in[i] == '-'&& str_in[i + 1] == '(' && (i == 0))		//处理-(3+2)在开头的多项式
			{
				

				houzhuibiaodashi.push_back("-1");			//改成-1 * (5+2) 进行计算,先压入-1,之后按照*规则处理


				while (!CStack.empty() && (CStack.top() == '*' || CStack.top() == '/'))
				{
					temp = "";
					temp = CStack.top();
					CStack.pop();
					houzhuibiaodashi.push_back(temp);
				}
				CStack.push('*');
			}

			

			else if (str_in[i] == ')')
			{
				temp = "";
				while (!CStack.empty() && CStack.top() != '(')
				{
					temp = "";
					temp = CStack.top();
					houzhuibiaodashi.push_back(temp);
					CStack.pop();
				}
				CStack.pop();			//(出栈
			}

			else if (str_in[i] == '+' || str_in[i] == '-' || str_in[i] == '*' || str_in[i] == '/')
			{
				temp = "";
				if (str_in[i] == '+' || str_in[i] == '-')
				{
					while (!CStack.empty() && (CStack.top() == '+' || CStack.top() == '-' || CStack.top() == '*' || CStack.top() == '/'))
					{
						temp = "";
						temp = CStack.top();
						CStack.pop();
						houzhuibiaodashi.push_back(temp);
					}
					CStack.push(str_in[i]);
				}
				else if (str_in[i] == '*' || str_in[i] == '/')
				{
					while (!CStack.empty() && (CStack.top() == '*' || CStack.top() == '/'))
					{
						temp = "";
						temp = CStack.top();
						CStack.pop();
						houzhuibiaodashi.push_back(temp);
					}
					CStack.push(str_in[i]);
				}

			}




		}


		while (!CStack.empty())
		{
			temp = CStack.top();
			CStack.pop();
			houzhuibiaodashi.push_back(temp);
		}


		/*完成后缀表达式,下边是李用后缀表达式求值*/

		

		int i = 0;
		float num1, num2;
		while (!houzhuibiaodashi.empty() && i<houzhuibiaodashi.size())
		{
			if (houzhuibiaodashi[i] == "+")
			{
				num1 = NStack.top();
				NStack.pop();
				num2 = NStack.top();
				NStack.pop();
				NStack.push(num1 + num2);
			}
			else if (houzhuibiaodashi[i] == "-")
			{
				if (i == 0)				//检测到负号时可能是负数
				{
					char * data = new char[houzhuibiaodashi.size()];
					for (int t = 1; t < houzhuibiaodashi[i].size(); t++)
					{
						data[t] = houzhuibiaodashi[i][t];
					}

					NStack.push(0 - atoi(data));
				}
				else
				{
					num1 = NStack.top();
					NStack.pop();
					num2 = NStack.top();
					NStack.pop();
					NStack.push(num2 - num1);
				}
			}
			else if (houzhuibiaodashi[i] == "*")
			{
				num1 = NStack.top();
				NStack.pop();
				num2 = NStack.top();
				NStack.pop();
				NStack.push(num1 * num2);
			}
			else if (houzhuibiaodashi[i] == "/")
			{
				num1 = NStack.top();
				NStack.pop();
				num2 = NStack.top();
				NStack.pop();
				NStack.push(num2 / num1);
			}
			else
			{
				char * data = new char[houzhuibiaodashi.size()];
				for (int t = 0; t < houzhuibiaodashi[i].size(); t++)
				{
					data[t] = houzhuibiaodashi[i][t];
				}

				NStack.push(atoi(data));
			}

			i++;
		}
		cout <<  "等式的值为" <<NStack.top() << endl;
	}
	system("pause");
}

代码更新说明:

上一个版本(就是划线的)简直bug百出,不能计算-(5+2)这种,除号和减号的运算规则也有错误。本次更新内容:

进一步优化判断条件;

修复了一些操作符bug;

完美支持加减乘除操作。

可自行加入乘方或者其他运算操作


第一步是将中缀表达式转换成后缀表达式。这一步很麻烦,用到的转换规则不是很好理解:

  1. 建立符号栈
  2. 顺序扫描中序表达式 
    a) 是数字, 直接输出 (即压入后缀表达式)
    b) 是运算符 
    i : “(” 直接入栈 (压入运算符栈CStack)
    ii : “)” 将符号栈中的元素依次出栈并输出(压入后缀表达式), 直到 “(“, “(“只出栈, 不输出 
    iii: 其他符号, 将符号栈中的元素依次出栈并输出, 直到 遇到比当前符号优先级更低的符号或者”(“。 将当前符号入栈。
  3. 扫描完后, 将栈中剩余符号依次输出

iii解释一下:举个例子,如果当前运算符栈中的内容是+,而当前的运算符是-,因为+不符合“比当前符号优先级低”的条件,所以需要将+弹栈并压入后缀表达式。之后栈为空,可以将-压入。也就是说,如果当前操作符是+、-,则一直弹栈,直到栈为空或者遇到“(”。如果当前操作符是*、/,则一直弹栈直到遇到+-或者“(”。


第二步是根据后缀表达式求值。很简单,从头读取后缀表达式,数字则压入数字栈,遇到操作符则从数字栈弹出相应数量数字进行运算(注意减法的减数和被减数不能搞错),运算结果压入数字栈。 最终,数字栈将只剩下一个数字,即为多项式运算结果。


附运行截图:



欢迎大家批评指正。

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 一元多项式相加是在数据结构中比较基础的一部分,也是我们在数学中常见的操作。在计算机中,我们通常将多项式看作一个数组(或链表)的形式,其中数组下标表示该项的指数,数组中存放的表示该项的系数。两个多项式相加就是将两个数组对应项的系数相加得到一个新的数组。 具体步骤如下: 1. 定义一个数组(或链表)来存放结果多项式,长度为两个原始多项式中指数最大的项数加1。 2. 遍历两个原始多项式数组(或链表),将对应项的系数相加,赋给结果数组的对应项。 3. 返回结果数组(或链表)。 当然,在实现过程中还需注意以下几点: 1. 若某个多项式存在系数为0的项,则计算时应该忽略该项,即不将其对应项相加到结果数组中。 2. 当两个原始多项式不等长时,需在系数较短的数组中补0,使其长度与较长数组相等。 3. 若相加的结果系数为0,则结果多项式也应该忽略该项,即不将其加入到结果数组中。 总之,一元多项式的加法并不复杂,只需遍历数组,将对应项的系数相加即可。需要注意的是,在实现过程中考虑越界以及忽略系数为0的项这些问题。 ### 回答2: 一元多项式的运算主要包括加、减、乘和求导等,其中加法是最基本的一种运算。在数据结构中,我们可以用链表来表示一元多项式,在链表中每个结点表示一个单项式,包含系数和指数两个数据项。对于两个一元多项式的相加,则需要对它们的各个单项式进行合并,合并的方法是按照单项式的指数大小进行排序,然后分别将同一指数的单项式的系数相加得到新的单项式,最终得到一个新的一元多项式。 具体实现上,可以通过定义一个新的链表来存储结果,然后使用两个指针分别遍历两个原始的链表,根据两个指针所对应的单项式的指数关系来决定需要将哪个单项式加入到结果链表中。需要注意的是,在遍历的过程中,如果出现同一指数的单项式,则需要将它们的系数相加得到新的单项式,否则直接将单项式插入结果链表中即可。 在实现过程中,可以使用一个小技巧来简化代码,即使用一个哑结点作为结果链表的头结点,这样就可以省略对链表进行空判断的代码。同时,为了提高运算效率,可以对原始链表进行排序,使得它们的单项式按照指数大小排列,从而便于遍历和合并。 综上所述,一元多项式的相加需要按照单项式的指数大小进行排序,然后遍历两个原始链表,合并同一指数的单项式并插入结果链表中,最终得到一个新的一元多项式。具体实现需要考虑空链表和排序等细节问题。 ### 回答3: 一元多项式相加是数据结构中的一个重要问题。我们需要定义一个多项式的结构体,同时考虑到指数可能不是连续的整数,我们需要使用链表来保存每一项的系数和指数。具体来说,结构体的定义如下: ```c typedef struct node { int coefficient; // 系数 int exponent; // 指数 struct node* next; // 下一项 } polynomial; ``` 接下来,我们可以先将两个多项式按指数从小到大排序,然后使用“归并”算法将它们相加。具体来说,分别遍历两个多项式的链表,按指数大小比较,将系数较小的项插入结果链表,并且修改指针。最后,如果有多余项,直接将它们接在结果链表的末尾即可。 具体实现如下: ```c polynomial* add(polynomial* p1, polynomial* p2) { polynomial* result = (polynomial*)malloc(sizeof(polynomial)); polynomial* cur = result; while (p1 && p2) { if (p1->exponent < p2->exponent) { cur->next = p1; p1 = p1->next; } else if (p1->exponent > p2->exponent) { cur->next = p2; p2 = p2->next; } else { cur->next = p1; cur->next->coefficient += p2->coefficient; p1 = p1->next; p2 = p2->next; } cur = cur->next; } cur->next = p1 ? p1 : p2; return result->next; } ``` 最后,记得要释放内存。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值