一元多项式计算器
概要
设有一元多项式An(x)和Bm(X),编程实现多项式Am(x)和Bn(X)的加法、减法和乘法运算。其中多项式描述为:
An(x)=A0+A1x1+A2x2+A3x3+….+Amxn
Bm(x)=B0+B1x1+B2x2+B3x3+….+Bmxm
数据结构的定义
- LNode为每个节点的数据类型,表示多项式每一项的系数-指数
- node为单链表链表,ELemType为已声明的LNode
1
2
3
4
5
6
7
8
9typedef struct LNode {
int coe; // 系数
int exp; // 指数
} ElemType;
typedef struct node {
ElemType data; // 数据
node* next; // 下一节点
} LinkNode, *LinkList;
LinkList——链表的实现
- 该部分用以定义链表结构以及声明链表的函数原型
- LinkList.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
typedef int Status;
typedef struct LNode {
int coe; // 系数
int exp; // 指数
// 构造函数,初始化节点,赋值
LNode() : coe(0), exp(0) {}
LNode(int coe, int exp) : coe(coe), exp(exp) {}
// 重载 == 用以比较,系数和指数均相同时判定相等
bool operator==(const LNode& A) const {
if (coe != A.coe)
return false;
if (exp != A.exp)
return false;
return true;
}
} ElemType;
typedef struct node {
ElemType data;
node* next;
} LinkNode, *LinkList;
Status creat_LinkList(LinkList& L); // 创建链表
void clear_LinkList(LinkList& L); // 清空链表
Status push_back(LinkList L, const ElemType x); // 在链表尾部插入元素
Status push_ascending(LinkList L, const ElemType x); // 插入链表,使链表保持升序
Status delete_node(LinkList L, ElemType x); // 删除链表中第一个与x相同的元素
void print_LinkList(LinkList L); // 输出链表
void print_LinkList_ascending(LinkList L /*, bool op*/); // 升幂输出链表
void print_LinkList_descending(LinkList L /*, bool op*/); // 降幂输出链表
void print_Lnode(const ElemType x, const bool op); // 输出当前节点元素
void copy(LinkList& C, LinkList L); // 复制L到C - LinkList.cpp
实现了链表的基本操作
tip:在某些情况下,递归输出链表的格式会出现非预期效果(已解决)
例如:(升幂) 当链表头元素的系数为0时(0 1 3 2 -2 1)
会输出: + 3x^2 - 2x 预期 3x^2 - 2x
例如:(降幂) 当链表内只含有一个有效元素时(3 2)
会输出: + 3x^2 预期 3x^2解决方案1:仍使用递归输出
升幂时,删除链表中所有系数为0的元素;降幂时,直接输出链表唯一元素
解决方案2:不使用递归输出
采用适当的容器,将链表中有效元素添加到容器中,控制格式输出1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// 创建链表
Status creat_LinkList(LinkList& L) {
L = (LinkList)malloc(sizeof(LNode));
if (!L)
return ERROR;
L->next = NULL;
return OK;
}
// 清空链表
void clear_LinkList(LinkList& L) {
if (L->next) {
clear_LinkList(L->next);
free(L->next);
L->next = NULL;
}
}
// 在链表尾部插入元素
Status push_back(LinkList L, const ElemType x) {
LinkList D;
while (L->next)
L = L->next;
D = (LinkList)malloc(sizeof(LNode));
if (!D)
return ERROR;
D->data = x;
D->next = NULL;
L->next = D;
return OK;
}
// 插入链表,使链表保持升序
Status push_ascending(LinkList L, const ElemType x) {
while (L->next && x.exp >= L->next->data.exp) {
// 如果已经含有相同指数,则系数相加
if (L->next->data.exp == x.exp) {
L->next->data.coe += x.coe;
return OK;
}
L = L->next;
}
// 新指数节点,插入到L的合适位置
LinkList D = (LinkList)malloc(sizeof(LNode));
D->data = x;
D->next = L->next;
L->next = D;
return OK;
}
// 删除链表中第一个与x相同的元素
Status delete_node(LinkList L, ElemType x) {
while (L->next) {
if (L->next->data == x) {
// 如果是链表最后一个元素
if (L->next->next == NULL) {
free(L->next->next);
L->next = NULL;
} else {
LinkList tmp = L->next->next;
free(L->next);
L->next = tmp;
}
return OK;
} else {
L = L->next;
}
}
return ERROR;
}
/*
* FOR: print_*
* op : true 多项式第一项
* op : false 非多项式第一项
*/
// 输出链表
void print_LinkList(LinkList L) {
__GREEN__
cout << "以升幂输出多项式" << endl;
__WHITE__
print_LinkList_ascending(L /*, true*/);
cout << endl;
__GREEN__
cout << "以降幂输出多项式" << endl;
__WHITE__
print_LinkList_descending(L /*, false*/);
cout << endl;
}
// 升幂输出链表
void print_LinkList_ascending(LinkList L /*, bool op*/) {
queue<ElemType> Q;
while (L->next) {
if (L->next->data.coe != 0)
Q.push(L->next->data);
L = L->next;
}
bool op = true;
while (!Q.empty()) {
print_Lnode(Q.front(), op);
op = false;
Q.pop();
}
// if (L) {
// print_Lnode(L->data, op);
// print_LinkList_ascending(L->next, false);
// }
}
// 降幂输出链表
void print_LinkList_descending(LinkList L /*, bool op*/) {
stack<ElemType> S;
while (L->next) {
if (L->next->data.coe != 0)
S.push(L->next->data);
L = L->next;
}
bool op = true;
while (!S.empty()) {
print_Lnode(S.top(), op);
op = false;
S.pop();
}
// if (L) {
// if (L->next && L->next->next == NULL)
// print_LinkList_descending(L->next, true);
// else
// print_LinkList_descending(L->next, false);
// print_Lnode(L->data, op);
// }
}
/*
* 用以格式化输出
* 例如,将会以如下格式输出多项式:
* "-3^2 + 4^3 - 5^4"
* "3^2 + 4^3 - 5^4"
*/
// 输出当前节点元素
void print_Lnode(const ElemType x, const bool op) {
if (op) {
if (x.coe < 0)
cout << "-";
} else {
if (x.coe < 0)
cout << " - ";
else
cout << " + ";
}
// 控制输出格式
int COE = abs(x.coe);
if (x.exp == 0) {
cout << COE;
} else if (x.exp == 1) {
if (COE != 1)
cout << COE;
cout << "x";
} else {
if (COE != 1)
cout << COE;
cout << "x^";
if (x.exp < 0)
cout << "(" << x.exp << ")";
else
cout << x.exp;
}
}
// 复制L到C
void copy(LinkList& C, LinkList L) {
while (L->next) {
push_ascending(C, L->data);
L = L->next;
}
}
calculate——计算多项式
- 该部分用以声明计算的函数原型
calculate.h
1
2
3
4
5
6
7
8
void AddList(LinkList A, LinkList B, LinkList& L); // 多项式相加
void SubList(LinkList A, LinkList B, LinkList& L); // 多项式相减
void MulList(LinkList A, LinkList B, LinkList& L); // 多项式相乘calculate.cpp
加/减:定义两个指针分别指向A,B,不断遍历两指针,分情况将得到的元素插入到L中
乘:定义两个指针la、lb,对于每个la,遍历每个lb,进行乘法运算
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
void AddList(LinkList A, LinkList B, LinkList& L) { // 多项式相加
LinkList la = A->next, lb = B->next;
while (la && lb) {
// 如果指数相同
if (la->data.exp == lb->data.exp) {
int COE = la->data.coe + lb->data.coe;
int EXP = la->data.exp;
push_ascending(L, ElemType(COE, EXP));
la = la->next;
lb = lb->next;
}
// 将小的元素添加到L中
else if (la->data.exp < lb->data.exp) {
push_ascending(L, la->data);
la = la->next;
} else {
push_ascending(L, lb->data);
lb = lb->next;
}
}
// 将A、B中剩余元素添加到L中
// 可以直接令L尾指针指向la或lb
while (la) {
push_ascending(L, la->data);
la = la->next;
}
while (lb) {
push_ascending(L, lb->data);
lb = lb->next;
}
}
void SubList(LinkList A, LinkList B, LinkList& L) { // 多项式相减
LinkList la = A->next, lb = B->next;
while (la && lb) {
// 如果指数相同
if (la->data.exp == lb->data.exp) {
int COE = la->data.coe - lb->data.coe;
int EXP = la->data.exp;
push_ascending(L, ElemType(COE, EXP));
la = la->next;
lb = lb->next;
}
// 将小的元素添加到L中
else if (la->data.exp < lb->data.exp) {
push_ascending(L, la->data);
la = la->next;
} else {
// 相减,系数取负
push_ascending(L, ElemType(-lb->data.coe, lb->data.exp));
lb = lb->next;
}
}
// 将A、B中剩余元素添加到L中
while (la) {
push_ascending(L, la->data);
la = la->next;
}
while (lb) {
// 相减,系数取负
push_ascending(L, ElemType(-lb->data.coe, lb->data.exp));
lb = lb->next;
}
}
void MulList(LinkList A, LinkList B, LinkList& L) { // 多项式相乘
LinkList la = A->next;
while (la) {
LinkList lb = B->next;
while (lb) {
// 系数相乘,指数相加
int COE = la->data.coe * lb->data.coe;
int EXP = la->data.exp + lb->data.exp;
push_ascending(L, ElemType(COE, EXP));
lb = lb->next;
}
la = la->next;
}
}
solve——主体框架
- solve.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void solve();
void tip_polynomial(const int num, LinkList& L); // 提示输入多项式
void tip_outPolynomial(const int num, LinkList L); // 提示输出输入的多项式
void tip_operator(char& op); // 提示输入运算符
void tip_outOperator(const char op); // 输出输入的运算符
void cal_polynomial(LinkList A, LinkList B, LinkList& L, const char op); // 计算多项式
void tip_answer(); // 提示输出结果 - solve.cpp
- 实现简单的交互界面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/*
* 能够实现n个多项式计算
* 更改solve.h中的TOL即可
*/
void solve() {
LinkList L[TOL + 1];
// 输入多项式
for (int i = 1; i <= TOL; i++) {
creat_LinkList(L[i]);
tip_polynomial(i, L[i]);
}
// 输出输入数据
for (int i = 1; i <= TOL; i++) {
tip_outPolynomial(i, L[i]);
cout << endl;
}
// 输入操作符
char oper;
tip_operator(oper);
tip_outOperator(oper);
// 创建RES链表,记录运算答案
LinkList CAS, RES;
creat_LinkList(CAS);
creat_LinkList(RES);
// 计算结果
for (int i = 1; i < TOL; i++) {
if (i == 1)
cal_polynomial(L[i], L[i + 1], RES, oper);
else {
// 将中间结果复制到CAS中,用于下一次计算
copy(CAS, RES);
cal_polynomial(CAS, L[i + 1], RES, oper);
}
}
// 输出结果多项式
tip_answer();
print_LinkList(RES);
}
// 提示输入多项式
void tip_polynomial(const int num, LinkList& L) {
__GREEN__
cout << "请输入第" << num << "个多项式" << endl;
cout << "请先输入一个整数n,表示多项式的项数" << endl;
__WHITE__
int n;
cin >> n;
__GREEN__
cout << "接着输出" << n << "个多项式(系数 指数)" << endl;
__WHITE__
for (int i = 0; i < n; i++) {
ElemType x;
cin >> x.coe >> x.exp;
push_ascending(L, x);
}
}
// 提示输出输入的多项式
void tip_outPolynomial(const int num, LinkList L) {
cout << "输入的第" << num << "个多项式的降幂形式为:";
print_LinkList_descending(L /*, false*/);
cout << endl;
}
// 提示输入运算符
void tip_operator(char& oper) {
__GREEN__
cout << "请输入操作符(+ - *)" << endl;
__WHITE__
cin >> oper;
}
// 输出输入的运算符
void tip_outOperator(const char op) {
cout << "输入的运算符为" << op << endl;
}
// 计算多项式
void cal_polynomial(LinkList A, LinkList B, LinkList& L, const char op) {
clear_LinkList(L);
switch (op) {
case '+':
AddList(A, B, L);
break;
case '-':
SubList(A, B, L);
break;
case '*':
MulList(A, B, L);
break;
default:
__RED__
cout << "操作符错误" << endl;
__WHITE__
break;
}
}
// 提示输出结果
void tip_answer() {
__GREEN__
cout << "计算结果多项式为:" << endl;
__WHITE__
}
main——主函数
- 包含其他所有使用到的头文件以及.h文件
- main.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using namespace std;
int main(); - main.cpp
1
2
3
4
5
6
7
8
int main() {
// freopen("D:\\CF\\in.txt", "r", stdin);
solve();
system("pause");
return 0;
}
changeFontColor——更改字体颜色
- changeFontColor.h
1
2
3
4
5
6
7
8
9
10
11
12
13
void fontColorToDefault();
void fontColorToWhite();
void fontColorToRed();
void fontColorToGreen();
void fontColorToBlue();
void fontColorToYellow();
void fontColorToPink();
void fontColorToCyanBlue(); - changeFontColor.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
void fontColorToDefault() {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY);
}
void fontColorToWtipe() {
SetConsoleTextAttribute(
GetStdHandle(STD_OUTPUT_HANDLE),
FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}
void fontColorToRed() {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
FOREGROUND_INTENSITY | FOREGROUND_RED);
}
void fontColorToGreen() {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
FOREGROUND_INTENSITY | FOREGROUND_GREEN);
}
void fontColorToBlue() {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
FOREGROUND_INTENSITY | FOREGROUND_BLUE);
}
void fontColorToYellow() {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);
}
void fontColorToPink() {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE);
}
void fontColorToCyanBlue() {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE);
}
附:随机生成数据
生成用以上述程序的数据,通过修改TOL值可以改变生成多项式的个数
1 |
|
实例演示
sample1
2
3 2 -3 0
2
3 4 -1 2
+sample2
2
4 0 3 5
3
3 3 3 5 1 0
-sample3
2
5 1 1 4
2
2 5 -3 1
*sample4
4
-7 5 4 -2 9 -9 -3 5
8
2 8 -5 -7 0 6 -1 -10 -9 -6 -2 10 6 -5 5 -1
+sample5
6
1 -7 9 -1 10 -1 9 3 4 -7 9 1
3
-8 8 7 -7 -1 -8
-sample6
6
-10 1 3 -3 6 -5 -9 2 -6 -1 1 2
2
2 0 -2 9
*