[数据结构]一元n次多项式的抽象数据类型

一、问题描述

一元n次多项式是代数学中经常出现的代数式,对于一元n次多项式的操作有很重要的实际意义。由于一个一元n次多项式最多有n+1项,且互不相关,所以可以用一个线性表来保存一个多项式,从前至后次数递增。对于一个一元n次多项式,我们可以定义操作:多项式的加法、减法、乘法。

本次小作业采用了链式表示的线性表实现,且只实现了多项式的加法。我认为如果要实现多项式的乘法,顺序表示的线性表更合适。

二、数据结构——线性表

1、链式表示:

链式表示的线性表,每个单位元由数据域和指针域组成,数据域保存当前结点的数值,而指针域保存的是下一个逻辑位置的地址,以便于通过这个指针访问下一个结点。与顺序表示相比,链式表示具有插入、删除灵活方便的特点,然而访问不方便,只能够从头指针处遍历。

2、顺序表示:

顺序表示的线性表,用一段物理存储上连续的空间模拟线性表,以物理上的位置的顺序关系,表示逻辑上的顺序关系。由于其物理地址的相近,所以在访问方便的同时,出现了两个麻烦:一是当一次申请的空间不够时,只能重新申请一段更大的空间,把之前的所有数据按顺序“搬”过去,否则无法保证其物理顺序的连续性;二是当线性表需要插入、删除操作时,需要对一部分数据进行“移位”操作,时间复杂度高。

3、基于本小作业对两种表示的对比分析:

此次作业是要求做两个一元n次多项式的加法,抽象到ADT上来看,就是两个线性表的分项加法,所以不涉及到结点的插入、删除操作,于是链式表示的优势被削弱,而顺序表示的劣势不那么明显了。相比较而言,两者的实现没什么区别,所以我选择了链式表示来实现。

更多地来想,如果需要做多项式的乘法,那么顺序表示就比链式表示的优势要大了。多项式乘法的算法核心可以大致说明为:LC(i+j-1) += LA(i)*LB(j)。这里涉及到寻找i+j-1位置的LC的值并进行修改的操作,如果使用顺序表示更方便找到该位置。

三、算法的设计及实现

(1)建立线性表LA和LB,并读入数据。

(2)将LB中的每一项按顺序逐项加到LA中对应的项。

(3)如果LB比LA长,则把LB中剩余元素按顺序依次加到LA中。

(4)最后得到的LA就是最终结果。

四、预期结果和实验中的问题

1、预期结果:

输入两个一元n次多项式的各项系数后,按照次数递增分别保存在LA和LB中,然后将LB中的每一项对应加在LA中。

如LA={1,2,3,4,5,6}表示fa(x)=1+2*x+3*x^2+4*x^3+5*x^4+6*x^5,LB={2,2,3}表示fb(x)=2+2*x+3*x^2,则得到的结果应该是{3,4,6,4,5,6}表示fa(x)+fb(x)=3+4*x+6*x^2+4*x^3+5*x^4+6*x^5。

2、实验中的问题:

除去线性表实现的一些细节问题以外,还有针对此次小作业的问题。

上面有提到的是,如果要实现多项式的乘法,若使用顺序表示的线性表,则可以直接遍历LA和LB,每一个合法位置执行LC(i+j-1) += LA(i)*LB(j)就可以了;而假如要使用链式表示的线性表来实现,如果继续按照顺序表示的方式来遍历LA和LB,这样处理LC的位置在不停地变动,查找该位置时间开销很大,所以可以选择遍历i+j-1的值,对于一个固定的i+j-1,通过遍历i求出j的值来计算LC(i+j-1)的值。

我也思考了多项式除法的问题,发现涉及到数论的一些结论,类似于高精度数除以高精度数,还没有比较好的处理方式。当然,带余除法是可以用LA一直减去LB直到0<LA<LB为止。

 

附:c++源代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 
  4 using namespace std;
  5 
  6 struct node
  7 {
  8     int Num;
  9     node *next;
 10 };
 11 
 12 class MyList
 13 {
 14 private:
 15     int Len;
 16     node *pHead;
 17 
 18 public:
 19     void InitList()//构造一个空的线性表
 20     {
 21         Len = 0;
 22         pHead = NULL;
 23     }
 24     void ClearList()//重置为空表
 25     {
 26         node *Tmp;
 27         while(pHead)
 28         {
 29             Tmp = pHead;
 30             pHead = pHead -> next;
 31             delete Tmp;
 32         }
 33         Len = 0;
 34     }
 35     bool ListEmpty()//判断L是否为空表
 36     {
 37         return pHead == NULL;
 38     }
 39     int ListLength()//返回L中数据元素个数
 40     {
 41         return Len;
 42     }
 43     bool GetElem(int Pos, int &e)//返回第Pos个元素,出错返回true
 44     {
 45         if(Pos < 1 || Pos > Len)
 46         {
 47             printf("Wrong position!\n");
 48             return true;
 49         }
 50         node *Cur = pHead;
 51         int Index = 0;
 52         while(++Index < Pos && Cur)
 53             Cur = Cur -> next;
 54         e = Cur -> Num;
 55         return false;
 56     }
 57     //LocateElem(L, e, compare())//返回L中第一个与e满足关系compare()的元素的位序,不存在返回0
 58     bool PriorElem(int e, int &Pre_e)//若e是L中的元素,返回e的前躯,失败时返回true
 59     {
 60         if(pHead -> Num == e)
 61         {
 62             printf("Cannot find the precursor!\n");
 63             return true;
 64         }
 65         node *Cur = pHead, *Prev;
 66         while(Cur)
 67         {
 68             if(Cur -> Num == e)
 69                 break;
 70             Prev = Cur;
 71             Cur = Cur -> next;
 72         }
 73         if(!Cur)
 74         {
 75             printf("Cannot find the element!\n");
 76             return true;
 77         }
 78         Pre_e = Prev -> Num;
 79         return false;
 80     }
 81     bool NextElem(int e, int &Next_e)//若e是L中的元素,返回e的后继,错误时返回true
 82     {
 83         node *Cur = pHead;
 84         while(Cur)
 85         {
 86             if(Cur -> Num == e)
 87                 break;
 88             Cur = Cur -> next;
 89         }
 90         if(!Cur)
 91         {
 92             printf("Cannot find the element!\n");
 93             return true;
 94         }
 95         Cur = Cur -> next;
 96         if(!Cur)
 97         {
 98             printf("Cannot find the successor!\n");
 99             return true;
100         }
101         Next_e = Cur -> Num;
102         return false;
103     }
104     bool ListInsert(int Pos, int e)//在Pos位置插入元素e,失败时返回true
105     {
106         if(Pos < 1 || Pos > Len + 1)
107         {
108             printf("Wrong position!\n");
109             return true;
110         }
111         node *InsElem = new node;
112         if(Pos == 1)
113         {
114             InsElem -> next = pHead;
115             pHead = InsElem;
116             InsElem -> Num = e;
117         }
118         else
119         {
120             node *Cur = pHead;
121             int Index = 0;
122             while(++Index + 1 < Pos && Cur)
123                 Cur = Cur -> next;
124             InsElem -> next = Cur -> next;
125             Cur -> next = InsElem;
126             InsElem -> Num = e;
127         }
128         Len++;
129         return false;
130     }
131     bool ListDelete(int Pos, int &e)//删除Pos位置的元素,用e返回,错误时返回true
132     {
133         if(Pos < 1 || Pos > Len)
134         {
135             printf("Wrong position!\n");
136             return true;
137         }
138         node *DelElem = pHead;
139         if(Pos == 1)
140         {
141             pHead = DelElem -> next;
142             e = DelElem -> Num;
143             delete DelElem;
144         }
145         else
146         {
147             node *Prev;
148             int Index = 0;
149             while(++Index < Pos && DelElem)
150             {
151                 Prev = DelElem;
152                 DelElem = DelElem -> next;
153             }
154             Prev -> next = DelElem -> next;
155             e = DelElem -> Num;
156             delete DelElem;
157         }
158         Len--;
159         return false;
160     }
161     //ListTraverse(L, visit())//依次对L中的每个数据元素调用函数visit(),一旦visit()失败,则操作失败
162     void PrintList()
163     {
164         if(ListEmpty())
165         {
166             printf("The List is empty!\n");
167             return ;
168         }
169         node *Cur = pHead;
170         int Index = 0;
171         while(++Index < Len && Cur)
172         {
173             printf("%d ",Cur -> Num);
174             Cur = Cur -> next;
175         }
176         printf("%d\n",Cur -> Num);
177     }
178     bool ElemPrio(node a, node b)
179     {
180         return a.Num < b.Num;
181     }
182     bool ChangeElem(int Pos, int El) //把Pos位置元素的值改为El,失败返回true
183     {
184         if(Pos < 1 || Pos > Len)
185         {
186             printf("Wrong position!\n");
187             return true;
188         }
189         node *Cur = pHead;
190         int Index = 0;
191         while(++Index < Pos && Cur)
192             Cur = Cur -> next;
193         Cur -> Num = El;
194         return false;
195     }
196     void MergeList(MyList Lb) //把Lb插入L中
197     {
198         int aElem, bElem, aIndex = 0;
199         while(aIndex < Len && (!Lb.ListEmpty()))
200         {
201             GetElem(++aIndex, aElem);
202             Lb.GetElem(1, bElem);
203             if(aElem > bElem)
204             {
205                 Lb.ListDelete(1, bElem);
206                 ListInsert(aIndex, bElem);
207             }
208         }
209         while(!Lb.ListEmpty())
210         {
211             Lb.ListDelete(1, bElem);
212             ListInsert(Len + 1, bElem);
213         }
214     }
215     void AddList(MyList Lb) //按项加法,把Lb往L中加
216     {
217         if(Lb.ListEmpty())
218             return ;
219         int bElem;
220         node *Cur = pHead;
221         while(Cur && (!Lb.ListEmpty()))
222         {
223             Lb.ListDelete(1, bElem);
224             Cur -> Num += bElem;
225             Cur = Cur -> next;
226         }
227         while(!Lb.ListEmpty())
228         {
229             Lb.ListDelete(1, bElem);
230             ListInsert(Len, bElem);
231         }
232     }
233     void PrintList_ForPolynomial()
234     {
235         if(ListEmpty())
236         {
237             printf("There is something wrong!\n");
238             return ;
239         }
240         node *Cur = pHead;
241         int Index = 0;
242         while(++Index < Len && Cur)
243         {
244             if(Index == 1)
245                 printf("%d + ", Cur -> Num);
246             else if(Index == 2)
247                 printf("%d * x + ", Cur -> Num);
248             else
249                 printf("%d * x^%d + ", Cur -> Num, Index - 1);
250             Cur = Cur -> next;
251         }
252         if(Index == 1)
253             printf("%d\n", Cur -> Num);
254         else if(Index == 2)
255             printf("%d * x\n", Cur -> Num);
256         else
257             printf("%d * x^%d\n", Cur -> Num, Index - 1);
258     }
259 };
260 
261 void Read(MyList &L)
262 {
263     int n, i, Elem;
264     L.InitList();
265     printf("Please input a number n.\n");
266     scanf("%d", &n);
267     printf("Please input n+1 numbers means a0+a1*x+a2*x^2+...+an*x^n.\n");
268     for(i = 1; i <= n + 1; i++)
269     {
270         scanf("%d", &Elem);
271         L.ListInsert(i, Elem);
272     }
273 }
274 
275 int main()
276 {
277     MyList La, Lb;
278     Read(La);
279     Read(Lb);
280     printf("La(x) = ");
281     La.PrintList_ForPolynomial();
282     printf("Lb(x) = ");
283     Lb.PrintList_ForPolynomial();
284     La.AddList(Lb);
285     printf("La(x) + Lb(x) = ");
286     La.PrintList_ForPolynomial();
287     return 0;
288 }
View Code

 

posted @ 2016-02-09 07:13  zyy是一只超级大沙茶  阅读(1719)  评论(0编辑  收藏  举报