写了大作业,来水一贴。这次使用了stl中的双链表管理数据。
1 功能介绍
- 输入多项式
- 多项式加法
- 多项式减法
- 多项式乘法
- 多项式求值
- 多项式求导
2 分析
(1)定义单项式结构体,包含系数与指数。
(2)多项式频繁增删,应使用链表存储。
(3)多项式加减法:本质上是合并链表,时间复杂度o(m + n)
(4)多项式乘法:用双重循环遍历两个多项式,最后排序,合并同类项,时间复杂度o(n2)
(5)多项式求导、求值:时间复杂度o(n)
3 设计
struct node
{
double coefficient_;
int exponent_;
};
class Poly
{
private:
list<node> ploy_;
public:
Poly();
Poly(const string x);
Poly(const Poly &x);
Poly(const list<node> &x);
Poly operator+(const Poly &x) const;
Poly operator-(const Poly &x) const;
Poly operator*(const Poly &x) const;
double value(double x) const; //求值
Poly derivative() const; //求导
friend ostream &operator<<(ostream &pout, const Poly &x);
};
#endif
4 代码
4.1 poly.hpp
#ifndef POLY_HPP
#define POLY_HPP
#include <list>
#include <iostream>
#include <sstream>
#include <cmath>
using namespace std;
struct node
{
double coefficient_;
int exponent_;
node(double a = 0, int n = 0) : coefficient_(a), exponent_(n){};
node(const node &x) : coefficient_(x.coefficient_), exponent_(x.exponent_){};
bool operator<(const node &x) { return exponent_ < x.exponent_; } //for sort
bool operator==(const node &x) { return coefficient_ == x.coefficient_; } //for erase
};
void combine(list<node> &x) //合并相邻的同类项
{
auto p = x.begin();
auto last = p++;
while (p != x.end())
{
if (last->exponent_ == p->exponent_)
{
p->coefficient_ += last->coefficient_;
if (p->coefficient_ == 0)
p++;
x.erase(last, p);
last = p++;
}
else
{
last++;
p++;
}
}
};
class Poly
{
private:
list<node> ploy_;
public:
Poly(){};
Poly(const string x) { init(x); }
Poly(const Poly &x)
{
for (auto &p : x.ploy_)
ploy_.push_back(p);
};
Poly(const list<node> &x)
{
for (auto p : x)
ploy_.push_back(p);
}
~Poly(){};
void init(string x)
{
istringstream sin(x);
double a;
int n;
while (sin.peek() != '#' && sin.peek() != EOF)
{
sin >> a >> n;
if (a != 0)
ploy_.push_back({a, n});
}
ploy_.sort();
};
Poly operator+(const Poly &x) const
{
list<node> left(this->ploy_), right(x.ploy_);
left.merge(right);
combine(left);
return Poly(left);
};
Poly operator-(const Poly &x) const
{
list<node> left(this->ploy_), right(x.ploy_);
for (auto &p : right)
p.coefficient_ = -p.coefficient_;
left.merge(right);
combine(left);
return Poly(left);
}
Poly operator*(const Poly &x) const
{
list<node> temp;
for (auto p = ploy_.begin(); p != ploy_.end(); p++)
for (auto q = x.ploy_.begin(); q != x.ploy_.end(); q++)
temp.push_back(node(p->coefficient_ * q->coefficient_, p->exponent_ + q->exponent_));
temp.sort();
combine(temp);
return Poly(temp);
}
double value(double x) const //求值
{
double temp = 0;
for (auto p : ploy_)
temp += p.coefficient_ * pow(x, p.exponent_);
return temp;
}
Poly derivative() const //求导
{
list<node> temp;
auto p = ploy_.begin();
if (p->exponent_ == 0)
p++;
for (; p != ploy_.end(); p++)
temp.push_back(node(p->coefficient_ * p->exponent_, p->exponent_ - 1));
return Poly(temp);
}
friend ostream &operator<<(ostream &pout, const Poly &x)
{
if (x.ploy_.size())
{
auto p = x.ploy_.rbegin();
cout << p->coefficient_ << "x^" << p->exponent_;
for (p++; p != x.ploy_.rend(); p++)
{
cout << " + ";
if (p->coefficient_ != 1 || p->exponent_ == 0) //系数不为1 || 常数项
cout << p->coefficient_;
if (p->exponent_) //不为常数项
{
cout << 'x';
if (p->exponent_ != 1) //有指数
cout << '^' << p->exponent_;
}
}
}
else
pout << 0;
return pout;
}
};
#endif
4.2 console.hpp
#ifndef CONSOLE_HPP
#define CONSOLE_HPP
#include <windows.h>
#include <conio.h>
#include <iostream>
#include <iomanip>
using std::ios_base;
using std::ostream;
//dwButtonState 鼠标按钮状态
#define L_BUTTON 0x1
#define R_BUTTON 0x2
// dwEventFlags 鼠标事件状态
#define MOUSE_CLICK 0x0
#define MOUSE_MOVED 0x1
#define DOUBLE_CLICK 0x2
//颜色
#define COLOR_default SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x07);
#define COLOR_Black_Cyan SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0b);
#define COLOR_Yellow_Blue SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0xe9);
// 光标位置
// 移动光标位置
inline void setcursor(short x = 0, short y = 0)
{
COORD temp = {x, y};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), temp);
}
inline void setcursor(const COORD &temp)
{
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), temp);
}
// 获得光标位置
inline void getcursor(COORD &other)
{
CONSOLE_SCREEN_BUFFER_INFO temp;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &temp);
other = temp.dwCursorPosition;
}
inline COORD getcursor()
{
CONSOLE_SCREEN_BUFFER_INFO temp;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &temp);
return temp.dwCursorPosition;
}
//比较坐标
inline bool operator==(COORD a, COORD b)
{
return a.X == b.X && a.Y == b.Y;
};
inline bool operator!=(COORD a, COORD b)
{
return !(a == b);
}
//输出光标坐标
ostream &operator<<(ostream &pout, const COORD &temp)
{
pout.setf(ios_base::fixed);
pout << "[Cursor Position] X: " << std::setw(2) << temp.X << " Y: " << std::setw(2) << temp.Y;
return pout;
}
//是否隐藏光标
void hidecursor(bool hide = true)
{
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &CursorInfo);
CursorInfo.bVisible = !hide;
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &CursorInfo);
}
// 更改控制台设置,防止控制台属性导致的判定失败
void setmode()
{
DWORD mode;
GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode);
mode &= ~ENABLE_QUICK_EDIT_MODE; //移除快速编辑模式
mode &= ~ENABLE_INSERT_MODE; //移除插入模式
// mode &= ~ENABLE_MOUSE_INPUT; //移除鼠标输入
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode);
}
//判断鼠标点击位置是否在指定的有效范围(本行,本列至5列之间)
bool operator<=(const COORD &button, const COORD &click)
{
if (button.Y == click.Y && button.X <= click.X && click.X <= button.X + 20)
return true;
else
return false;
};
//等待鼠标事件,可排除鼠标移动
MOUSE_EVENT_RECORD waitmouse(bool move = true)
{
INPUT_RECORD record; //输入事件
DWORD reg; //临时寄存
while (1)
{
Sleep(10);
ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &record, 1, ®); //将输入事件存入record
if (record.EventType == MOUSE_EVENT && (move | record.Event.MouseEvent.dwEventFlags != MOUSE_MOVED)) //是鼠标事件 && 移动事件与模式对应
return record.Event.MouseEvent;
}
}
// 清屏函数
void clean(int a = 0)
{
int temp = a ? a : getcursor().Y;
setcursor(0, 0);
for (int i = 0; i <= temp; i++)
std::cout << std::string(100, ' ') << '\n';
setcursor(0, 0);
}
//暂停
void pause()
{
std::cout << "请按任意键继续\n";
std::cin.sync();
std::cin.get();
}
#endif
4.3 menu.hpp
#ifndef MENU_HPP
#define MENU_HPP
#include "console.hpp"
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::vector;
#define show_real(x) cout << #x ": " << x << '\n'
//button - click
class Menu
{
private:
struct node
{
void (*pfunc_)();
string display_;
COORD pos_;
};
vector<node> nodes_;
string title_;
protected:
void init_pos()
{
for (auto p = nodes_.begin(); p != nodes_.end(); p++)
{
getcursor(p->pos_);
cout << p->display_ << "\n\n";
}
};
bool implement(COORD clickpos)
{
waitmouse(false); //过滤鼠标松开
for (auto p = nodes_.begin(); p != nodes_.end(); p++)
{
if (p->pos_ <= clickpos) //点击成功
{
hidecursor(0);
clean();
p->pfunc_();
hidecursor(1);
cout << "\n\n鼠标点击任意位置以继续\n";
waitmouse(false);
highlight({0, 0});
return true;
}
}
return false;
};
void highlight(COORD hang)
{
clean();
cout << title_ << endl //显示内容
<< "========================================" << endl;
for (auto p = nodes_.begin(); p != nodes_.end(); p++)
{
if (p->pos_ <= hang) //悬停点
{
COLOR_Black_Cyan;
cout << p->display_ << "\n\n";
COLOR_default;
}
else
cout << p->display_ << "\n\n";
}
}
public:
//constructor
Menu(){};
~Menu(){};
//methods
Menu &settitle(string s)
{
title_ = s;
return *this;
}
Menu &add(void (*p)() = nullptr, string d = "Unkown.")
{
nodes_.push_back({p, d});
return *this;
};
void start()
{
MOUSE_EVENT_RECORD mouse;
setmode();
hidecursor(1);
clean();
cout << title_ << endl //显示内容
<< "========================================" << endl;
init_pos(); //记录位置
do
{
Sleep(10); //减少次数
mouse = waitmouse();
if (mouse.dwEventFlags == MOUSE_MOVED)
highlight(mouse.dwMousePosition);
else if (mouse.dwButtonState == L_BUTTON)
implement(mouse.dwMousePosition);
} while (mouse.dwButtonState != R_BUTTON);
Sleep(100); //过滤
};
};
#endif
4.4 主函数
#include "poly.hpp"
#include "menu.hpp"
#include <iostream>
using namespace std;
void show1();
void show2();
void show11(); //+
void show12(); //-
void show13(); //*
void show14(); //`
void show15(); //求值
int main()
{
Menu loop;
loop.settitle("多项式计算器(右键退出)");
loop.add(show1, "开始计算").add(show2, "功能演示");
loop.start();
}
void show2()
{
cout << "输入格式:\n"
"先输入系数,再输入指数,使用空格分隔开;输入完按回车\n"
"如:\n"
"输入: 1.1 2 3.3 4\n"
"表示: 1.1x^2 + 3.3x^4\n"
"你并不需要降次输入,程序会完成整理过程\n";
Sleep(1000);
}
void show1()
{
Menu cal;
cal.settitle("请选择功能");
cal.add(show11, "多项式加法").add(show12, "多项式减法").add(show13, "多项式乘法");
cal.add(show14, "多项式求导").add(show15, "多项式求值");
cal.start();
}
void show11() //+
{
Poly left, right;
{
char temp[101];
cout << "请输入左多项式:";
cin.getline(temp, 100);
left.init(temp);
cout << "请输入右多项式:";
cin.getline(temp, 100);
right.init(temp);
}
show_real(left);
show_real(right);
show_real(left + right);
}
void show12() //-
{
Poly left, right;
{
char temp[101];
cout << "请输入左多项式:";
cin.getline(temp, 100);
left.init(temp);
cout << "请输入右多项式:";
cin.getline(temp, 100);
right.init(temp);
}
show_real(left);
show_real(right);
show_real(left - right);
};
void show13() //*
{
Poly left, right;
{
char temp[101];
cout << "请输入左多项式:";
cin.getline(temp, 100);
left.init(temp);
cout << "请输入右多项式:";
cin.getline(temp, 100);
right.init(temp);
}
show_real(left);
show_real(right);
show_real(left * right);
}
void show14() //`
{
Poly polynomial;
{
char temp[101];
cout << "请输入多项式:";
cin.getline(temp, 100);
polynomial.init(temp);
}
show_real(polynomial);
cout << "导数为:" << polynomial.derivative() << '\n';
}
void show15() //求值
{
Poly polynomial;
double x;
{
char temp[101];
cout << "请输入多项式:";
cin.getline(temp, 100);
polynomial.init(temp);
cout << "请输入x的值:";
cin >> x;
}
show_real(polynomial);
printf("当x的值为%f时,多项式的值为: %f", x, polynomial.value(x));
}