数据结构算法C语言实现(六)---2.4一元多项式的表示及相加
一.简述
利用链表表示稀疏多项式,并基于之前的一些操作(编程实现上还是有所不同的)组合新的操作实现一元多项式的表示及相加。
二.ADT
1 抽象数据类型一元多项式的定义
2 ADT Polyomail{
3 数据对象:D = {a[i]|a[i]属于TermSet, i = 1,2,3...,m,m>=0
4 TermSet中每个元素包含一个表示系数的实数和表示指数的整数}
5 数据关系
6 基本操作:
7 CreatPolyn(&P, m)
8 操作结果:输入 m 项的系数和指数,建立一元多项式 P
9 DestroyPolyn(&P)
10 初始条件:一元多项式 P 已存在
11 操作结果:销毁一元多项式P
12 PrintPolyn(P)
13 初始条件:一元多项式 P 已存在
14 操作结果:打印输出一元多项式 P
15 PolynLength(P)
16 初始条件:一元多项式 P 已存在
17 操作结果:返回一元多项式中 P 的项数
18 AddPolyn(&Pa, &Pb)
19 初始条件:一元多项式 Pa 和 Pb 已存在
20 操作结果:完成多项式相加运算,即:Pa = Pa + Pb,并销毁一元多项式 Pb
21 SubtractPolyn(&Pa, &Pb)
22 初始条件:一元多项式 Pa 和 Pb 已存在
23 操作结果:完成多项式相减运算,即 Pa = Pa - Pb,并销毁一元多项式 Pb
24 MultiplyPolyn(&Pa, &Pb)
25 初始条件:一元多项式 Pa 和 Pb 已存在
26 操作结果:完成多项式相乘运算,即 Pa = Pa x Pb,并销毁一元多项式 Pb
27 }ADT Polynomial
28 */
View Code
三.头文件
1 //2_4.h
2 /**
3 《数据结构(C语言版)》 Page 37
4 ....为此,从实际应用角度出发重新定义线性链表及其基本操作....
5 */
6 /**
7 author:zhaoyu
8 email:zhaoyu1995.com@gmail.com
9 date:2016-6-6
10 note:realize my textbook <<数据结构(C语言版)>>
11 */
12 #ifndef _2_4_H_
13 #define _2_4_H_
14 #include "head.h"
15 typedef struct{//项的表示,多项式的项作为LinkList的数据元素
16 float coef;//系数
17 int expn;//指数
18 }term, ElemType;//两个类型名:term用于本ADT,ElemType为LinkList的数据对象名
19 typedef struct LNode{
20 ElemType data;
21 struct LNode *next;
22 }*Link, *Position;
23 typedef struct{//链表类型
24 Link head, tail;//分别指向线性链表中的头结点和最后一个结点
25 int len;//指示线性链表中数据元素的个数
26 }LinkList;
27 typedef LinkList polynomial;//用带表头结点的有序链表表示多项式
28
29 int cmp(term a, term b)
30 {
31 //依据 a 的指数值 <(或=)(或>) b 的指数值 ,返回 -1 ,0, +1
32 if(a.expn < b.expn)
33 {
34 return -1;
35 }
36 else if (a.expn == b.expn)
37 {
38 return 0;
39 }
40 else
41 {
42 return 1;
43 }
44 }
45 Status InitList(LinkList &L)
46 {
47 //构造一个空的线性表L
48 L.head = (Link)malloc(sizeof(struct LNode));
49 L.head->data.coef = 0.0;
50 L.head->data.expn = -1;
51 L.head->next = NULL;
52 L.tail = L.head->next;
53 L.len = 0;
54 }
55 Position GetHead(LinkList L)
56 {
57 //返回线性链表 L 中头结点的位置
58 return L.head;
59 }
60 Status SetCurElem(Link &p, ElemType e)
61 {
62 //已知 p 指向线性链表中的一个结点,用 e 更新 p 所指结点中数据元素的值
63 p->data.coef = e.coef;
64 p->data.expn = e.expn;
65 return OK;
66 }
67 Status LocateElem(LinkList L, ElemType e, Position &q, Status (* compare)(ElemType, ElemType))
68 {
69 //若有序链表 L 中存在与 e 满足判定函数 compare() 取值为 0 的函数
70 //则 q 指示 L 中第一个值为 e 的结点的位置,并返回 TRUE;否则 q 指示
71 //第一个与 e 满足compare() 取值>0的元素的前驱的位置,并返回FLASE
72 Link temp = L.head->next;
73 while (temp != NULL)
74 {
75 if (0 == (* compare)(temp->data, e))
76 {
77 q = temp;
78 return TRUE;
79 }
80 temp = temp->next;
81 }
82 temp = L.head;
83 while (temp->next != NULL)
84 {
85 if ((* compare)(temp->next->data, e) > 0)
86 {
87 q = temp;
88 return FALSE;
89 }
90 temp = temp->next;
91 }
92 q = temp;
93 return FALSE;
94 }
95 Status MakeNode(Link &p, ElemType e)
96 {
97 //分配由 p 指向的值为 e 的结点,并返回 OK;若分配失败,则返回 ERROR
98 p = (Link)malloc(sizeof(struct LNode));
99 if (!p)
100 {
101 return ERROR;
102 }
103 p->data.coef = e.coef;
104 p->data.expn = e.expn;
105 p->next = NULL;
106 return OK;
107 }
108 Status InsFirst(Link &h, Link &s)
109 {
110 //已知 h 指向线性链表的头结点,将 s 所指节点插入在第一个结点之前
111 if (NULL == h)
112 {
113 return ERROR;
114 }
115 else
116 {
117 s->next = h->next;
118 h->next = s;
119 }
120 return OK;
121 }
122 ElemType GetCurElem(Link p)
123 {
124 //已知 p 指向线性链表中的一个节点,返回 p 所指结点中数据元素的值
125 if (p != NULL)
126 {
127 return p->data;
128 }
129 else
130 {
131 exit(ERROR);
132 }
133 }
134 /**
135 My Code
136 */
137 Position NextPos(LinkList L, Link p)
138 {
139 //已知 p 指向线性链表 L 中的一个节点,返回 p 所指结点
140 //的直接后继的位置,若无后继,返回 NULL
141 Link q = L.head;
142 while (q->next != NULL)
143 {
144 if(q == p)
145 {
146 return p->next;
147 }
148 q = q->next;
149 }
150 return NULL;
151 }
152 Status DelFirst(Link &h, Link &q)
153 {
154 //已知 h 指向线性链表的头结点,删除链表中的第一个节点并以 q 返回
155 if (h == NULL)
156 {
157 return ERROR;
158 }
159 q = h->next;
160 h->next = q->next;
161 q->next = NULL;
162 return OK;
163 }
164 Status FreeNode(Link &p)
165 {
166 //释放 p 所指节点
167 p = NULL;//便于回收???释放后再次使用
168 free(p);
169 }
170 Status ListEmpty(LinkList L)
171 {
172 //若线性链表 L 为空,则返回 TRUE,否则返回 FALSE
173 if (L.head->next == NULL)
174 {
175 return TRUE;
176 }
177 else
178 {
179 return FALSE;
180 }
181 }
182 Status Append(LinkList &L, Link &s)
183 {
184 //将指针 s 所指(彼此以指针相链)的一串结点
185 //链接在线性链表 L 最后一个结点
186 Link q = L.head;
187 while (q->next != NULL)
188 {
189 q = q->next;
190 }
191 q->next = s;
192 int cnt = 0;
193 Link temp = s;
194 while (temp != NULL)
195 {
196 cnt++;
197 if (NULL == temp->next)
198 {
199 L.tail = temp;//注意更新尾指针
200 }
201 temp = temp->next;//注意这一句要放在最后,否则可能访问非法内存
202 }
203
204 L.len += cnt;
205 //注意要根据这一串结点长度增加链表长度
206 return OK;
207 }
208 void PrintPolyn(polynomial P)
209 {
210 Link temp = P.head->next;
211 while (temp != NULL)
212 {
213 printf("%.1f\t", temp->data.coef);
214 temp = temp->next;
215 }
216 printf("\n");
217 temp = P.head->next;
218 while (temp != NULL)
219 {
220 printf("%d\t", temp->data.expn);
221 temp = temp->next;
222 }
223 printf("\n");
224 }
225 /**
226 algorithm 2.22
227 */
228 void CreatPolyn(polynomial &P, int m)
229 {
230 //输入 m 项的系数和指数,建立表示一元多项式的有序链表 P
231 InitList(P);
232 Link h = GetHead(P), s, q;
233 ElemType e;
234 e.coef = 0.0;
235 e.expn = -1;
236 SetCurElem(h, e);//设置头结点中的数据元素
237 for (int i = 1; i <= m; i++)
238 {//依次输入 m 个非零项
239 scanf("%f%d", &e.coef, &e.expn);
240 if (!LocateElem(P, e, q, (* cmp)))
241 {//当前链表中不存在该指数项
242 if (MakeNode(s, e))
243 {
244 InsFirst(q, s);
245 }
246 }
247 }
248 }//CreatePolyn
249 /**
250 algorithm 2.23
251 */
252 void AddPolyn(polynomial &Pa, polynomial &Pb)
253 {
254 //多项式加法:Pa = Pa + Pb,利用两个多项式构成和多项式
255 Link ha = GetHead(Pa);
256 Link hb = GetHead(Pb);//pa 和 pb 分别指向 Pa 和 Pb 的头结点
257 Link qa = NextPos(Pa, ha);
258 Link qb = NextPos(Pb, hb);//qa 和 qb 分别指向 Pa 和 Pb 中当前节点
259 while (qa && qb)//qa 和 qb均非空
260 {
261 ElemType a = GetCurElem(qa);
262 ElemType b = GetCurElem(qb);//a、b为两表中当前比较元素
263 switch ((* cmp)(a, b))
264 {
265 case -1://多项式 Pa 中当前节点的指数值小
266 {
267 ha = qa;
268 qa = NextPos(Pa, qa);//printf("%d\n", qa->data.expn);
269 break;
270 }
271 case 0://两者的指数值相等
272 {
273 ElemType S = {a.coef + b.coef, a.expn};
274 if(0 != S.coef)
275 {//修改多项式 Pa 中当前节点
276 SetCurElem(qa, S);
277 ha = qa;
278 }
279 else
280 {//删除多项式中 Pa 当前节点
281 DelFirst(ha, qa);
282 FreeNode(qa);
283 }
284 DelFirst(hb, qb);
285 FreeNode(qb);
286 qa = NextPos(Pa, ha);
287 qb = NextPos(Pb, hb);
288 break;
289 }
290 case 1://多项式 Pb 当前结点指数值小
291 {
292 DelFirst(hb, qb);
293 InsFirst(ha, qb);
294 qb = NextPos(Pb, hb);
295 ha = NextPos(Pa, ha);
296 break;
297 }
298 }//switch
299 }//while
300 if (!ListEmpty(Pb))
301 {
302 Append(Pa, qb);//链接 Pb 中剩余结点
303 }
304 FreeNode(hb);//释放 Pb 的头结点
305 }//AddPolyn
306 #endif
View Code
四.CPP文件
1 #include "2_4.h"
2
3 int main(int argc, char const *argv[])
4 {
5 polynomial Pa, Pb, Pc;
6 int n;
7 printf("Input n\t");
8 scanf("%d", &n);
9 CreatPolyn(Pa, n);
10 printf("Pa\n");
11 PrintPolyn(Pa);
12 printf("Input n\t");
13 scanf("%d", &n);
14 CreatPolyn(Pb, n);
15 printf("Lb\n");
16 PrintPolyn(Pb);
17 AddPolyn(Pa, Pb);
18 printf("La + Lb\n");
19 PrintPolyn(Pa);
20 return 0;
21 }
View Code
五.测试

六.小结
不要对着伪代码一行行敲代码,一定要在理解的基础上实现算法,否则敲错一个变量导致奇怪的错误也要大费周折才能找到。