1. 程式人生 > 其它 >資料結構 - 連結串列 - 一元多項式

資料結構 - 連結串列 - 一元多項式

採用連結串列形式實現一元多項式資料結構,對該結構最重要的一個操作是一元多項式相乘

一元多項式相乘

 要求採用連結串列形式,求兩個一元多項式的乘積:\(h_3 = h_1 * h_2\)。函式原型為:void multiplication( NODE * h1, NODE * h2, NODE * h3 )

輸入格式

輸入資料為兩行,分別表示兩個一元多項式。每個一元多項式以指數遞增的順序輸入多項式各項的係數(整數)、指數(整數)。

例如:\(1+2x+x^2\) 表示為:<1,0>,<2,1>,<1,2>,

輸出格式

指數遞增的順序輸出乘積: <係數,指數>,<係數,指數>,<係數,指數>,

零多項式的輸出格式為:<0,0>,

預置程式碼

/* PRESET CODE BEGIN - NEVER TOUCH CODE BELOW */

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

typedef struct node
{   int    coef, exp;
    struct node  *next;
} NODE;

void multiplication( NODE *, NODE * , NODE * );
void input( NODE * );
void output( NODE * );

void input( NODE * head )
{   int flag, sign, sum, x;
	char c;

    NODE * p = head;

	while ( (c=getchar()) !='\n' )
	{
		if ( c == '<' )
	    {    sum = 0;
	         sign = 1;
	         flag = 1;
        }
		else if ( c =='-' )
             sign = -1;
		else if( c >='0'&& c <='9' )
		{    sum = sum*10 + c - '0';
        }
		else if ( c == ',' )
        {    if ( flag == 1 )
             {    x = sign * sum;
                  sum = 0;
                  flag = 2;
		  sign = 1;
             }
        }
		else if ( c == '>' )
        {    p->next = ( NODE * ) malloc( sizeof(NODE) );
             p->next->coef = x;
             p->next->exp  = sign * sum;
             p = p->next;
             p->next = NULL;
             flag = 0;
        }
    }
}

void output( NODE * head )
{
    while ( head->next != NULL )
    {   head = head->next;
        printf("<%d,%d>,", head->coef, head->exp );
    }
    printf("\n");
}

int main()
{   NODE * head1, * head2, * head3;

    head1 = ( NODE * ) malloc( sizeof(NODE) );
    input( head1 );

    head2 = ( NODE * ) malloc( sizeof(NODE) );
    input( head2 );

    head3 = ( NODE * ) malloc( sizeof(NODE) );
    head3->next = NULL;
    multiplication( head1, head2, head3 );

	output( head3 );

	return 0;
}

/* PRESET CODE END - NEVER TOUCH CODE ABOVE */

輸入輸出樣例

樣例 \(1\)

輸入

<1,0>,<2,1>,<1,2>,
<1,0>,<1,1>,

輸出

<1,0>,<3,1>,<3,2>,<1,3>,

樣例 \(2\)

輸入

<-1,0>,<1,1>,
<1,0>,<1,1>,

輸出

<-1,0>,<1,2>,

樣例 \(3\)

輸入

<5,0>,<10,1>,
<2,0>,<3,1>,<4,2>,<5,3>,

輸出

<10,0>,<35,1>,<50,2>,<65,3>,<50,4>,

題解

一元多項式相乘就直接使用兩層 for 巢狀對第一個多項式的指標和第二個多項式的指標進行遍歷相乘即可(實際實現中使用 while)。設第一個多項式有 \(m\) 項,第二個多項式有 \(n\) 項,顯然共有 \(m * n\) 輪多項式相乘,把每一次相乘結果加到第三個多項式中去,即得到答案。

由於一元多項式在輸入輸出規定了指數遞增,因此對第三個多項式不用再進行一次指標遍歷,第三個 while 迴圈並沒有對第三個多項式從頭到尾在遍歷一次。實際上,它是從第三個多項式當前指標 tmp 開始,根據當前建立結點(此輪多項式相乘的結果)的指數大小(一定大於等於 tmp 指向結點的指數 ),向後移動到合適的位置,把當前建立結點“加到”tmp結點上或“加到”tmp結點後面。

在程式碼中要充分討論到邊界情況。同時應該要注意到隱藏測試用例中有兩個是關於零多項式的。

程式碼如下:

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

typedef struct node
{
    int coef, exp;
    struct node* next;
}node;

void multiplication(node* n1, node* n2, node* n3);
void input(node* head);
void output(node* head);

/*
 * 有限自動機解析字串(非工程不嚴謹的解析)
 */
void input(node* head)
{
    int flag, sign, sum, x;
    char c;
    node* p = head;
    while ((c = getchar()) != '\n') {
        if (c == '<')
        {
            sum = 0;
            sign = 1;
            flag = 1;
        }
        else if (c == '-')
        {
            sign = -1;
        }
        else if (c >= '0' && c <= '9')
        {
            sum = sum * 10 + c - '0';
        }
        else if (c == ',')
        {
            if (flag == 1) {
                x = sign * sum;
                // 重新設定
                sum = 0;
                sign = 1;
                flag = 2;
            }
        }
        else if (c >= '>')
        {
            if (flag == 2) {
                p->next = (node*)malloc(sizeof(node));
                p->next->coef = x;
                p->next->exp = sign * sum;
                p = p->next;
                p->next = NULL;
                flag = 0;
            }
        }
    }
}

void output(node* head)
{
    while (head->next != NULL) {
        head = head->next;
        printf("<%d,%d>,", head->coef, head->exp);
    }
    printf("\n");
}

void multiplication(node* head1, node* head2, node* head3)
{
    // 注意輸入順序是遞增的
    node* pt1 = head1->next; // 第一個多項式的指標
    node* pt2 = head2->next; // 第二個多項式的指標
    node* tmp = head3->next; // 第三個多項式的指標
    node* pre = head3; // tmp 的前一個指標
    if ((pt1->coef == 0 && pt1->exp == 0) || (pt2->coef == 0 && pt2->exp == 0)) {
        // 零多項式單獨討論
        node* newn = (node*)malloc(sizeof(node));
        newn->coef = 0;
        newn->exp = 0;
        newn->next = NULL;
        pre->next = newn;
        return;
    }
    while (pt1 != NULL) {
        pre = head3;
        tmp = head3->next;
        pt2 = head2->next;
        while (pt2 != NULL) {
            // 建立新的結點。注意多項式乘法,係數相乘,指數相加
            node* newn = (node*)malloc(sizeof(node));
            newn->coef = pt2->coef * pt1->coef;
            newn->exp = pt2->exp + pt1->exp;
            newn->next = NULL;
            // 將建立的新結點加入到第三個多項式中,因此需要將 tmp 移動到合適的位置
            while (tmp != NULL) {
                if (tmp->next == NULL || (tmp->exp <= newn->exp && newn->exp < tmp->next->exp)) break;
                tmp = tmp->next;
                pre = pre->next;
            }
            // 將 “退出迴圈條件”分情況討論
            if (tmp == NULL) {
                pre->next = newn;
                tmp = newn;
            }
            else if (tmp->exp == newn->exp) {
                tmp->coef = tmp->coef + newn->coef;
                if (tmp->coef == 0) {
                    // 刪除當前節點
                    pre->next = tmp->next;
                    tmp = pre->next;
                }
            }
            else {
                if (tmp->next != NULL) {
                    newn->next = tmp->next;
                }
                tmp->next = newn;
                tmp = tmp->next;
                pre = pre->next;
            }
            pt2 = pt2->next;
        }
        pt1 = pt1->next;
    }
}

int main()
{
    node* head1;
    node* head2;
    node* head3;
    head1 = (node*)malloc(sizeof(node));
    input(head1);
    head2 = (node*)malloc(sizeof(node));
    input(head2);
    head3 = (node*)malloc(sizeof(node));
    head3->next = NULL;
    multiplication(head1, head2, head3);
    output(head3);
    return 0;
}