MFC实现一元稀疏多项式运算器
MFC实现一元稀疏多项式运算器
首先看看效果图,下面一一介绍各个按钮的实现

基本要求
- 输入并建立两个多项式
- 多项式a与b相加,建立和多项式c
- 多项式a与b相减,建立差多项式d
- 输出多项式a, b, c, d。输出格式:比如多项式a为:A(x)=c1xe1+ c2xe2+…+ cmxem,其中,ci和ei分别为第i项的系数和指数,且各项按指数的升幂排列,即0≤e1<e2<…<em
功能已加强,这里我实现了输入可以不需要保持递增,输出依然递增有序,即加入了查找位置的函数。
首先看一下我界面,较为粗糙,实现计算器界面(个人感觉手动输入更为方便,但实习的拓展要求是计算器的仿真界面Orz)
这个可以自己添加一个头文件,用于多项式的类定义(下面的重载>> <<属于多余的,如果单纯C++控制台程序的可以应用,MFC工程可以直接忽略)。
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
bool flag = 0;
struct Term
{
double coef;//系数
int exp;//指数
Term* link;
Term(double c, int e, Term* next = NULL)
{
coef = c; exp = e; link = next;
}
Term*InsertAfter(double c, int e);
friend ostream& operator <<(ostream&, const Term&);
};
class Polynomial//多项式类定义
{
public:
Term * first;
friend ostream&operator<<(ostream&, const Polynomial&);
friend istream&operator>>(istream&, Polynomial&);
friend Polynomial operator+(Polynomial&, Polynomial&);
friend Polynomial operator-(Polynomial&, Polynomial&);
Polynomial() { first = new Term(0, -10000000); }//构造函数,建立空链表
Polynomial(Polynomial&R);//复制构造函数
int maxOrder();//计算最大阶数
Term* find_place(int e);
bool inser_order(double c, int e);
Term*getHead()const { return first; };//取得单链表的头指针
//~Polynomial();
};
Polynomial x, y;
Term* Term::InsertAfter(double c, int e)
{
link = new Term(c, e, link);
return link;
}
ostream& operator<<(ostream& out, const Term&x)
{
if (x.coef == 0.0)return out;
out << x.coef;
switch (x.exp)
{
case 0:break;
case 1:out << "X"; break;
default:out << "X" << x.exp;
break;
}
return out;
}
Polynomial::Polynomial(Polynomial&R)
{
//复制构造函数
first = new Term(0, -1);
Term *destptrr = first, *srcptr = R.getHead()->link;
while (srcptr != NULL)
{
destptrr->InsertAfter(srcptr->coef, srcptr->exp);
srcptr = srcptr->link;
destptrr = destptrr->link;
}
}
int Polynomial::maxOrder()
{
//升序排序计算最大阶数,即为最后一项
Term*current = first;
while (current->link != NULL)
{
current = current->link;
}
return current->exp;
}
//寻找需要插入的位置,由inser_order(double c, int e)调用
Term* Polynomial::find_place(int e)
{
Term* current = first;
while (current->link!=NULL&¤t->link->exp<e)
{
current = current->link;
}
return current;
}
//插入,保持递增单链表
bool Polynomial::inser_order(double c, int e)
{
Term*current = find_place(e);
Term*temp=NULL;
//if (current == NULL) { AfxMessageBox(_T("插入出错!")); return false; }
Term* newnode= new Term(c, e, temp);
if (newnode == NULL) { AfxMessageBox(_T("插入出错!")); return false; }
newnode->link = current->link;
current->link = newnode;
return true;
}
istream& operator>>(istream&in, Polynomial& x)
{
//输入,尾插法建立多项式
Term* rear = x.getHead(); double c; int e;
while (true)
{
cout << "input a term(c,exp)" << endl;
in >> c >> e;
if (e < 0)break;
rear = rear->InsertAfter(c, e);
}
return in;
}
ostream& operator<<(ostream &out, Polynomial&x) {
Term*current = x.getHead()->link;//头指针为空,不输出
cout << "多项式:" << endl;
bool h = true;
while (current != NULL)
{
if (h == false && current->coef > 0)out << "+";
h = false;
out << *current;
current = current->link;
}
out << endl;
return out;
}
Polynomial operator+(Polynomial&A, Polynomial&B)
{
Term*pa, *pb, *pc, *p; double temp;
Polynomial C; pc = C.first;
pa = A.getHead()->link; pb = B.getHead()->link;
while (pa != NULL && pb != NULL)
{
if (pa->exp == pb->exp)
{
temp = pa->coef + pb->coef;
if (fabs(temp) > 0.0001)
pc = pc->InsertAfter(temp, pa->exp);
pa = pa->link; pb = pb->link;
}
else if (pa->exp < pb->exp) {
pc = pc->InsertAfter(pa->coef, pa->exp);
pa = pa->link;
}
else {
pc = pc->InsertAfter(pb->coef, pb->exp);
pb = pb->link;
}
}
if (pa != NULL)p = pa;
else p = pb;
while (p != NULL)
{
pc = pc->InsertAfter(p->coef, p->exp);
p = p->link;
}
return C;
}
Polynomial operator-(Polynomial&A, Polynomial&B)
{
Term*pa, *pb, *pc, *p; double temp;
Polynomial C; pc = C.first;
pa = A.getHead()->link; pb = B.getHead()->link;
while (pa != NULL && pb != NULL)
{
if (pa->exp == pb->exp)
{
temp = pa->coef-pb->coef;
if (fabs(temp) > 0.0001)
pc = pc->InsertAfter(temp, pa->exp);
pa = pa->link; pb = pb->link;
}
else if (pa->exp < pb->exp) {
pc = pc->InsertAfter(pa->coef, pa->exp);
pa = pa->link;
}
else {
pc = pc->InsertAfter(pb->coef*(-1), pb->exp);
pb = pb->link;
}
}
bool flag = true;
if (pa != NULL)p = pa;
else {
p = pb; flag = false;
}
while (p != NULL)
{
if(flag)
pc = pc->InsertAfter(p->coef, p->exp);
else pc = pc->InsertAfter(p->coef*(-1), p->exp);
p = p->link;
}
return C;
}
接下来实现计算器按钮的实现,下面是按钮1的相关代码,其他按钮类似
void CPolynomialDlg::OnBnClickedButton1()
{
UpdateData(true);//写入
CString str;
mEdit.GetWindowTextW(str);//得到编辑框的文字
str = str + _T("1");//CString后面加1
mEdit.SetWindowTextW(str);//编辑框显示更新内容
UpdateData(false);
// TODO: 在此添加控件通知处理程序代码
}
接下来是切换多项式的代码,并且读入一个多项式。处理思路是一次读入系数和指数,采取后插法实现单链表的建立。这里用到CString到double和int的转化,需要注意的是,转double会出现一些后导0,影响美观,需要去掉。我处理的麻烦了点,在大佬那知道了这个函数CString.Delete(CString.Getlength()-1,1),就懒得改了。
void CPolynomialDlg::OnBnClickedButtonnext()
{
CString str;
CString temp, temp1, temp2, temp3;
mEdit.GetWindowTextW(str);
double c = 0; int e = 0;
int j; int i;
//Term* rear;
//if (flag) rear = y.getHead();
// else rear = x.getHead();
for (j = 0; j < str.GetLength(); j++)
{
temp = temp1 = temp2 = temp3 = "";
if (str[j] == ' ')continue;
c = 0; e = 0;
while (str[j] != ' '&&j < str.GetLength()) { temp += str[j]; j++; }
for (i = 0; i < temp.GetLength(); i++)
{
if (temp[i] != '.')temp1 += temp[i];
else break;
}
c += _ttof(temp1);//CString转double
i++;
for (i; i < temp.GetLength(); i++)
temp2 += temp[i];
if(c<0)
c -= _ttof(temp2) / pow(10, temp2.GetLength());
else c += _ttof(temp2) / pow(10, temp2.GetLength());
while(str[j]==' ')j++;
while (str[j] != ' '&&j < str.GetLength()) { temp3 += str[j]; j++; }
e = _ttoi(temp3);
//输入,尾插法建立多项式
// if (flag)
//rear = rear->InsertAfter(c, e);
if (!flag)x.inser_order(c, e);
else y.inser_order(c, e);
// rear->InsertAfter(c, e, y.first);
// else rear = rear->InsertAfter(c, e,x.first);
// else rear->InsertAfter(c, e, x.first);
}
if(!flag)
AfxMessageBox(_T("第一个表达式建立完毕!"));
else AfxMessageBox(_T("第二个表达式建立完毕!"));
mEdit.SetWindowTextW(_T(""));
flag = !flag;
// TODO: 在此添加控件通知处理程序代码
}
关键就是计算函数了,也就是确定按钮,这里用到了下拉框选择操作,用index判断即可。最后作为CString输出也有点格式优化,大家可以看一下。
void CPolynomialDlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
//CDialogEx::OnOK();
CString temp;
int index = combox.GetCurSel();
//combox.GetLBText(index, temp);
CString str;
Polynomial C;
if (index == 0)
C = x + y;
else
C = x-y;
Term*current = C.getHead()->link;//头指针为空,不输出
// cout << "多项式:" << endl;
bool h = true;
while (current != NULL)
{
if (h == false && current->coef > 0)str+='+';
h = false;
//str+= *current;
if (current->coef == 0.0)
continue;
CString strr, str0;
if (current->coef == 1.0&¤t->exp!=0);
else
{
strr.Format(_T("%3f"), current->coef);
int len = strr.GetLength();
int i;
for (i = len - 1; i >= 0; i--)
{
//小数点的处理
if (strr[i] == '0' || strr[i] == '.');
else break;
}
for (int j = 0; j <= i; j++)
str += strr[j];
}
switch (current->exp)//系数输出,0,1单独处理
{
case 0:break;
case 1:str+="X"; break;
default: {str += "X"; strr.Format(_T("%d"), current->exp); str += strr; }
break;
}
current = current->link;
}
n_Edit.SetWindowTextW(str);
}
最后的就是释放空间的按钮,以便实现多次运算,这里偷了个懒,一个小程序,就没有delete了,最好还是顺着单链表delete。
// CDialogEx::OnCancel();
n_Edit.SetWindowTextW(_T(""));//编辑框的清空
x.first = new Term(0, -1);
y.first = new Term(0, -1);
欢迎大家纠正错误,完整代码见GitHub链接,主要是了解MFC框架即可。
MFC实现一元稀疏多项式运算器的更多相关文章
- MFC版链表实现稀疏多项式相加减
链表实现多项式运算(加减)MFC可视化版 题目 设计一个一元稀疏多项式简单计算器. 基本要求 (1)输入并建立两个多项式: (2)多项式a与b相加,建立和多项式c: (3)多项式a与b相减,建立差多项 ...
- C算法与数据结构-线性表的应用,多项式求和---ShinePans
/*---上机作业作业,二项式加法---*/ /*---By 潘尚 ---*/ /*---日期: 2014-5-8 . ---*/ /*---题目:---*/ //如果有两个稀疏多项式A和B,设计算法 ...
- 一道 google曾出过的笔试题:编程实现对数学一元多项式的相加和相乘操作(1)
数学中一元n次多项式可表示成如下的形式: Pn(x)=p0+p1x+p2x^2+…+pnx^n (最多有 n+1 项,n +1 个系数唯一确定她) (1)请设计一套接口用以表示和操 ...
- 数据结构算法C语言实现(六)---2.4一元多项式的表示及相加
一.简述 利用链表表示稀疏多项式,并基于之前的一些操作(编程实现上还是有所不同的)组合新的操作实现一元多项式的表示及相加. 二.ADT 抽象数据类型一元多项式的定义 ADT Polyomail{ 数据 ...
- 算法 《秦九韶算法java实践》
[历史背景] 秦九韶算法是中国南宋时期的数学家秦九韶表述求解一元高次多项式的值的算法--正负开方术.它也能够配合牛顿法用来求解一元高次多项式的根.在西方被称作霍纳算法(Horner algorithm ...
- 算法 《霍纳的方法java实践》
[历史背景] 霍纳的方法是中国南宋时期的数学家秦九韶表述求解一元高次多项式的值的算法--正负开方术. 它也能够配合牛顿法用来求解一元高次多项式的根.在西方被称作霍纳算法(Horner algorith ...
- Single linked List by pointer
其实本应该从一般性的表讲起的,先说顺序表,再说链表 .但顺序表的应用范围不是很广,而且说白了就是数组的高级版本,他的优势仅在于两点:1.逻辑直观,易于理解.2.查找某个元素只需要常数时间--O(1), ...
- SICP读书笔记 2.5
SICP CONCLUSION 让我们举起杯,祝福那些将他们的思想镶嵌在重重括号之间的Lisp程序员 ! 祝我能够突破层层代码,找到住在里计算机的神灵! 目录 1. 构造过程抽象 2. 构造数据抽象 ...
- HEAAN新版学习
本篇文章对最新版的HEAAN库进行研究,老版的介绍见 HEAAN库学习 主要参考:slide-HEAAN.pdf HEAAN介绍 HEAAN是一个支持在加密的复数数组之间进行操作的库,方案的安全性取决 ...
随机推荐
- Linux虚拟文件系统
从文件 I/O 看 Linux 的虚拟文件系统 1 引言 Linux 中允许众多不同的文件系统共存,如 ext2, ext3, vfat 等.通过使用同一套文件 I/O 系统 调用即可对 Linux ...
- mongodb高级聚合查询(转)
在工作中会经常遇到一些mongodb的聚合操作,特此总结下.mongo存储的可以是复杂类型,比如数组.对象等mysql不善于处理的文档型结构,并且聚合的操作也比mysql复杂很多. 注:本文基于 mo ...
- 第三部分:Android 应用程序接口指南---第二节:UI---第九章 搜索
第9章 搜索 在android平台上搜索是一个核心的用户功能.无论内容位于设备或网络上,用户应该能够搜索任何对它们可用的数据.为了创建一个一致的用户搜索体验,Android平台提供了一个搜索框架帮助你 ...
- SAP BW: Replacement Path Variables
How to use Replacement Path Variables to perform Date Calculations A Step-by-Step guide Have you eve ...
- 模仿CyclicBarrier,自定义自己屏障类
简介 在这里模仿CyclicBarrier,自定义一个自己多线程屏障类,里面有个计时器count,count为0时,才唤醒线程,否则就await挂起,(没错就是用的object类的挂起和唤醒全部线程方 ...
- STM32 ADC 采样 频率的确定
一 STM32 ADC 采样频率的确定 1. : 先看一些资料,确定一下ADC 的时钟: (1),由时钟控制器提供的ADCCLK 时钟和PCLK2(APB2 时钟)同步.CLK 控制器为A ...
- Amazon
刚接到Recruiter电话,说恭喜,feedback都非常好. 心里大石落地,FLAG / UAT终于完成一家. 接下来就要加倍努力冲刺其他公司了. Mark: (入职以后一定要去地里补发一波面经, ...
- Unity5 AssetBundle系列——资源加载卸载以及AssetBundleManifest的使用
下面代码列出了对于assetbundle资源的常用操作,其中有针对bundle.asset.gameobject三种类型对象的操作,实际使用中尽量保证成对使用. 这一块的操作比较繁琐,但只要使用正确, ...
- 阿里云 FTP 无法读取目录问题
安全组除了添加制定 FTP端口外 需要加入再添加1024/65535端口 放行策略,ftp被动模式需要随机开一个此范围端口进行传输 添加安全组规则参考文档:https://help.aliyun.co ...
- CLOS网络的无阻塞条件
交换单元及网络 模拟信号数字化和时分复用基础 交换单元模型基本交换单元 交换网络 2.1模拟信号数字化和分时复用基础 模拟信号是指在是和幅度数值上连续变化的信号 数字信号是指在时间和幅度取值上离散的编 ...