下面来讲解下一元多项式,第一个问题,我们为什么不用线性表,我们知道栈区是很小的,很多编译器都默认1MB左右,如下面的代码:

#include <stdio.h>

int main()
{
	char arr[1024*1024];
	return 0;
}



这时的运行结果为:

一元多项式的相加相减相乘 java 一元多项式求和代码_数据结构

上面提示 Stack Overflow,也就是栈溢出,所以当我们要存S(x)=1+3*x^9999999+2*x^999999999999

这类很大指数的数据时,第一是浪费很多空间,第二是很有可能会栈溢出。

所以一般用线性链表来表示。

比如表示A(x)=7+3*x+9*x^8+5*x^17和B(x)=8*x+22*x^7-9*x^8,这时用链表可以节省很多空间(堆区很大的)

如下图所示:

一元多项式的相加相减相乘 java 一元多项式求和代码_栈_02

我们还是先来说明下一元多项式相加的运算规则:对于两个一元多项式中所有指数相同的项,对应系数相加,若其和不为0,则构成“和多项式”中的一项;对于两个一元多项式中的所有指数不相同的项,则分别复抄到“和多项式”中去。


这里我们对上面那个A(x)=7+3*x+9*x^8+5*x^17和B(x)=8*x+22*x^7-9*x^8做和运算说明下:

看那个节点多,节点少的插入节点多的那个链,相同的话,随便。

A(x)=7+3*x+9*x^8+5*x^17和B(x)=8*x+22*x^7-9*x^8这个相加如下图所示:

一元多项式的相加相减相乘 java 一元多项式求和代码_线性表_03

下面来看指数的比较:

代码如下:

int Compare(PElemType a, PElemType b) {
  if (a.expn<b.expn) return -1;
  if (a.expn>b.expn) return 1;
  return 0;
}


分析如下:

这里的expn为指数(接下来的代码有coef这个是系数)。但a>b则返回-1,a<b返回1,相等时返回0



下面是创建一个多项式。

代码如下:

void CreatPolyn(PLinkList &P, int m) {  
  // 输入m项的系数和指数,建立表示一元多项式的有序链表P
  PLink h, q, s;
  PElemType e;
  int i;
  InitList(P);   h = GetHead(P);
  e.coef = 0.0;  e.expn = -1;
  SetCurElem(h,3);	//设置头结点的数据元素
  for(i=1;i<=m;++i)
  {
	scanf(e.coef,e.expn);
	if(!LocateElem(P,e,q,(*cmp)()))//是否存在该指数项
	{
		if(MakeNode(s,e))//生成节点
			InsFirst(q,s);	//插入
	}
  }
} // CreatPolyn




我们来分析下:

1.m为要输入的相数。

2.InitList为初始化链表,SetCurElem如注释所示。

3.这个代码的思路是从键盘输入项,但如果输入两次相同指数的话,就有第一次输入有效。




算法2.22:

多项式加法:Pa=Pa+Pb,利用两个多项式的结点构成“和多项式”。

void AddPolyn(PLinkList &Pa, PLinkList &Pb) {
  // 多项式加法:Pa = Pa+Pb,利用两个多项式的结点构成"和多项式"。
  PLink ha,hb,qa,qb;
  PElemType a, b, temp;
  float sum;
  ha = GetHead(Pa);      // ha和hb分别指向Pa和Pb的头结点
  hb = GetHead(Pb);
  qa = NextPos(Pa,ha);   // qa和qb分别指向La和Lb中当前结点
  qb = NextPos(Pb,hb);
  while (qa && qb) {     // Pa和Pb均非空
    a = GetCurElem (qa); // a和b为两表中当前比较元素
    b = GetCurElem (qb);
    switch (Compare(a,b)) {
      case -1:  // 多项式PA中当前结点的指数值小
          ha = qa;
          qa = NextPos (Pa, qa);
          break;  
      case 0:   // 两者的指数值相等
          sum = a.coef + b.coef ;
          if (sum != 0.0) {  // 修改多项式PA中当前结点的系数值
            temp.coef=sum;
            temp.expn=a.expn;
            SetCurElem(qa, temp) ;
            ha = qa;
          } else {  // 删除多项式PA中当前结点
            DelFirst(ha, qa);
            FreeNode(qa);
          }
          DelFirst(hb, qb);
          FreeNode(qb);
          qb = NextPos(Pb, hb);
          qa = NextPos(Pa, ha);
          break;
      case 1:   // 多项式PB中当前结点的指数值小
          DelFirst(hb, qb);
          InsFirst(ha, qb); 
          qb = NextPos(Pb, hb);
          ha = NextPos(Pa, ha);
          break;
    } // switch
  } // while
  if (!Empty(Pb)) Append(Pa, qb);   // 链接Pb中剩余结点
  FreeNode(hb);  // 释放Pb的头结点
} // AddPolyn


下面来分析下:

这个代码涉及很多函数并且书中都没提及,下面我只说下思路,用两个指针指向两个链表头,又用两个指针,分别指向两个链表第一个节点。这个功能是保留Pa的链,在case -1 里面,当发现Pa和Pb的指数不一样时(这里是Pa的指数小,所以Pa后移,移到Pa和Pb指数一样为止),case 0,就是合并,case 1,就是把Pb当前节点给Pa,最后当qa也就是Pa链到结尾,但Pb还没到链尾时,把Pb直接附加到Pa上。这就是整体思路。