Polynomial.h
1 #define _CRT_SECURE_NO_DEPRECATE 2 #include "Polynomial.h" 3 #include <stdio.h> 4 #include <stdlib.h> 5 6 int ListLength(NormLinkList *L) 7 { 8 int num = 0; 9 Link p = NextPos(L, GetHead(L)); 10 while(p) 11 { 12 num++; 13 p = NextPos(L, p); 14 } 15 return num; 16 }//PolynLength()個人覺得這兩個函數功能一樣 17 18 Status MakeNode(Link *p, ElemType e) 19 { 20 //分配由*p指向的值為e的節點,並返回OK;若分配失敗,則返回ERROR(此處使用了指向指針的指針p,*p為節點的地址) 21 *p = (Link)malloc(sizeof(NormLNode)); 22 if(!(*p)) 23 return ERROR; 24 (*p)->data = e; 25 (*p)->next = NULL; 26 return OK; 27 } 28 29 void FreeNode(Link p) 30 { 31 //釋放p所指節點 32 free(p); 33 } 34 35 36 Status InitList(NormLinkList *L) 37 { 38 //構造一個空的線性鏈表L 39 L->head = (Link)malloc(sizeof(NormLNode));//生成頭節點 40 if(!(L->head)) 41 return ERROR; 42 L->head->next = NULL; 43 L->tail = L->head; 44 L->len = 0; 45 return OK; 46 } 47 48 49 Status DestroyList(NormLinkList *L) 50 { 51 //銷毀線性鏈表L,L不再存在 52 Link p = L -> head -> next;//p指向L的第一個節點 53 Link q; 54 while(p) 55 { 56 q = p -> next; 57 free(p); 58 p = q; 59 } 60 free(L -> head);//釋放頭節點空間 61 free(L); 62 return OK; 63 } 64 65 66 Status ClearList(NormLinkList *L) 67 { 68 //將線性鏈表L重置為空表(僅有頭節點),並釋放原鏈表的存儲空間 69 Link p = L -> head -> next;//p指向L的第一個節點 70 Link q; 71 while(p) 72 { 73 q = p -> next; 74 free(p); 75 p = q; 76 } 77 L -> head -> next = NULL; 78 L -> tail = L -> head; 79 L -> len = 0; 80 return OK; 81 } 82 83 84 Status InsFirst(Link h, Link s) 85 { 86 //將s所指節點插入在第一個節點之前 87 if(h && s) 88 { 89 s -> next = h -> next; 90 h -> next = s; 91 return OK; 92 } 93 else 94 return ERROR; 95 } 96 97 98 Status DelFirst(Link h, Link *q) 99 { 100 //刪除鏈表中的第一個節點,並用q返回 101 *q = h -> next;//*q指向待刪除節點 102 h -> next = (*q) -> next; 103 (*q)->next = NULL;//非常重要,否則*q會鏈接到剩余的節點 104 return OK; 105 } 106 107 108 Status Append(NormLinkList *L, Link s) 109 { 110 //將指針s所指(彼此以指針相鏈接)的一串節點鏈接在線性鏈表L的最后一個節點之后, 111 //並改變鏈表L的尾指針指向新的尾節點 112 Link p = s, q = s;//p指向s,q保持在p前面 113 int j = 0;//指示s中的節點個數,用於更新L->len,考慮到了s為空的情況,此時while條件不滿足,j為0 114 if(!UpdateTail(L)) 115 return ERROR; 116 L -> tail -> next = s; 117 while(p) 118 { 119 //退出時,q指向s中最后一個節點,j為s中的節點個數 120 j++; 121 q = p; 122 p = p -> next; 123 } 124 L -> tail = q; 125 L -> len += j; 126 return OK; 127 } 128 129 130 Status UpdateTail(NormLinkList *L) 131 { 132 //注意L為空表的情況 133 //更新L的尾節點,並更新鏈表長度 134 Link p = L -> head -> next, q = L -> head -> next;//p指向鏈表第一個節點,q保持在p前面 135 int j = 0;//指示s中的節點個數,用於更新L->len,考慮到了s為空的情況,此時while條件不滿足,j為0 136 if(!(L->head->next))//考慮L為空的情況,此時若執行后面語句,會導致L->tail指向NULL,使得Append函數的L->tail->next = s;語句訪存沖突 137 return OK; 138 while(p) 139 { 140 //退出時,q指向L中最后一個節點,j為L中的節點個數(僅在L非空時有效) 141 j++; 142 q = p; 143 p = p -> next; 144 } 145 L -> tail = q; 146 L -> len = j; 147 return OK; 148 } 149 150 151 Position GetHead(NormLinkList *L) 152 { 153 //返回線性鏈表L中頭節點的位置 154 return L -> head; 155 } 156 157 158 Position NextPos(NormLinkList *L, Link p) 159 { 160 //已知p指向線性鏈表L中的一個節點,返回p所指節點的直接后繼的位置,若無后繼,則返回NULL 161 return p->next; 162 } 163 164 165 ElemType GetCurElem(Link p) 166 { 167 //已知p指向線性鏈表中的一個節點,返回p所指節點中數據元素的值 168 return p -> data; 169 } 170 171 172 Status LocatePos(NormLinkList *L, int i, Link *p) 173 { 174 //用*p返回線性鏈表L中第i個節點的位置並返回OK,i值不合法時返回ERROR。此處p為指向指針的指針,用於返回第i個節點的地址 175 //0 <= i <= 表長;(i取0時,返回頭節點位置,用於在L的第一個節點前插入元素,ListInsert_NL調用時會用到) 176 Link q = L -> head;//q指向L中的頭節點 177 int j = 0; 178 while(q && j < i) 179 { 180 //退出時,q == NULL,或者j == i 181 q = q->next; 182 j++; 183 } 184 if(!q || j > i)//q為空,或者 i < 0,即第i個元素不存在 185 return ERROR; 186 *p = q;//此時q指向L中第i個節點的位置 187 return OK; 188 } 189 190 191 Status SetCurElem(Link p, ElemType e) 192 { 193 //已知p指向線性鏈表中的一個節點,用e更新p所指節點中數據元素的值 194 if(p) 195 p->data = e; 196 else 197 return ERROR; 198 return OK; 199 } 200 201 202 Status LocateElem(NormLinkList *L, ElemType e, Position *q, Status (* compare)(ElemType, ElemType)) 203 { 204 //若有序鏈表L中存在與e滿足判定函數compare()取值為0的元素,則*q指示L中第一個值為e的節點的位置,並返回TRUE 205 //否則*q指示第一個與e滿足判定函數compare()取值>0的元素的前驅的位置,並返回FALSE。此處p為指向指針的指針,用於返回滿足條件的節點的地址 206 Position p = L -> head, r = L -> head -> next;//p指向L中的頭節點,r作為p的直接后繼 207 while(r && (* compare)(r -> data, e) < 0) 208 { 209 //退出時,要么r為NULL,要么r->data的指數項等於或者大於e的指數項 210 p = r; 211 r = r->next; 212 } 213 if(r == NULL) 214 { 215 //要么表為空,要么e的指數項大於L中的最高指數項,此時返回r的直接前驅p 216 *q = p; 217 return FALSE; 218 } 219 else 220 { 221 //r不為空 222 if((* compare)(r->data, e) == 0) 223 { 224 //存在與e指數項相同的節點,此時r指向該節點 225 *q = r; 226 return TRUE; 227 } 228 else 229 { 230 //不存在與e指數項相同的節點,此時r->data的指數項大於e的指數項,此時返回r的直接前驅p 231 *q = p; 232 return FALSE; 233 } 234 } 235 236 } 237 238 239 Status ListEmpty(NormLinkList *L) 240 { 241 //若線性鏈表L為空表,則返回TRUE,否則返回FALSE 242 if(L -> head -> next == NULL) 243 return TRUE; 244 else 245 return FALSE; 246 } 247 248 249 Status ListInsert_NL(NormLinkList *L, int i, ElemType e) 250 { 251 //在帶頭節點的單鏈線性表L的第i個元素之前插入元素e 252 Link *h = (Link *)malloc(sizeof(Link)); 253 Link *s = (Link *)malloc(sizeof(Link)); 254 if(!LocatePos(L, i-1, h))//i值在鏈表范圍之外,即i<=0,或者i>表長;否則,通過*h返回L中的第i-1個節點的位置 255 return ERROR; 256 if(!MakeNode(s, e))//結點存儲分配失敗;否則,通過*s返回新生成的節點地址 257 return ERROR; 258 InsFirst(*h, *s);//將節點*s插入到節點*h后面 259 return OK; 260 } 261 262 263 Status MergeList_NL(NormLinkList *La, NormLinkList *Lb, NormLinkList *Lc, int (* compare)(ElemType, ElemType)) 264 { 265 //UpdateTail函數中未處理表為空的情況 266 //已知單鏈線性表La和Lb的元素按值非遞減排列 267 //歸並La和Lb得到新的單鏈線性表Lc,Lc的元素也按值非遞減排列 268 Position ha = GetHead(La); 269 Position hb = GetHead(Lb);//ha,hb分別指向La,Lb的頭節點 270 Position pa = NextPos(La, ha); 271 Position pb = NextPos(Lb, hb);//pa,pb分別指向La,Lb的當前節點(第一個節點) 272 ElemType a, b; 273 Link *q = (Link *)malloc(sizeof(Link)); 274 while(pa && pb) 275 { 276 //pa,pb均不為空 277 a = GetCurElem(pa); 278 b = GetCurElem(pb);//a,b為兩表中待比較元素 279 if((* compare)(a, b) <= 0) 280 { 281 //a <= b 282 DelFirst(ha, q); 283 Append(Lc, *q); 284 pa = NextPos(La, ha); 285 } 286 else 287 { 288 //a > b 289 DelFirst(hb, q); 290 Append(Lc,*q); 291 pb = NextPos(Lb, hb); 292 } 293 } 294 if(pa) 295 Append(Lc, pa); 296 else 297 Append(Lc, pb); 298 FreeNode(ha); 299 FreeNode(hb); 300 return OK; 301 } 302 303 304 int cmp(term a, term b) 305 { 306 //根據a的指數值<(或=)(或>)b的指數值,分別返回-1,0,+1 307 if(a.expn < b.expn) 308 return -1; 309 else if(a.expn == b.expn) 310 return 0; 311 else 312 return 1; 313 } 314 315 316 void CreatePolyn(polynomial *P, int m) 317 { 318 //輸入m項的系數和指數,建立表示一元多項式的有序鏈表P 319 //最多能輸入m項,若輸入指數相同的項,則后輸入項會被丟棄 320 Position h; 321 Position *q = (Position *)malloc(sizeof(Position));//指針使用前一定要先初始化 322 Position *s = (Position *)malloc(sizeof(Position)); 323 term e; 324 int i; 325 InitList(P); 326 h = GetHead(P); 327 e.coef = 0.0; 328 e.expn = -1; 329 SetCurElem(h, e); 330 for(i = 1; i <= m; i++) 331 { 332 scanf("%f %d", &(e.coef), &(e.expn)); 333 if(!(LocateElem(P, e, q, cmp))) 334 { 335 //當前鏈表不存在該指數項 336 if(MakeNode(s, e))//生成節點並插入鏈表 337 InsFirst(*q, *s); 338 } 339 } 340 } 341 342 343 void PrintPolyn(polynomial *P) 344 { 345 //打印輸出一元多項式 346 Position p = P -> head -> next;//p指向鏈表P的第一個節點 347 int i = 1; 348 while(p) 349 { 350 if(i != 1) 351 printf(" + "); 352 printf("%fx^%d", p->data.coef, p->data.expn); 353 p = p->next; 354 i++; 355 } 356 printf("\n\n"); 357 } 358 359 360 void AddPolyn(polynomial *Pa, polynomial *Pb) 361 { 362 //完成多項式相加運算,即:Pa = Pa + Pb,並銷毀一元多項式Pb 363 term a, b; 364 int diff; 365 float sum; 366 Position *dp = (Position *)malloc(sizeof(Position));//*dp中用於保存被刪除節點的地址 367 Position ha = GetHead(Pa); 368 Position hb = GetHead(Pb);//ha,hb分別指向Pa,Pb的頭節點 369 Position qa = NextPos(Pa, ha); 370 Position qb = NextPos(Pb, hb);//qa,qb分別指向Pa,Pb的當前待處理結點 371 while(qa && qb) 372 { 373 //qa與qb均為非空 374 a = GetCurElem(qa); 375 b = GetCurElem(qb);//a,b為當前待比較元素 376 diff = cmp(a, b); 377 if(diff == -1) 378 { 379 //多項式Pa中當前結點的指數值小 380 ha = qa; 381 qa = NextPos(Pa, qa);//ha指向qa,qa往后走 382 } 383 else if(diff == 0) 384 { 385 sum = a.coef + b.coef; 386 if(sum != 0.0) 387 { 388 //修改多項式Pa中當前結點的系數值 389 a.coef = sum; 390 SetCurElem(qa, a);//教材此處有誤,第二個參數應為term類型 391 ha = qa;//此處為后面qa = NextPos(Pa, ha)做准備,使得當qa指向節點不被刪除時,ha即相當於qa 392 } 393 else 394 { 395 //刪除多項式Pa中當前結點 396 DelFirst(ha, dp);//此處使用dp,為了跟DelFirst的函數原型匹配,因此與教材寫法不同 397 FreeNode(*dp);//實際*dp的內容就是qa 398 } 399 DelFirst(hb,dp);//此處使用dp,為了跟DelFirst的函數原型匹配,因此與教材寫法不同 400 FreeNode(*dp);//實際*dp的內容就是qb 401 qb = NextPos(Pb, hb); 402 qa = NextPos(Pa, ha); 403 } 404 else 405 { 406 //多項式Pb中當前結點的指數值小 407 DelFirst(hb, dp);//此處使用dp,為了跟DelFirst的函數原型匹配,因此與教材寫法不同 408 InsFirst(ha, *dp);//將Pb的當前節點接在ha后面,實際*dp的內容就是qb 409 qb = NextPos(Pb, hb); 410 ha = NextPos(Pa, ha);//ha指向剛插入的節點,即*dp 411 } 412 }//while 413 if(!ListEmpty(Pb)) 414 Append(Pa, qb);//鏈接Pb中剩余節點 415 FreeNode(hb); 416 } 417 418 419 void Multpolyn(polynomial *Pa, polynomial *Pb) 420 { 421 //實現兩個一元多項式的乘法 422 float coef0 = 0.0; int expn0 = 0; ElemType a; 423 Link mid0 = NULL, mid1 = NULL, mid2 = NULL; 424 Link PaH = GetHead(Pa); 425 polynomial *pa = (polynomial *)malloc(sizeof(polynomial)); 426 polynomial *Pc = (polynomial *)malloc(sizeof(polynomial)); 427 polynomial *Pd = (polynomial *)malloc(sizeof(polynomial)); 428 429 PaH = NextPos(Pa, PaH);//PaH -> next 430 a = GetCurElem(PaH);//PaH->data 431 coef0 = a.coef; 432 expn0 = a.expn; 433 434 InitList(pa); InitList(Pc); InitList(Pd);//init 435 436 pa -> head -> data = GetCurElem(GetHead(Pa));//Pa ->head->data; 437 mid0 = NextPos(Pa, (GetHead(Pa)));//mid0 = Pa -> head->next 438 pa -> head -> next = NULL; 439 mid1 =GetHead(pa);//pa -> head; 440 while(mid0) 441 { 442 //完成Pa的copy 443 mid1 -> next = (Link)malloc(sizeof(NormLNode)); 444 mid1 = NextPos(pa,mid1);//mid1 -> next, 445 mid1 ->next = NULL; 446 mid1->data = GetCurElem(mid0); 447 //mid1 -> data.coef = mid0 -> data.coef, mid1 -> data.expn = mid0 -> data.expn; 448 mid0 = NextPos(Pa, mid0);//mid0 -> next; 449 } 450 pa -> tail = mid1, pa -> len = Pa -> len;//處理pa的尾結點和長度 451 452 mid0 = NextPos(Pa, GetHead(Pa));//Pa -> head -> next 453 while(mid0) 454 { 455 //完成Pa 與 Pb第一項相乘 456 mid0 -> data.coef = mid0 -> data.coef * coef0, mid0 -> data.expn = mid0 -> data.expn + expn0; 457 mid0 = NextPos(Pa, mid0);//mid0 -> next; 458 } 459 460 //完成后續工作 461 //mid0 = pa -> head -> next; 462 //mid1 = Pc -> head; 463 mid2 = NextPos(Pb,NextPos(Pb,GetHead(Pb)));//Pb -> head -> next -> next; 464 while(mid2) 465 { 466 mid1 = GetHead(Pc);//Pc -> head; 467 mid0 = NextPos(pa,GetHead(pa));//pa -> head -> next; 468 while(mid0) 469 { 470 mid1 -> next = (Link)malloc(sizeof(NormLNode)); 471 mid1 = NextPos(Pc, mid1);//mid1 -> next; 472 mid1 -> data.coef = mid0 -> data.coef * mid2 -> data.coef; 473 mid1 -> data.expn = mid0 -> data.expn +mid2 -> data.expn; 474 mid0 = NextPos(pa, mid0);//mid0 -> next; 475 } 476 mid1 -> next = NULL;//處理尾巴,否則Append()函數中while循環無法判定 477 Pc -> tail = mid1; 478 AddPolyn(Pa, Pc); 479 Pc = (polynomial *)malloc(sizeof(polynomial)); 480 InitList(Pc); 481 mid2 = NextPos(Pb, mid2);//mid2 -> next; 482 } 483 Pa -> len = ListLength(Pa); 484 } 485 486 487 int main() 488 { 489 /*******************************測試一元多項式加法*******************************/ 490 polynomial *Pa = (polynomial *)malloc(sizeof(polynomial)); 491 polynomial *Pb = (polynomial *)malloc(sizeof(polynomial)); 492 printf("分別輸入一個4項的多項式和一個3項的多項式\n"); 493 CreatePolyn(Pa, 4); 494 printf("Pa:\n"); 495 PrintPolyn(Pa); 496 CreatePolyn(Pb, 3); 497 printf("\nPb:\n"); 498 PrintPolyn(Pb); 499 AddPolyn(Pa, Pb); 500 printf("\nPa+Pb:\n"); 501 PrintPolyn(Pa); 502 DestroyList(Pa); 503 /*******************************測試一元多項式乘法*******************************/ 504 Pa = (polynomial *)malloc(sizeof(polynomial)); 505 Pb = (polynomial *)malloc(sizeof(polynomial)); 506 printf("分別輸入一個4項的多項式和一個3項的多項式\n"); 507 CreatePolyn(Pa, 4); 508 printf("Pa:\n"); 509 PrintPolyn(Pa); 510 CreatePolyn(Pb, 3); 511 printf("\nPb:\n"); 512 PrintPolyn(Pb); 513 printf("\nPa * Pb\n"); 514 Multpolyn(Pa, Pb); 515 PrintPolyn(Pa); 516 DestroyList(Pa); 517 return 0; 518 }
這么多行的代碼不容易啊,雖然里面還有好多函數還沒有實現,等待慢慢補充吧(雖然可能性不大,過段時間估計看着都頭疼了吧,還是要給自己個勇氣嘛)。
