Multiplication and addition of univariate polynomials in linked lists (C language)

Posted by s2j1j1b0 on Fri, 17 Dec 2021 10:25:24 +0100

Multiplication and addition of univariate polynomials in linked lists (C language)

Foreword

It is only implemented in C language

This one should be the most orderly one (that is, it doesn't look big), but it is the longest one.

subject

Design the function and find the product and sum of two univariate polynomials respectively.

Input format

The input is divided into 2 lines. In each line, the number of non-zero terms of the polynomial is given respectively, and then the coefficient and exponent of a non-zero term of the polynomial (the absolute value is an integer no more than 1000) are input in an exponential descending manner. The numbers are separated by spaces.

Output format

The output is divided into two lines, and the coefficients and exponents of product polynomials and non-zero terms of polynomials are output in an exponential descending manner respectively. Numbers are separated by spaces, but there must be no extra spaces at the end. Zero polynomial should output 0.

sample input

4 3 4 -5 2  6 1  -2 0
3 5 20  -7 4  3 1

sample output

15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1
5 20 -4 4 -5 2 9 1 -2 0

Program subject

#include <stdio.h>
#include <stdlib.h>

#define PRINTF_SPACE(X) (X == 1) ? (printf(" ")) : (X = 1)

//Structure definition of univariate polynomial linked list
typedef struct List_Node{
    int Coefficient;  //coefficient
    int Exponential;  //index
    struct List_Node *Next;
}L;

//Required action set
L *Create_List(int number);
L *Create_List_Node(L **last, int Coefficient, int Exponential);
L *Mult(L *s1, L *s2);
L *Add(L *s1, L *s2);
void *Simplification(L **s);
void Printf_List(L *s);
void Free_List(L *s);

int main(int argc, char const *argv[])
{
    //Read in the data of two univariate polynomials
    L *s1, *s2;
    int n1, n2;
    scanf("%d", &n1);
    s1 = Create_List(n1);
    scanf("%d", &n2);
    s2 = Create_List(n2);
    //Multiplication of two polynomials
    L *MultResult = Mult(s1, s2);
    Simplification(&MultResult);
    Printf_List(MultResult);
    //Add two polynomials
    L *AddResult = Add(s1, s2);
    Simplification(&AddResult);
    Printf_List(AddResult);
    
    return 0;
}

General idea

  1. Read in polynomials;
  2. Multiplication and addition (here, the results of multiplication and addition need to be simplified and sorted out further);
  3. Print the results.

Operation set

L *Create_List(int number);  //Create a linked list from scratch and return the head node pointer of the linked list (tail insertion method)
L *Create_List_Node(L **last, int Coefficient, int Exponential);  //Create a node and return the tail node pointer of the linked list
L *Mult(L *s1, L *s2);  //Multiply and return the head node pointer of the result linked list
L *Add(L *s1, L *s2);  //Add and return the head node pointer of the result linked list
void *Simplification(L **s);  //Simplify the polynomial, remove the zero term, and return the simplified chain header node pointer
void Printf_List(L *s);  //Print the whole linked list. If the input linked list is NULL, print "0"
void Free_List(L *s);  //Free up space for the entire linked list

Create_List function

Create a linked list from scratch and return the head node pointer of the linked list. Here, tail interpolation is used.

L *Create_List(int number)
{
    int Coefficient, Exponential;
    L *head, *last;
    head = last = NULL;
    while (number--)
    {
        scanf("%d%d", &Coefficient, &Exponential);
        Create_List_Node(&last, Coefficient, Exponential);
        if (head == NULL){
            head = last;
        }
    }
    return head;
}

Create_List_Node function

Create a node and return the tail node pointer of the linked list, which can be used to extend the linked list.

The secondary pointer passed in is to facilitate the extension of a single linked list, so it is only applicable to the single linked list with saved tail node address.

(in fact, you can not return the tail node)

The specific operation is to create a node and let the Next of the incoming tail node point to the new node. If the incoming is a null pointer, let the last point to p.

L *Create_List_Node(L **last, int Coefficient, int Exponential)
{
    L *last_ = *last;
    L *p = (L*)malloc(sizeof(L));
    p->Coefficient = Coefficient;
    p->Exponential = Exponential;
    p->Next = NULL;
    if (last_){
        last_->Next = p;
    }else{  //If last is empty, a linked list will be created
        last_ = p;
    }
    *last = p;
    return p;  //In fact, the operation of this step has been performed by the previous step
}

Add function

Realize the addition of two polynomials and return the result polynomial.

Main idea: by traversing the two linked lists at the same time, follow the "addition of coefficients of the same exponential term".

  1. If both nodes are not NULL, you need to compare whether the indices of the two nodes are the same.

    If yes, add the coefficients, create a new node, and make the two transition to the next node at the same time;

    Otherwise, compare the index size, create a node based on the data in the node with a large index, and make the large one equal to its next node.

  2. If one of them is NULL, the job of creating nodes is to copy the data of each node remaining in the non empty linked list.

L *Add(L *s1, L *s2)  //Add and return the head node pointer of the result linked list
{
    int Coefficient, Exponential;
    L *head, *last;
    head = last = NULL;
    while (s1 || s2)  //NULL is returned if both pointers entered are NULL pointers
    {
        if (s1 && s2){
            if (s1->Exponential == s2->Exponential){
                Coefficient = s1->Coefficient + s2->Coefficient;
                Exponential = s1->Exponential;
                s1 = s1->Next;
                s2 = s2->Next;
            }else if (s1->Exponential > s2->Exponential){
                Coefficient = s1->Coefficient;
                Exponential = s1->Exponential;
                s1 = s1->Next;
            }else{
                Coefficient = s2->Coefficient;
                Exponential = s2->Exponential;
                s2 = s2->Next;
            }
        }else if (s1){
            Coefficient = s1->Coefficient;
            Exponential = s1->Exponential;
            s1 = s1->Next;
        }else{
            Coefficient = s2->Coefficient;
            Exponential = s2->Exponential;
            s2 = s2->Next;
        }
        Create_List_Node(&last, Coefficient, Exponential);
        if (head == NULL){
            head = last;
        }
    }
    //Simplification(&head);  // In order to improve operation efficiency
    return head;
}

Mult function

Realize the multiplication of two polynomials and return the result polynomial.

Here, we use item by item multiplication and then addition, so the pre function needs to Add, although it is output first. Therefore, if Simplification is executed in each cycle, the time complexity will increase, so it will be independent.

Main idea: retrieve the term of one polynomial, and then multiply the term of this polynomial with each term of the other polynomial to obtain a new polynomial. The polynomials obtained in each cycle must be combined (i.e. added) with the polynomials obtained in the previous cycle. After this step, redundant space occupied by the linked list will be generated, which needs to be released immediately.

L *Mult(L *s1, L *s2)
{
    L *a1, *a2, *head, *last, *p;
    a1 = s1;
    head = last = p = NULL;
    int Coefficient, Exponential;
    while (a1)
    {
        a2 = s2;
        while (a2)  //Get a new polynomial linked list
        {
            Coefficient = a1->Coefficient * a2->Coefficient;
            Exponential = a1->Exponential + a2->Exponential;
            Create_List_Node(&last, Coefficient, Exponential);
            if (head == NULL){
                head = last;
            }
            a2 = a2->Next;
        }
        if (p){  //Merge the resulting polynomial linked list
            L *s = Add(p, head);  //If the simplification step is also in the Add function, the time complexity will become larger
            Free_List(p);
            Free_List(head);
            p = s;
        }else{
            p = head;
        }
        head = last = NULL;
        a1 = a1->Next;
    }
    //Simplification(&p);
    return p;
}

Simplification function

Simplify polynomial linked list

Idea: 1 Copy one item and compare it with the next item. If the coefficients are the same, add exponentially. Otherwise, copy the items to be compared, extend the new linked list, finally get the sorted linked list, and release the original UN simplified linked list.

​ 2. The second step is to find out whether there are terms with zero coefficients for the sorted polynomials, and delete the terms with zero coefficients.

void *Simplification(L **s)
{
    L *r = *s;
    if (r == NULL){
        return NULL;
    }
    int Coefficient, Exponential;
    L *head, *last, *p, *q;
    head = last = p = q = NULL;
    //Step 1: merge similar items
    do
    {
        if (last){
            if (last->Exponential == r->Exponential){
                last->Coefficient = last->Coefficient + r->Coefficient;
            }else{
                Create_List_Node(&last, r->Coefficient, r->Exponential);
            }
        }else{
            Coefficient = r->Coefficient;
            Exponential = r->Exponential;
            head = Create_List_Node(&last, Coefficient, Exponential);
        }
        p = r;
        r = r->Next;
        free(p);
        p = NULL;
    } while (r);
    //Step 2: sort out the items with a clearance factor of zero
    p = head;
    while (p){
        if (p->Coefficient == 0){
            if (q){
                q->Next = p->Next;
                free(p);
                p = q->Next;
            }else{
                head = p->Next;
                free(p);
                p = head;
            }
        }else{
            q = p;
            p = p->Next;
        }
    }
    *s = head;
}

Free_List function

This function is set to directly release an entire linked list.

void Free_List(L *s)
{
    while (s){
        L *p = s;
        s = s->Next;
        free(p);
        p  = NULL;
    }
}

Printf_List function

The function is to output the data in the polynomial linked list directly.

Macro PRINTF_SPACE is to add a space in the middle of each output result.

//#define PRINTF_SPACE(X) (X == 1) ? (printf(" ")) : (X = 1)

void Printf_List(L *s)
{
    if (s == NULL){
        printf("0 0");
    }else{
        for (int set = 0; s; s = s->Next)
        {
            PRINTF_SPACE(set);
            printf("%d %d", s->Coefficient, s->Exponential);
        }
    }
    printf("\n");
}

Topics: data structure