数据结构学习笔记(二)多项式加法与乘法

来源:互联网 发布:知乎怎么增加 编辑:程序博客网 时间:2024/05/18 22:17

之前自己看书学链表、栈、队列,觉得比较难懂,还是得自己动手实践下。这次就是实现一个多项式的加法和乘法运算,主要是要求熟练链表的各种操作。
看看程序的大体框架是:

  1. 设计数据结构:多项式的表示。可以用数组和链表。数组需事先确定数组大小,链表则对动态操作比较有利。

  2. 读多项式:这里需要设计一个attach函数,是用来将新的结点插入链尾的。

  3. 加法实现:多项式相加其实就是比较指数,相同则合并同类项,不同则直接插入到结果链表。

  4. 乘法实现:乘法实现比较复杂。大致的思路就是其中一个多项式的每一项与另一个多项式的每一项相乘。可以先将p1的第一项与p2的各项相乘得到一个初始的p,然后再双重循环P1 p2,系数相乘指数相加,再插入到初始链表的适当位置。由于原来的链表是按指数递减排列的,只要比较指数大小就可以找到适当的插入位置的。当然其中还有很多细节问题需注意。

  5. 多项式输出:输出用循环,链表指针依次后移就行。

代码实现:

#include <cstdio>#include <cstdlib>#include <iostream>typedef int Type;typedef struct PolyNode *PolyNomial;struct PolyNode {  Type coef;  Type expo;  PolyNomial link;};//多项式读入函数void attach(Type e, Type c, PolyNomial *PtrRear) {  /*注意这里PtrRear实际上是指针的指针,为什么这么做呢?由于在本函数中要改变d当前结果表达式尾指针的值,  所以函数传递进来的是结点指针的地址,*PtrRear指向尾项*/  /*因为c语言中函数参数传递要改变参数值应采用传址方式*/  PolyNomial P;  P = (PolyNomial)malloc(sizeof(struct PolyNode));  P->coef = c;  P->expo = e;  P->link = NULL;  (*PtrRear)->link = P;  (*PtrRear) = P;}PolyNomial ReadPloy() {  int N, c, e;  PolyNomial P, Rear, t;  //生成一个头节点来使Rear指向它  P = (PolyNomial)malloc(sizeof(struct PolyNode));  P->link = NULL;  Rear = P;  scanf("%d", &N);  while (N--) {    scanf("%d%d", &c, &e);    attach(e, c, &Rear);  }  //删除临时生成的头节点  t = P;  P = P->link;  free(t);  return P;}PolyNomial Add(PolyNomial P1, PolyNomial P2) {  PolyNomial t1, t2, P, Rear;  t1 = P1;  t2 = P2;  P = (PolyNomial)malloc(sizeof(struct PolyNode));  P->link = NULL;  Rear = P;  while (t1 && t2) {    if (t1->expo == t2->expo) {      attach(t1->expo, t1->coef + P2->coef, &Rear);      t1 = P1->link;      t2 = P2->link;    } else if (t1->expo > t2->expo) {      attach(t1->expo, t1->coef, &Rear);      t1 = t1->link;    } else {      attach(t2->expo, t2->coef, &Rear);      t2 = t2->link;    }  }  while (t1) {    attach(t1->expo, t1->coef, &Rear);    t1 = t1->link;  }  while (t2) {    attach(t2->expo, t2->coef, &Rear);    t2 = t2->link;  }  return P;}PolyNomial Multi(PolyNomial P1, PolyNomial P2) {  PolyNomial t1, t2, P, Rear, t;  int c, e;  P = (PolyNomial)malloc(sizeof(struct PolyNode));  P->link = NULL;  Rear = P; // Rear指向头节点  t1 = P1;  t2 = P2;  //边界条件:如果两个多项式中有一个为空,则相乘结果为0  if (!t1 || !t2)    return NULL;  //先让p1的第一项与p2的所有项相乘,得到初始的P  while (t2) {    attach(t1->expo + t2->expo, t1->coef * t2->coef, &Rear);    t2 = t2->link;  }  t1 = t1->link;  //让p1的第一项后的所有项分别与p2相乘  while (t1) {    t2 = P2; //注意没循环一遍要使指针回到表首节点    Rear = P;    while (t2) {      c = t1->coef * t2->coef;      e = t1->expo + t2->expo;      //插入初始链表的适当位置,指数大于则继续寻找,相等则合并,小于则插入      while (Rear->link && Rear->link->expo > e) {        Rear = Rear->link;        if (Rear->link && Rear->link->expo == e) {          if (Rear->link->coef + c)            Rear->link->coef += c;          else {            t = Rear->link;            Rear->link = t->link;            free(t);          }        } else {          //生成新节点插入之          t = (PolyNomial)malloc(sizeof(struct PolyNode));          t->link = NULL;          t->coef = c;          t->expo = e;          t->link = Rear->link;          Rear->link = t;          Rear = Rear->link;        }      }      t2 = t2->link;    }    t1 = t1->link;  }  t2 = P;  P = P->link;  free(t2);  return P;}void PrintPoly(PolyNomial P) {  int flag = 0;  if (!P) {    printf("0 0");    return;  }  while (P) {    if (!flag)      flag = 1;    else      printf(" ");    printf("%d%d", P->coef, P->expo);    P = P->link;  }}int main() {  PolyNomial P1, P2, Psum, Pmulti;  P1 = ReadPloy();  P2 = ReadPloy();  Psum = Add(P1, P2);  Pmulti = Multi(P1, P2);  PrintPoly(Pmulti);  printf("\n");  PrintPoly(Psum);  return 0;}

需要特别注意的地方:

代码实现的过程中有很多细枝末节需要注意:

  • 在循环过程中指针遍历完了重新循环记得要将指针重新指向表首节点(好吧,书上说表头节点与表首节点是不同的)
  • 还有attach()函数中Rear 这个指针的传递,代码注释里说明的很清楚了。

  • 一般将新节点插入链表中都要先生成,再插入。

  • Multi() 函数中,将新节点插入有序链表中,注意算法思想。插入时应当清楚插入点是在指针的后面一个节点还是前面一个节点。这个函数里,如下图:
    这里写图片描述
    指针位于前面,则插入算法的关键语句应这样写:
    t->link = Rear->link;
    Rear->link = t;
    Rear = Rear->link;
0 0
原创粉丝点击