Data Structure and Algorithm lab1-Harbin Institute of Technology


title: Data Structure lab1 - Algebraic Operations of Unary Polynomials
date: 2023-05-16 11:42:26
tags: Data Structure and Algorithm


Git address: https://github.com/944613709/HIT-Data-Structures-and-Algorithms

School of Computer Science and Technology, Harbin Institute of Technology

experimental report

Course Title: Data Structures and Algorithms

Course Type: Compulsory

Experimental project: Linked storage structure and application of linear tables

Experiment topic: Algebraic operations of polynomials in one variable

Experiment date: 2021.10.13

Class: 2003001

Student ID: 120L021011

Name: Shi Zhuofan

1. Purpose of the experiment

1. Grasp the characteristics of the sequential storage structure of the linear table and the realization of various basic operations of the linear table in the sequential storage structure.

2. Grasp the characteristics of the linear table chain storage structure and the realization of various basic operations of the linear table in the chain storage structure.

3. Focus on consolidating and understanding various operations and applications of linear tables on chained storage structures.

2. Experimental requirements and experimental environment

Experimental requirements:

Design the (dynamic or static) chain storage structure of the linear table, and realize the algebraic operation of the unary polynomial.

The unary polynomial is stored in a linked list, and the algebraic operation on the polynomial is completed on this basis.

1. Able to input polynomials (according to any input sequence of items, establish polynomials arranged in descending powers of exponents) and output polynomials (arranged in descending powers of exponents), input and output in file form, and display.

2. It can calculate the value of polynomial at a certain point x=x0, where x0 is a floating-point constant, and the return result is a floating-point number.

3. Able to calculate the result polynomial of addition, subtraction, multiplication and division of two polynomials. The result of division includes quotient polynomial and remainder polynomial.

4. It is required to minimize the space occupation of intermediate results of multiplication and division operations and the frequent allocation and recovery operations of nodes. (Hint: Use the circular linked list structure or the idea of ​​the available space table to return the polynomial represented by the circular linked list to the system or the available space table to solve the above problems).

lab environment:

Operating system: Win7/Win10

Integrated development environment: devcpp++

External library: no

3. Design ideas (definition of all data types used in this program, flow chart of the main program and the calling relationship between program modules)

1. Function function and external interface design

A total of 9 functions are designed in this system, and the function and interface design of each function are shown in the following table:

serial number Function name function function function parameters function return value
1 Main Execute each function according to order none none
2 ReadPoly Read the polynomials in In1.txt or In2.txt, and store them in the linked list in descending order FILE *ff Polynomial
3 Attach Insert a new node at the end of the linked list, assign coef and expon float c, int e, Polynomial* pRear NULL
4 Add Addition, store the result in the linked list, and return the header Polynomial P1, Polynomial P2 Polynomial
5 Sub Subtraction, store the result in the linked list, and return the header Polynomial P1, Polynomial P2 Polynomial
6 A lot Multiplication, store the result in the linked list, and return the header Polynomial P1, Polynomial P2 Polynomial
7 Divide Divide, print and output the result directly Polynomial P1, Polynomial P2 NULL
8 PrintPoly Print the screen and output the data to the file Out.txt according to the header of the linked list Polynomial P NULL
9 Calculated Calculate the result of Xo, print and output the result directly Polynomial P,float x NULL

2. The flow chart of the main program and the calling relationship between each program module

* Flow chart and calling relationship of program modules*img

img

* Detailed call relationship of each function *

img

img

imgimg

img

3. Definition of data type

typedef struct PolyNode *Polynomial;

struct PolyNode

{

**float coef; //** coefficient

**int expon; //** exponent

Polynomial link;

}PolyNode;

**(1)** Logic design

(1) Attach the inserted item into the current linked list

\1. Create a new node t and assign each value

\2. Tail insertion method to enter the linked list

(2) Read polynomials from a file

\1. Open the file

\2. Create the head node of the linked list

\3. Loop to create new nodes in turn, read in the coefficient and index of each item, and insert the linked list for the tail interpolation method Attach

\4. Remove blank header nodes

(3) addition

\1. Create a new link list head node, and tail pointer

\2. While loop until one of P1 or P2 is empty

2.1 For P with a large coefficient between the two, insert the P node into the linked list using Attach(P1->coef,P1->expon,&Rear);

2.2 For the same coefficient between the two

2.2.1 If the sum of the current coefficients of P1 and P2 is 0, there is no need to insert the linked list

2.2.2 If the sum of the current coefficients of P1 and P2 is not 0, insert the linked list Attach(P1->coef + P2->coef,P2->expon,&Rear);

3.while until P1 is empty, keep Attach(P1->coef,P1->expon,&Rear);

4.While until P2 is empty, continue Attach(P2->coef,P2->expon,&Rear);

5. Remove blank header nodes

(4) subtraction

\1. Create a new linked list head node, and tail pointer

\2. While loop until one of P1 or P2 is empty

2.1 For P with a large coefficient between the two, insert the P node into the linked list using Attach(P1->coef,P1->expon,&Rear);

2.2 For the same coefficient between the two

2.2.1 If the current coefficient difference between P1 and P2 is 0, there is no need to insert the linked list

2.2.2 If the current coefficient difference between P1 and P2 is not 0, insert, Attach((P1->coef)-(P2->coef),P1->expon,&Rear);

\3. While until P1 is empty Attach(P1->coef,P1->expon,&Rear)

\4. While until P2 is empty Attach(-(P2->coef),P2->expon,&Rear);

\5. Remove blank header nodes

(5) Multiplication

\1. If P1 or P2 is empty, return NULL, t1=P1, t2=P2

\2. Create a new linked list head node =P

\3. While until t1 is empty

(1) Assignment t2=P2, Rear=P

(2) While until t2 is empty

① Calculate the coefficient and exponent after the multiplication of the current t1 and t2 items

② While loop to find the position where the current multiplication result needs to be inserted

③ Case 1 is inserted at the end of the linked list, and Case 2 is inserted in the middle of the linked list (Rear->link==NULL||Rear->link->expon < e)

④ Case 3 (Rear->link->expon == e) can currently be merged

\1) If it is 0 after merging, there is no need to insert, and delete the node at the corresponding position

\2) Insert if not 0 after merging

(6) Division

a. Determine whether the divisor P2 is 0, if it is 0, division cannot be performed

b. Create a new link list head node, t1=P1, t2=P2

c. While looping

a) Calculate the exponent newe and coefficient newc of the term of the current quotient

b) If (P2->expon==0) when the divisor is a constant (x is the power of 0), it can be obtained only once, and the remainder polynomial must be 0. Directly attach Attach(newc, newe, &RearS); to insert the quotient item into the quotient polynomial. According to short division, Ptemp1 = Mult(RearS,P2), Ptemp1 = Sub(t1,Ptemp1); t1=Ptemp1; and end the loop break

c) If t1->expon < P2->expon has reached the end loop condition to break

d) Otherwise, the direct calculation will be Attach(newc,newe,&RearS); and the quotient item will be inserted into the quotient polynomial. According to short division, Ptemp1 = Mult(RearS,P2), Ptemp1 = Sub(t1,Ptemp1);t1=Ptemp1

(7) Calculate x0

a. While loop

a) sum+=(P->coef)*pow(x,P->expon);

b) P=P->link;

**(2)** Physical design

The expression is stored in a linked list. The node of the linked list is that each item in the expression is represented by PolyNode, coef is the coefficient, expon is the index, and link points to the next item

struct PolyNode

{

float coef;

int expon;

Polynomial link;

}PolyNode;

**4.** Test results

Test case 1:

F1 = 1x2-3x1+1x^0

F2 = 3x3-5x1+6x^0

img

img

img

img

Test case 2

F1=9x 2+0x 5-2x^2

F2=0x0+1x1

imgimgimgimg

**5. ** Experience and deficiencies

insufficient:

1. For data with a coefficient of 0 (such as 0x^4) that appears after addition, subtraction, multiplication, and division, the early stage did not consider whether to delete the node or keep it, resulting in confusion and unification in the later stage

Solution: Unify the data deletion node with a coefficient of 0, and then perform supplementary conditions in ReadPoly to prevent the output from being empty

2. For the first division function, space occupation and node deletion are too frequent

Solution: Merge the originally defined polynomials that can be merged into common ones, reducing a considerable part of redundant usage

Experience:

a. For a program, multiple test samples are required to find out the bugs existing in the program and the situation that is not currently considered. For example, the extreme situation in this program does not exist when the divisor polynomial is 0. For example, when the final output is 0x^0 The sign decision for is a special case

b. More attention should be paid to the occupation of space in the linked list and the release of nodes. There are many reused ones that can be deleted, and those with a coefficient of 0 can also be used without wasting nodes.

c. For tail interpolation and inserting a node in the middle, the codes used are common, and the two cases can be merged together.

6. Appendix: Source Code (with comments)

\#include<stdio.h>

\#include<stdlib.h>

\#include<math.h>

typedef struct PolyNode *Polynomial;

struct PolyNode

{

  float coef;

  int expon;

  Polynomial link;

}PolyNode;

Polynomial ReadPoly(FILE *ff);

void Attach(float c, int e, Polynomial* pRear);

Polynomial Add(Polynomial P1, Polynomial P2);

Polynomial Sub(Polynomial P1, Polynomial P2);

Polynomial Mult(Polynomial P1, Polynomial P2);

void PrintPoly(Polynomial P);

void Calulate(Polynomial P,float x);

void Divide(Polynomial P1, Polynomial P2);

void Sort(Polynomial P);

int main()

{

​    Polynomial P1,P2,P;

​    FILE *fp1=NULL;

​    FILE *fp2=NULL;

​    fp1= fopen("In1.txt","r");

​    fp2= fopen("In2.txt","r");

​    printf("            -------------------------------------------------------------------\n");

  printf("            |==================    一元多项式的运算    =================|\n");

  printf("            -------------------------------------------------------------------\n\n");

  printf("            |==================     1.相加(+)     =================|\n");

  printf("            |==================     2.相减(-)     =================|\n");

  printf("            |==================     3.相乘(*)     =================|\n");

  printf("            |==================     4.相除(/)     =================|\n");

  printf("            |==================     5.计算Xo(=)     =================|\n");

  int n;

  printf("请输入选择:");

  scanf("%d",&n);

  switch (n)

  {

  case 3:

​          P1 = ReadPoly(fp1);

​            P2 = ReadPoly(fp2);

​            P=Mult(P1,P2);

​          printf("f1*f2="); 

​            PrintPoly(P);

​            break;

​    case 1:

​          P1 = ReadPoly(fp1);

​            P2 = ReadPoly(fp2);

​            P=Add(P1,P2);

​            printf("f1+f2="); 

​            PrintPoly(P);

​            break;

​    case 4:

​          P1 = ReadPoly(fp1);

​            P2 = ReadPoly(fp2);

​            Divide(P1,P2);//除法 

​            break;

​    case 2:

​          P1 = ReadPoly(fp1);

​            P2 = ReadPoly(fp2);

​            P=Sub(P1,P2);

​            printf("f1-f2="); 

​            PrintPoly(P);

​            break;

​    case 5:

​            float x;

​            printf("请输入xo:");

​            scanf("%f",&x);

​            P1 = ReadPoly(fp1);

​            P2 = ReadPoly(fp2);

​            printf("f1(xo)=");

​            Calulate(P1,x);

​            printf("f2(xo)=");

​            Calulate(P2,x);

​    }

​    fclose(fp1);

​    fclose(fp2);

}

void PrintPoly(Polynomial P)

{

​    FILE *p;

​    if((p=fopen("Out.txt","a"))==NULL)

​    {

​        printf("文件打开失败");

​        exit(0);

​    }

​    fprintf(p,"当前结果为:"); 

  int flag = 0;  // 判断是否是开头

  int Emptyflag = 1 ;//标记是否最终结果是否一个没输出,如果是1->Empty则输出0x^0 

  if (!P)

  {

​    printf("NULL");//当结果是NULL,P就是NULL,用以观测是否会出现P==NULL

​    fprintf(p,"NULL");

​    return;

  }

  while (P)

  {

​      if(P->coef==0) //对于0x^2直接跳过不输出 

​      {

​          P = P->link;

​          continue;

​        }

​        if(P->coef>0&&flag==1)//flag==1 不是开头则就要考虑+符号 

​            {

​            printf("+");

​            fprintf(p,"+"); 

​            }

​    printf("%.2fx^%d ", (P->coef), P->expon);

​    fprintf(p,"%.2fx^%d ", (P->coef), P->expon);

​    Emptyflag=0;//输出有非0数据

​    P = P->link;

​    if(flag==0)

​        flag=1;

  }

  if(Emptyflag==1)//如果P结果全是 0x^2+0x^1则只输出为0x^0 

  {

​      printf("0.00x^0");//结果为0总得输出一个

​    fprintf(p,"0.00x^0");

​    }

  printf("\n");

  fprintf(p,"\n");

  fclose(p);

}

Polynomial Mult(Polynomial P1, Polynomial P2)

{

​    Polynomial P,t1,t2,t,Rear;

​    if(!P1||!P2)

​        return NULL;//防止P1或P2万一为NULL,报错提示 

​    t1=P1;

​    t2=P2;

​    float c;

​    int e;

​    P=(Polynomial)malloc(sizeof(PolyNode));

​    P->link=NULL;

​    while(t1)//固定P1中的某个,依次遍历P2每一个 

​    {

​        t2=P2;

​        Rear=P;

​        while(t2)//t2==NULL 停下 

​        {

​            c=t1->coef * t2->coef;

​            e=t1->expon + t2->expon;

​            while(Rear->link!=NULL&&Rear->link->expon > e)//利用降幂顺序 来while循环找到插入的对应位置 

​                Rear=Rear->link;

​            if(Rear->link==NULL||Rear->link->expon < e)//在结尾插入(Rear->link==NULL) 和 在中间插入,都可以归为插入 

​            {                      //(Rear->link->expon)在中间插入

​                t=(Polynomial)malloc(sizeof(PolyNode));

​                t->coef=c;

​                t->expon=e;

​                t->link=Rear->link;

​                Rear->link=t;

​            }

​            else if(Rear->link->expon == e)//发现插入的可以合并同类项 

​            {

​                if(c + Rear->link->coef !=0)//合并之后不是0 

​                {

​                    Rear->link->coef += c;

​                }

​                else if (c + Rear->link->coef ==0)//合并之后为0直接删除结点 

​                {

​                    Polynomial temp;

​                    temp=Rear->link;

​                    Rear->link=Rear->link->link;

​                    free(temp);

​                }

​            }

​            t2=t2->link;

​        }

​        t1=t1->link;

​    }

​    t=P;

​    P=P->link;

​    free(t);

​    return P;

}

Polynomial Add(Polynomial P1, Polynomial P2)

{

​    Polynomial P,Rear,t;

​    P=(Polynomial)malloc(sizeof(PolyNode));

​    P->link=NULL;

​    Rear=P;


​    while(P1&&P2)//从两个多项式依照降幂顺序,找指数高的开始 

​    {

​        if((P1->expon) > (P2->expon) )

​        {

​            Attach(P1->coef,P1->expon,&Rear);

​            P1=P1->link;

​        }

​        else if ((P1->expon) < (P2->expon))

​        {

​            Attach(P2->coef,P2->expon,&Rear);

​            P2=P2->link;

​        }

​        else

​        {   

​            if(P1->coef + P2->coef!=0)

​            {

​            Attach(P1->coef + P2->coef,P2->expon,&Rear);

​            P1=P1->link;

​            P2=P2->link;

​            }

​            else//coef = = 0

​            {

​            P1=P1->link;

​            P2=P2->link;

​            }//一旦系数为0都不存入结点 

​        }

​    }

​    while(P1)

​        {Attach(P1->coef,P1->expon,&Rear);

​            P1=P1->link;

​        }

​    while(P2)

​        {Attach(P2->coef,P2->expon,&Rear);

​            P2=P2->link;

​        }

​    t=P;

​    P=P->link;

​    free(t);

​    if(!P)

​    {

​        P=(Polynomial)malloc(sizeof(PolyNode));

​        P->link=NULL;

​        P->coef =0;

​        P->expon =0;

​    }//当结果为0时候防止P==NULL,不妨将新建结点,数据为0x^0

​    return P;

}

Polynomial Sub(Polynomial P1, Polynomial P2) //P1-P2  

{

​    Polynomial P,Rear,t;

​    P=(Polynomial)malloc(sizeof(PolyNode));

​    P->link=NULL;

​    Rear=P;

​    while(P1&&P2)

​    {

​        if((P1->expon) > (P2->expon) )//按照降幂这么放入P 

​        {

​            Attach(P1->coef,P1->expon,&Rear);

​            P1=P1->link;

​        }

​        else if ((P1->expon) < (P2->expon))

​        {

​            Attach(-(P2->coef),P2->expon,&Rear);

​            P2=P2->link;

​        }

​        else if ((P1->expon) == (P2->expon))

​        {   

​            if((P1->coef) -(P2->coef) == 0)

​            {

​                P1=P1->link;

​                P2=P2->link;

​            }

​            else

​            {

​                Attach((P1->coef)-(P2->coef),P1->expon,&Rear);

​                P1=P1->link;

​                P2=P2->link;

​            }

​        }

​    }

​    while(P1)

​        {Attach(P1->coef,P1->expon,&Rear);

​            P1=P1->link;

​        }

​    while(P2)

​        {Attach(-(P2->coef),P2->expon,&Rear);

​            P2=P2->link;

​        }

​    t=P;

​    P=P->link;

​    free(t);

​    if(!P)

​    {

​        P=(Polynomial)malloc(sizeof(PolyNode));

​        P->link=NULL;

​        P->coef =0;

​        P->expon =0;

​    }//当结果为0时候防止P==NULL,不妨将新建结点,数据为0

​    return P;

}

 

void Attach(float c, int e, Polynomial* pRear)

{

​    Polynomial t;

​    t=(Polynomial)malloc(sizeof(PolyNode));

​    t->coef=c;

​    t->expon=e;

​    t->link=NULL;

​    (*pRear)->link=t;//利用尾插法,当然要将尾结点指向更新,*pRear才能修改尾结点自己地址 

​    *pRear=t;

}

Polynomial ReadPoly(FILE *ff)

{

​    int exp;

​    float coe;

​    char ch;

​    Polynomial P,Rear,t,Head;

​    P=(Polynomial)malloc(sizeof(PolyNode));

​    P->link=NULL;

​    Rear=P;

  ch = fgetc(ff);

  if(ch==EOF)//看txt文本是否为空 

  {

​      printf("ERROR: In.txt输入为空");

​        exit(0);

​    }

  if(ch!='-')//3x^2+3x^1这种首项第一个不会带有+,特殊情况 

  {

​      rewind(ff);

​      fscanf(ff,"%fx^%d",&coe,&exp);

​      Attach(coe,exp,&Rear);

​    }

​    else//ch='-'

​    {

​        fscanf(ff,"%fx^%d",&coe,&exp);

​        Attach((-coe),exp,&Rear);

​    }

​    while(fscanf(ff,"%c%fx^%d",&ch,&coe,&exp)!=EOF)//开始按照降幂插入 

​    {

​        if(ch=='-')//如果是符号要调整coe 

​            coe=-coe;


​        Head=P;

​        while(Head->link!=NULL&&Head->link->expon > exp ) //

​            Head=Head->link;

​        if(Head->link==NULL||Head->link->expon < exp)

​            {

​                t=(Polynomial)malloc(sizeof(PolyNode));

​                t->coef=coe;

​                t->expon=exp;

​                t->link=Head->link;

​                Head->link=t;

​            }

​        else if(Head->link->expon == exp)

​            {

​                if(coe + Head->link->coef !=0)

​                {

​                    Head->link->coef += coe;

​                }

​                else if (coe + Head->link->coef ==0)

​                {

​                    t=Head->link;

​                    Head->link=Head->link->link;

​                    free(t);

​                }//对于0x^2这种数据直接删掉结点 

​            }

​    }

​    t=P;

​    P=P->link;

​    free(t);

​    printf("f(x)=");

​    PrintPoly(P);

​    return P;//若In.txt为空则输出0x^0 

}

void Calulate(Polynomial P,float x)

{

​    FILE *p;

​    if((p=fopen("Out.txt","a"))==NULL)

​    {

​        printf("文件打开失败");

​        exit(0);

​    }

​    float sum;

​    sum=0;

​    while(P)

​    {

​        sum+=(P->coef)*pow(x,P->expon);

​        P=P->link;

​    }

​    printf("%f",sum);

​    fprintf(p,"代入Xo之后等于:%f",sum);

​    fclose(p);

​    printf("\n");

}

void Divide(Polynomial P1, Polynomial P2)//p1 / p2 

{

​    Polynomial PS,t1,t2,RearS,Ptemp1,t;

​    PS=(Polynomial)malloc(sizeof(PolyNode));//商多项式 

​    PS->link=NULL;

​    RearS=PS;//用来存储

​    t1=P1;

​    t2=P2;

​    if(P2->coef==0&&P2->expon==0)//当除数时0,数学公式不成立

​        {

​            printf("ERROR:P2不能为0");

​            exit(0);

​        }

​    float newc; 

​    int newe;

​    while(1)//进入循环

​    {

​        if(P2->expon==0)//特殊情况,当除数是常数(x是0次方)只需要出一次就能够得到,且余数多项式一定为0 

​            {

​            newe=t1->expon - P2->expon;//本次依次得到的商的一个项的指数 

​            newc=t1->coef / P2->coef;//本次依次得到的商的一个项的系数

​            Attach(newc, newe, &RearS);//将当前项,加入到商多项式

​            Ptemp1 = Mult(RearS,P2);//PP1*P2 = Ptemp,除法公式用到的 

​        Ptemp1 = Sub(t1,Ptemp1);//除法公式用到的 

​        t1=Ptemp1;//再次进行,当前短除法之后得到的余数多项式(不一定是最终的余数),成为新的t1,继续试探 

​        break;

​            }

​      if(t1->expon < P2->expon)

​        {

​            //已经完成商多项式 余数多项式

​            //t1就是最终余数多项式

​            break;//终止循环唯一条件

​        }

​        else//需要继续除 

​        {

​            newe=t1->expon - P2->expon;//本次依次得到的商的一个项的指数 

​            newc=t1->coef / P2->coef;//本次依次得到的商的一个项的系数

​            Attach(newc, newe, &RearS);//将当前项,加入到商多项式

​            Ptemp1 = Mult(RearS,P2);//PP1*P2 = Ptemp

​        Ptemp1 = Sub(t1,Ptemp1);

​        t1=Ptemp1;//再次进行,当前短除法之后得到的余数多项式(不一定是最终的余数),成为新的t1,继续试探 

​        }

​    }

​    t=PS;

​    PS=PS->link;

​    free(t);//删掉PS空白头结点 

​    if(!PS)//对于0/9x = 0 ..9x  此时防止商为空 

​    {

​    PS=(Polynomial)malloc(sizeof(PolyNode));//商多项式 

​    PS->link=NULL;

​    PS->coef = 0;

​    PS->expon = 0;

​    }

​    printf("余数多项式:");

​    PrintPoly(t1);//开始输出余数多项式 

​    printf("商多项式:");

​    PrintPoly(PS);//已经完成输出商多项式 

}

 

Guess you like

Origin blog.csdn.net/qq_35798433/article/details/130701886