多項式加減乘相對直觀,但**除法**涉及試商、乘減、遞迴/迴圈處理餘式,邏輯較複雜,教材常略過。本文提供基於**單向鏈表**儲存多項式(按指數遞減序),模擬手算「長除法」流程的完整 C 語言實現。
typedef struct LinkList {
float coef; // 係數
int expn; // 指數
struct LinkList *next; // 指向下一項(指數更低)
} LinkList, *PLink;
coef=expn=0 不存實際資料。expn **從大到小** 排序,便於對齊同次項運算。模擬手算步驟:
coef_q, expn_q)。GetMaxPLink GetMax(PLink p) {
PLink q = p->next;
if (!q) return NULL; // 空多項式
while (q->next) q = q->next; // 遍歷至尾部 (因按指數遞減,尾部為最高次? 待確認)
// 注意:原代碼建立時插在頭結點後,若輸入「從大到小」,則鏈表順序為「小到大」。
// GetMax 遍歷到 next==NULL 即為最後輸入者(指數最小?)。
// **修正**:若輸入要求「從大到小」,且用 头插法 (s->next=(*p)->next; (*p)->next=s),則鏈表實際存儲順序為「指數遞增」。
// 此時 GetMax 應遍歷至尾部獲取最大指數。原代碼邏輯自洽。
return q;
}
SubPolyn (核心難點)合併同次項,係數相減;刪除係數為 0 的節點;處理多項式長度不同。
void SubPolyn(PLink *p1, PLink p2) {
PLink qa = (*p1)->next, ha = *p1; // ha 為 qa 前驅
PLink qb = p2->next, hb;
while (qa && qb) {
switch (cmp(qa->expn, qb->expn)) {
case -1: // qa 指數較小 (在後) -> 保留 qa,前進
ha = qa; qa = qa->next; break;
case 0: // 同次項 -> 係數相減
qa->coef -= qb->coef;
if (qa->coef != 0) ha = qa;
else Del(&ha, qa); // 係數為 0 刪除節點
qa = ha->next; qb = qb->next; break;
case 1: // qb 指數較小 (p2 有 p1 無的項) -> 複製 qb 到 p1 (係數取負)
hb = (PLink)malloc(sizeof(LinkList));
hb->coef = -qb->coef; hb->expn = qb->expn;
Ins(&ha, hb); // 插入 ha 之後
qb = qb->next; ha = ha->next; break;
}
}
if (qb) Append(&ha, qb); // p2 剩餘項全取負加入 p1
// 原代碼此處有額外遍歷將 ha 後所有項取負,屬於邏輯重複/修正,需視具體插入邏輯而定。
}
DevPolynvoid DevPolyn(PLink *p1, PLink *p2) {
PLink res = (PLink)malloc(sizeof(LinkList)); // 商多項式頭結點
res->coef = res->expn = 0; res->next = NULL;
// 迴圈條件:被除數非零 且 被除數最高次 >= 除數最高次
while (GetMax(*p1) && GetMax(*p1)->expn >= GetMax(*p2)->expn) {
// 1. 計算商項
PLink max1 = GetMax(*p1), max2 = GetMax(*p2);
float coef_q = max1->coef / max2->coef;
int expn_q = max1->expn - max2->expn;
// 2. 複製除數
PLink temp_divisor = (PLink)malloc(sizeof(LinkList));
temp_divisor->coef = temp_divisor->expn = 0; temp_divisor->next = NULL;
AddPolyn(&temp_divisor, *p2); // temp_divisor = p2 的副本
// 3. 遍乘副本
PLink q = temp_divisor->next;
while (q) { q->coef *= coef_q; q->expn += expn_q; q = q->next; }
// 4. 插入商項到結果
PLink term = (PLink)malloc(sizeof(LinkList));
term->coef = coef_q; term->expn = expn_q; term->next = NULL;
Ins(&res, term); // 注意:Ins 是頭插,商多項式順序會反轉,最終輸出需注意或用 Append
// 5. 被除數減去乘積
SubPolyn(p1, temp_divisor);
Destroy(&temp_divisor);
}
// 結果輸出調整:原代碼將 p1 指向商,p2 指向餘數
PLink temp1 = *p1; *p1 = res; *p2 = temp1; Destroy(p2的舊頭?); // 細節見完整代碼
}
#include
#include
#include
typedef struct LinkList { float coef; int expn; struct LinkList *next; } LinkList, *PLink;
void CreatePolyn(PLink *p); void PrintPolyn(PLink p); void DevPolyn(PLink *, PLink *);
void AddPolyn(PLink *, PLink); void SubPolyn(PLink *, PLink); void Ins(PLink *, PLink);
void Append(PLink *, PLink); void Destroy(PLink *); PLink GetMax(PLink); int cmp(int, int);
int main() {
PLink p1 = (PLink)malloc(sizeof(LinkList));
PLink p2 = (PLink)malloc(sizeof(LinkList));
p1->next = p2->next = NULL; p1->coef=p1->expn=p2->coef=p2->expn=0;
printf("建立被除數:\n"); CreatePolyn(&p1); PrintPolyn(p1);
printf("\n建立除數:\n"); CreatePolyn(&p2); PrintPolyn(p2);
DevPolyn(&p1, &p2);
printf("\n=== 商 ===\n"); PrintPolyn(p1);
printf("\n=== 餘數 ===\n"); PrintPolyn(p2);
Destroy(&p1); Destroy(&p2);
return 0;
}
// ... 其他輔助函數 (CreatePolyn, PrintPolyn, cmp, Del, Ins, Append, Destroy, GetMax, AddPolyn, SubPolyn, DevPolyn) 實現略,邏輯同上文解析 ...
輸入被除數: 3 項 -> 2x^3 + 3x^2 + 4x^1 + 5x^0 (假設輸入 4 項)
輸入除數: 2 項 -> 1x^1 + 1x^0
輸出:
商: 2.0x^2 + 1.0x^1 + 3.0x^0
餘數: 2.0x^0
驗證: (x+1)(2x^2+x+3) + 2 = 2x^3+2x^2+x^2+x+3x+3+2 = 2x^3+3x^2+4x+5 ✓
GetMax 遍歷 O(n),SubPolyn O(m+n)。可優化:維護尾指標或雙向鏈表使 GetMax 為 O(1)。float 易產生誤差。高精度需求應改用 double 或分數結構體(分子/分母)。malloc/free 產生碎片。可引入記憶體池或靜態陣列模擬鏈表。coef[degree+1] 效率更高。本實現完整展示了鏈表模擬多項式長除法的經典教學級代碼。雖非工業級高效實現,但清晰演示了「試商-遍乘-相減-迭代」的核心邏輯,是理解多項式運算與鏈表綜合應用的優秀案例。