使用列表在C中乘法求多项式

时间:2017-03-31 09:58:10

标签: c polynomials

我使用列表来实现多项式的乘法运算。 我的代码是:

typedef struct node *node_ptr;
typedef struct node
{
    unsigned int power;
    int coeff;
    node_ptr next;
}POLY;
typedef node_ptr polynomial; 

void mult_polynomial(polynomial poly1, polynomial poly2, polynomial poly_mult)
{
    assert(!is_null(poly1) && !is_null(poly2) && is_null(poly_mult));
    node_ptr p1 = poly1->next;
    node_ptr p2;
    node_ptr p3;
    node_ptr tmp, cell;

    while (p1) {
        p2 = poly2->next;
        while (p2) {
            p3 = poly_mult;
            cell = p3->next;
            tmp = (node_ptr)malloc(sizeof(struct node));
            tmp->power = p1->power + p2->power;
            tmp->coeff = p1->coeff * p2->coeff;
            tmp->next = NULL;
            if (!cell)
                p3->next = tmp;
            else { 
                if (cell->power == tmp->power) {
                    cell->coeff += tmp->coeff;
                    free(tmp);   
                } else if (cell->power < tmp->power) {
                    p3->next = tmp;
                    tmp->next = cell;
                } else if (cell->power > tmp->power) {
                    while (cell->power > tmp->power) {
                        if(!cell->next || cell->next->power < tmp->power) {
                            cell->next = tmp;
                            break; 
                        } else if (cell->next->power == tmp->power) {
                            cell->next->coeff += tmp->coeff;
                            break;
                        }
                        p3 = cell;
                        cell = p3->next;
                    }
                }
            }
            p2 = p2->next;
        }
        p1 = p1->next;
    }
}

但它似乎太多余了;如何简化?

1 个答案:

答案 0 :(得分:1)

这是我对解决方案的看法。它基本上是一个完整的重写 - 虽然使用的结构只是重命名,但在结构上与你拥有的相同。

函数add_term()变得至关重要 - 它是mult_polynomial()中所有内容的变体,但它也适用于add_polynomial()和{{1} - 一个表明它是一个有用的抽象的因素。请注意,sub_polynomial()本身非常简单紧凑 - mult_polynomial()add_polynomial()都不复杂。

我对sub_polynomial()中的代码并不完全满意(有太多特殊情况),但我相信它的工作做得相当好。你可以得到一个多项式,其中有许多项,其中0为系数;代码不会删除这些条款,但可以(应该)进行升级。因此,打印代码必须跳过这些术语 - 并且有一个特殊情况来处理所有术语零(当然,它打印add_term())。

此外,问题中0的设计是不充分的。如果您有mult_polynomial(),则无法从void mult_polynomial(polynomial *p1, polynomial *p2, polynomial *p3)中获取该功能中的新数据。选项是使用p3或返回新的多项式 - 此代码返回新值。

并且,正如评论中已经提到的,通常最好不要将polynomial **p3用于数据指针(函数指针是另一回事)。您可以在Is it a good idea to typedef pointers找到更多信息。我最终得到了一个多项式结构,它与多项式中一个项的结构相同。 (测试代码使用一对结构,typedefterm来描述用于测试目的的多项式。它们使生活更轻松。有适量的测试代码。termlist并且add_polynomial()函数在10分钟内完成,包括修复sub_polynomial()多项式的打印,这证明了0函数的有用性。

add_term()功能非常重要且有用。它还必须处理一些特殊的特殊情况(负系数,第一系数负,零系数,1的幂和0的幂)。应该可以概括为允许指定变量名称;它被硬编码为print_polynomial()。可能有一些更简单的函数试图逃避 - 一种可能性是x函数,可以在其他地方使用,也可以在print_term()中调用。当然,处理繁琐的特殊情况会有棘手的沟通。

FYI:我将所有函数(print_polynomial()除外)定义为main(),除非引用它们的第二个源文件和声明它们的头文件。显然,如果要重用代码,那么这些函数中的一些将变为可公开访问,然后将其作为static(非extern)并在标头中声明。该类型的详细信息不在标题中; static会在那里,但这就是所需要的。该定义将隐藏在实现文件中。这将是 opaque类型。某些功能(例如typedef struct polynomial polynomial;add_term())将保留为make_term()个功能。

代码使用C99指定的初始值设定项和复合文字。它可以使用C89 / C90代码编写,但它会更难和/或更混乱。不一定非常难,但是......

不用多说,这是代码(很长):

static

输出分为三个部分,以便您可以看到测试的乘法,加法和减法部分的开始:

/* SO 4313-7847 */
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "emalloc.h"

typedef struct polynomial polynomial;

struct polynomial
{
    unsigned int power;
    int          coeff;
    polynomial  *next;
};

static void print_polynomial(const char *tag, const polynomial *poly);

static polynomial *make_term(unsigned int power, int coeff, polynomial *next)
{
    polynomial *new_term = MALLOC(sizeof(*new_term));
    new_term->power = power;
    new_term->coeff = coeff;
    new_term->next  = next;
    return new_term;
}

static polynomial *add_term(polynomial *poly, unsigned int power, int coeff)
{
    if (coeff == 0)
        return poly;
    if (poly == NULL)
        return make_term(power, coeff, NULL);

    /* Find where this term goes */
    polynomial *term = poly;
    polynomial *prev = NULL;
    while (term != NULL && term->power > power)
    {
        prev = term;
        term = term->next;
    }

    if (term != NULL && term->power == power)
    {
        term->coeff += coeff;
        /* Eliminate zero terms here */
    }
    else
    {
        assert(term == NULL || term->power < power);
        polynomial *new_term = make_term(power, coeff, term);
        if (prev == NULL)
            poly = new_term;
        else
            prev->next = new_term;
    }
    return poly;
}

static polynomial *mult_polynomial(polynomial *poly1, polynomial *poly2)
{
    assert(poly1 != NULL && poly2 != NULL);
    polynomial *result = NULL;

    for (polynomial *p1 = poly1; p1 != NULL; p1 = p1->next)
    {
        for (polynomial *p2 = poly2; p2 != NULL; p2 = p2->next)
            result = add_term(result, p1->power + p2->power, p1->coeff * p2->coeff);
    }
    return result;
}

static polynomial *add_polynomial(polynomial *poly1, polynomial *poly2)
{
    assert(poly1 != NULL && poly2 != NULL);
    polynomial *result = NULL;

    for (polynomial *p1 = poly1; p1 != NULL; p1 = p1->next)
        result = add_term(result, p1->power, p1->coeff);
    for (polynomial *p2 = poly2; p2 != NULL; p2 = p2->next)
        result = add_term(result, p2->power, p2->coeff);
    return result;
}

static polynomial *sub_polynomial(polynomial *poly1, polynomial *poly2)
{
    assert(poly1 != NULL && poly2 != NULL);
    polynomial *result = NULL;

    for (polynomial *p1 = poly1; p1 != NULL; p1 = p1->next)
        result = add_term(result, p1->power, p1->coeff);
    for (polynomial *p2 = poly2; p2 != NULL; p2 = p2->next)
        result = add_term(result, p2->power, -p2->coeff);
    return result;
}

static void print_polynomial(const char *tag, const polynomial *poly)
{
    int printed = 0;
    printf("%s:", tag);
    char sign = ' ';
    while (poly != NULL)
    {
        int coeff = poly->coeff;
        if (coeff != 0)
        {
            if (sign != ' ' && coeff < 0)
            {
                sign = '-';
                coeff = -coeff;
            }
            if (poly->power == 0)
                printf(" %c %d", sign, coeff);
            else if (poly->power == 1)
                printf(" %c %dx", sign, coeff);
            else
                printf(" %c %dx^%u", sign, coeff, poly->power);
            printed++;
        }
        poly = poly->next;
        sign = '+';
    }
    if (printed == 0)
        printf("   0");
    putchar('\n');
    fflush(stdout);
}

static void free_polynomial(polynomial *poly)
{
    while (poly != NULL)
    {
        polynomial *next = poly->next;
        free(poly);
        poly = next;
    }
}

typedef struct term
{
    unsigned int power;
    int coeff;
} term;

typedef struct termlist
{
    int n_terms;
    term *terms;
} termlist;

static polynomial *make_polynomial(termlist *terms)
{
    polynomial *poly = 0;
    for (int i = 0; i < terms->n_terms; i++)
    {
        printf("Term: %dx^%u\n", terms->terms[i].coeff, terms->terms[i].power);
        fflush(stdout);
        poly = add_term(poly, terms->terms[i].power, terms->terms[i].coeff);
    }
    return poly;
}

int main(void)
{
    termlist p1[] =
    {
        { .n_terms = 4, .terms = (term[]){ { 3, 2 }, { 2,  1 }, { 1,  4 }, { 0, -9 } } },
        { .n_terms = 3, .terms = (term[]){ { 2, 3 }, { 1, -4 }, { 0,  8 } } },
        { .n_terms = 3, .terms = (term[]){ { 1, 5 }, { 0,  3 }, { 2, -4 } } },
        { .n_terms = 2, .terms = (term[]){ { 4, 5 }, { 0, -5 } } },
        { .n_terms = 4, .terms = (term[]){ { 3, 2 }, { 2,  1 }, { 1,  4 }, { 2, -9 } } },
    };
    enum { NUM_POLYS = sizeof(p1) / sizeof(p1[0]) };
    polynomial *poly[NUM_POLYS] = { 0 };

    for (int i = 0; i < NUM_POLYS; i++)
    {
        poly[i] = make_polynomial(&p1[i]);
        print_polynomial("Building", poly[i]);
    }

    printf("Checking:\n");
    for (int i = 0; i < NUM_POLYS; i++)
        print_polynomial("Next", poly[i]);
    putchar('\n');

    printf("Multiplying polynomials:\n");
    for (int i = 0; i < NUM_POLYS; i++)
    {
        for (int j = 0; j < NUM_POLYS; j++)
        {
            print_polynomial("Term 1", poly[i]);
            print_polynomial("Term 2", poly[j]);
            polynomial *prod = mult_polynomial(poly[i], poly[j]);
            print_polynomial("Product", prod);
            free_polynomial(prod);
        }
        putchar('\n');
    }

    printf("Adding polynomials:\n");
    for (int i = 0; i < NUM_POLYS; i++)
    {
        for (int j = 0; j < NUM_POLYS; j++)
        {
            print_polynomial("Term 1", poly[i]);
            print_polynomial("Term 2", poly[j]);
            polynomial *sum = add_polynomial(poly[i], poly[j]);
            print_polynomial("Sum", sum);
            free_polynomial(sum);
        }
        putchar('\n');
    }

    printf("Subtracting polynomials:\n");
    for (int i = 0; i < NUM_POLYS; i++)
    {
        for (int j = 0; j < NUM_POLYS; j++)
        {
            print_polynomial("Term 1", poly[i]);
            print_polynomial("Term 2", poly[j]);
            polynomial *diff = sub_polynomial(poly[i], poly[j]);
            print_polynomial("Difference", diff);
            free_polynomial(diff);
        }
        putchar('\n');
    }

    for (int i = 0; i < NUM_POLYS; i++)
        free_polynomial(poly[i]);

    return 0;
}

乘:

Term: 2x^3
Term: 1x^2
Term: 4x^1
Term: -9x^0
Building:   2x^3 + 1x^2 + 4x - 9
Term: 3x^2
Term: -4x^1
Term: 8x^0
Building:   3x^2 - 4x + 8
Term: 5x^1
Term: 3x^0
Term: -4x^2
Building:   -4x^2 + 5x + 3
Term: 5x^4
Term: -5x^0
Building:   5x^4 - 5
Term: 2x^3
Term: 1x^2
Term: 4x^1
Term: -9x^2
Building:   2x^3 - 8x^2 + 4x
Checking:
Next:   2x^3 + 1x^2 + 4x - 9
Next:   3x^2 - 4x + 8
Next:   -4x^2 + 5x + 3
Next:   5x^4 - 5
Next:   2x^3 - 8x^2 + 4x

增加:

Multiplying polynomials:
Term 1:   2x^3 + 1x^2 + 4x - 9
Term 2:   2x^3 + 1x^2 + 4x - 9
Product:   4x^6 + 4x^5 + 17x^4 - 28x^3 - 2x^2 - 72x + 81
Term 1:   2x^3 + 1x^2 + 4x - 9
Term 2:   3x^2 - 4x + 8
Product:   6x^5 - 5x^4 + 24x^3 - 35x^2 + 68x - 72
Term 1:   2x^3 + 1x^2 + 4x - 9
Term 2:   -4x^2 + 5x + 3
Product:   -8x^5 + 6x^4 - 5x^3 + 59x^2 - 33x - 27
Term 1:   2x^3 + 1x^2 + 4x - 9
Term 2:   5x^4 - 5
Product:   10x^7 + 5x^6 + 20x^5 - 45x^4 - 10x^3 - 5x^2 - 20x + 45
Term 1:   2x^3 + 1x^2 + 4x - 9
Term 2:   2x^3 - 8x^2 + 4x
Product:   4x^6 - 14x^5 + 8x^4 - 46x^3 + 88x^2 - 36x

Term 1:   3x^2 - 4x + 8
Term 2:   2x^3 + 1x^2 + 4x - 9
Product:   6x^5 - 5x^4 + 24x^3 - 35x^2 + 68x - 72
Term 1:   3x^2 - 4x + 8
Term 2:   3x^2 - 4x + 8
Product:   9x^4 - 24x^3 + 64x^2 - 64x + 64
Term 1:   3x^2 - 4x + 8
Term 2:   -4x^2 + 5x + 3
Product:   -12x^4 + 31x^3 - 43x^2 + 28x + 24
Term 1:   3x^2 - 4x + 8
Term 2:   5x^4 - 5
Product:   15x^6 - 20x^5 + 40x^4 - 15x^2 + 20x - 40
Term 1:   3x^2 - 4x + 8
Term 2:   2x^3 - 8x^2 + 4x
Product:   6x^5 - 32x^4 + 60x^3 - 80x^2 + 32x

Term 1:   -4x^2 + 5x + 3
Term 2:   2x^3 + 1x^2 + 4x - 9
Product:   -8x^5 + 6x^4 - 5x^3 + 59x^2 - 33x - 27
Term 1:   -4x^2 + 5x + 3
Term 2:   3x^2 - 4x + 8
Product:   -12x^4 + 31x^3 - 43x^2 + 28x + 24
Term 1:   -4x^2 + 5x + 3
Term 2:   -4x^2 + 5x + 3
Product:   16x^4 - 40x^3 + 1x^2 + 30x + 9
Term 1:   -4x^2 + 5x + 3
Term 2:   5x^4 - 5
Product:   -20x^6 + 25x^5 + 15x^4 + 20x^2 - 25x - 15
Term 1:   -4x^2 + 5x + 3
Term 2:   2x^3 - 8x^2 + 4x
Product:   -8x^5 + 42x^4 - 50x^3 - 4x^2 + 12x

Term 1:   5x^4 - 5
Term 2:   2x^3 + 1x^2 + 4x - 9
Product:   10x^7 + 5x^6 + 20x^5 - 45x^4 - 10x^3 - 5x^2 - 20x + 45
Term 1:   5x^4 - 5
Term 2:   3x^2 - 4x + 8
Product:   15x^6 - 20x^5 + 40x^4 - 15x^2 + 20x - 40
Term 1:   5x^4 - 5
Term 2:   -4x^2 + 5x + 3
Product:   -20x^6 + 25x^5 + 15x^4 + 20x^2 - 25x - 15
Term 1:   5x^4 - 5
Term 2:   5x^4 - 5
Product:   25x^8 - 50x^4 + 25
Term 1:   5x^4 - 5
Term 2:   2x^3 - 8x^2 + 4x
Product:   10x^7 - 40x^6 + 20x^5 - 10x^3 + 40x^2 - 20x

Term 1:   2x^3 - 8x^2 + 4x
Term 2:   2x^3 + 1x^2 + 4x - 9
Product:   4x^6 - 14x^5 + 8x^4 - 46x^3 + 88x^2 - 36x
Term 1:   2x^3 - 8x^2 + 4x
Term 2:   3x^2 - 4x + 8
Product:   6x^5 - 32x^4 + 60x^3 - 80x^2 + 32x
Term 1:   2x^3 - 8x^2 + 4x
Term 2:   -4x^2 + 5x + 3
Product:   -8x^5 + 42x^4 - 50x^3 - 4x^2 + 12x
Term 1:   2x^3 - 8x^2 + 4x
Term 2:   5x^4 - 5
Product:   10x^7 - 40x^6 + 20x^5 - 10x^3 + 40x^2 - 20x
Term 1:   2x^3 - 8x^2 + 4x
Term 2:   2x^3 - 8x^2 + 4x
Product:   4x^6 - 32x^5 + 80x^4 - 64x^3 + 16x^2

减法:

Adding polynomials:
Term 1:   2x^3 + 1x^2 + 4x - 9
Term 2:   2x^3 + 1x^2 + 4x - 9
Sum:   4x^3 + 2x^2 + 8x - 18
Term 1:   2x^3 + 1x^2 + 4x - 9
Term 2:   3x^2 - 4x + 8
Sum:   2x^3 + 4x^2 - 1
Term 1:   2x^3 + 1x^2 + 4x - 9
Term 2:   -4x^2 + 5x + 3
Sum:   2x^3 - 3x^2 + 9x - 6
Term 1:   2x^3 + 1x^2 + 4x - 9
Term 2:   5x^4 - 5
Sum:   5x^4 + 2x^3 + 1x^2 + 4x - 14
Term 1:   2x^3 + 1x^2 + 4x - 9
Term 2:   2x^3 - 8x^2 + 4x
Sum:   4x^3 - 7x^2 + 8x - 9

Term 1:   3x^2 - 4x + 8
Term 2:   2x^3 + 1x^2 + 4x - 9
Sum:   2x^3 + 4x^2 - 1
Term 1:   3x^2 - 4x + 8
Term 2:   3x^2 - 4x + 8
Sum:   6x^2 - 8x + 16
Term 1:   3x^2 - 4x + 8
Term 2:   -4x^2 + 5x + 3
Sum:   -1x^2 + 1x + 11
Term 1:   3x^2 - 4x + 8
Term 2:   5x^4 - 5
Sum:   5x^4 + 3x^2 - 4x + 3
Term 1:   3x^2 - 4x + 8
Term 2:   2x^3 - 8x^2 + 4x
Sum:   2x^3 - 5x^2 + 8

Term 1:   -4x^2 + 5x + 3
Term 2:   2x^3 + 1x^2 + 4x - 9
Sum:   2x^3 - 3x^2 + 9x - 6
Term 1:   -4x^2 + 5x + 3
Term 2:   3x^2 - 4x + 8
Sum:   -1x^2 + 1x + 11
Term 1:   -4x^2 + 5x + 3
Term 2:   -4x^2 + 5x + 3
Sum:   -8x^2 + 10x + 6
Term 1:   -4x^2 + 5x + 3
Term 2:   5x^4 - 5
Sum:   5x^4 - 4x^2 + 5x - 2
Term 1:   -4x^2 + 5x + 3
Term 2:   2x^3 - 8x^2 + 4x
Sum:   2x^3 - 12x^2 + 9x + 3

Term 1:   5x^4 - 5
Term 2:   2x^3 + 1x^2 + 4x - 9
Sum:   5x^4 + 2x^3 + 1x^2 + 4x - 14
Term 1:   5x^4 - 5
Term 2:   3x^2 - 4x + 8
Sum:   5x^4 + 3x^2 - 4x + 3
Term 1:   5x^4 - 5
Term 2:   -4x^2 + 5x + 3
Sum:   5x^4 - 4x^2 + 5x - 2
Term 1:   5x^4 - 5
Term 2:   5x^4 - 5
Sum:   10x^4 - 10
Term 1:   5x^4 - 5
Term 2:   2x^3 - 8x^2 + 4x
Sum:   5x^4 + 2x^3 - 8x^2 + 4x - 5

Term 1:   2x^3 - 8x^2 + 4x
Term 2:   2x^3 + 1x^2 + 4x - 9
Sum:   4x^3 - 7x^2 + 8x - 9
Term 1:   2x^3 - 8x^2 + 4x
Term 2:   3x^2 - 4x + 8
Sum:   2x^3 - 5x^2 + 8
Term 1:   2x^3 - 8x^2 + 4x
Term 2:   -4x^2 + 5x + 3
Sum:   2x^3 - 12x^2 + 9x + 3
Term 1:   2x^3 - 8x^2 + 4x
Term 2:   5x^4 - 5
Sum:   5x^4 + 2x^3 - 8x^2 + 4x - 5
Term 1:   2x^3 - 8x^2 + 4x
Term 2:   2x^3 - 8x^2 + 4x
Sum:   4x^3 - 16x^2 + 8x