线性表(三)一元多项式应用

引言

符号多项式的操作,已经成为表处理的典型用例。用一个长度为m且每个元素有两个数据项(系数项和指数项)的线性表((p1,e1), (p2,e2), ···,(pm, em))便可唯一确定多项式Pn(x)。
对应于线性表的两种存储结构,上述定义的一元多项式也可以有两种存储表示方法。由于多项式多进行相加、乘法等操作,因此采用链式存储结构,节约结点插入、删除等操作时间。

元素定义
typedef struct{
        float coef;          // 项的系数
        int exp;           // 项的指数
}ElemType;               // 多项式的项
一元多项式定义
typedef struct PNode{
        ElemType data;              // 数据项
        struct PNode *next;        // 指向后继元素
}PNode, *Polynomail;             // 带头结点的链表表示多项式
基本操作
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define SUCCESS 1
#define FAILURE 0 

// 定义多项式数据元素
typedef struct{
        float coef;     // 项的系数
        int exp;        // 项的指数
} ElemType;

int compare(ElemType e1, ElemType e2){
        // 依e1的指数值<(或=)(或>)e2的指数值,分别返回-1,0和1
        if(e1.exp < e2.exp){
                return -1; 
        } else if(e1.exp == e2.exp){
                return 0;
        } else {
                return 1;
        }   
}

typedef struct PNode{
        ElemType data;
        struct PNode *next;
}PNode, *Polynomail;    // 带头结点的有序链表表示多项式

// 基本操作
int InitPolyn(Polynomail *P){
        // 初始化P
        *P = (Polynomail)malloc(sizeof(PNode));
        if(!*P) exit(-1);
        (*P)->next = NULL;
}

int LocatePolyn(Polynomail P, ElemType e, int(*compare)(ElemType, ElemType)){
        // 在P中寻找和e满足compare结果为0的元素,成功返回1,否则返回-1
        P = P->next;
        while(P){
                if(compare(P->data, e) == 0) return 1;
                P = P->next;
        }   
        return -1;      // 没有找到
}

void CreatPolyn(Polynomail *P, int m){ 
        // 输入m项系数和指数,建立表示一元多项式的有序链表P
        printf("请输入%d项系数和参数, 格式:\ncoef exp\n", m); 
        Polynomail head = *P; 
        PNode *s; 
        head->data.coef = 0.0; head->data.exp = -1;     // 头结点
        int i;
        for(i=0;i<m;){
                s = (Polynomail)malloc(sizeof(PNode));
                if(!s) exit(-1);        // 存储空间不足
                scanf("%f %d", &(s->data.coef), &(s->data.exp));
                if(LocatePolyn(*P, s->data, compare) < 0) {     // 排除相同指数项
                        s->next = NULL;
                        head->next = s;
                        head = s;
                        i++;
                }
        }
}

void DestroyPolyn(Polynomail *P){
        // 销毁一元多项式P
        Polynomail s = *P;
        Polynomail t;
        while(s){
                t = s->next;
                free(s);
                s = t;
        }
        *P = NULL;
}

void PrintPolyn(Polynomail P){
        // 打印输出一元多项式
        P = P->next;
        int i = 1;
        if(P) printf("%.2fx^%d", P->data.coef, P->data.exp);
        P = P->next;
        while(P){
                printf("%+.2fx^%d", P->data.coef, P->data.exp);
                P = P->next;
        }
        printf("\n");
}

int PolynLength(Polynomail P){
        // 返回一元多项式P的项数
        int l = 0;
        P = P->next;
        while(P){
                l++;
                P = P->next;
        }
        return l;
}

void AddPolyn(Polynomail *Pa, Polynomail *Pb,
                int(*compare)(ElemType, ElemType)){
        // 完成有序多项式相加运算,即Pa = Pa + pb; 并销毁Pb
        Polynomail heada = *Pa, headb = *Pb;
        Polynomail headc = heada;
        Polynomail temp;        // 释放节点时使用
        heada = heada->next;    // 指向首元素
        headb = headb->next;
        while(heada && headb){
                if(compare(heada->data, headb->data) < 0){
                        // 当前heada节点指数小于headb
                        headc->next = heada;
                        headc = heada;
                        heada = heada->next;
                } else if(compare(heada->data, headb->data) > 0){
                        // 当前heada节点指数大于headb
                        headc->next = headb;
                        headc = headb;
                        headb = headb->next;
                } else{
                        // 两者节点指数相同
                        if(heada->data.coef + headb->data.coef != 0){
                                heada->data.coef = heada->data.coef +
                                        headb->data.coef;
                                headc->next = heada;
                                headc = heada;
                                heada = heada->next;
                        } else {
                                temp = heada;
                                heada = heada->next;
                                free(temp);
                        }
                        temp = headb;
                        headb = headb->next;
                        free(temp);
                }
        }
        if(headb) headc->next = headb;  // 链接Pb中剩余节点
        free(*Pb);      // 释放Pb头结点
}

void MultiplyPolyn(Polynomail Pa, Polynomail Pb, Polynomail *Pc){
        // 完成多项式相乘运算,即Pc = Pa * Pb   
        Polynomail pa, pb, s;
        // 临时链表
        Polynomail temp, headtemp;
        pa = Pa->next;
        while(pa){
                InitPolyn(&temp);
                headtemp = temp;
                pb = Pb->next;  // 每次需将pb重置
                while(pb){      // pa同pb中每项相乘并将结果存在pc中
                        s = (Polynomail)malloc(sizeof(PNode));
                        s->data.coef = pa->data.coef * pb->data.coef;
                        s->data.exp = pa->data.exp + pb->data.exp;
                        s->next = NULL;
                        headtemp->next = s;
                        headtemp = s;
                        pb = pb->next;
                }
                // 将每次乘积结果相加存储至Pc中
                AddPolyn(Pc,&temp, compare);
                pa = pa->next;
        }
}

void main(){
        Polynomail P;
        // 初始化
        printf("******** init ********\n");
        InitPolyn(&P);
        // 赋值
        printf("********* create value **************\n");
        CreatPolyn(&P, 6);
        // 打印
        printf("********* console value **********\n");
        PrintPolyn(P);
        // 长度
        printf("*************** length **************\n");
        printf("P length is: %d\n", PolynLength(P));
        //销毁
        printf("*************** destroy **************\n");
        DestroyPolyn(&P);
        printf("after destory, P postion is: %p\n", P);

        // 多项式相加
        printf("********** polyn add ******************\n");
        Polynomail P1,  P2;
        InitPolyn(&P1); InitPolyn(&P2);
        CreatPolyn(&P1, 5); CreatPolyn(&P2, 6);
        printf("P1: ");
        PrintPolyn(P1);
        printf("P2: ");
        PrintPolyn(P2);

        printf("\n");
        AddPolyn(&P1, &P2, compare);

        printf("After add, P1: ");
        PrintPolyn(P1);
        printf("\n");
        // 多项式相乘
        printf("************ polynnomail multi********\n");
        Polynomail P3, P4, P5;
        InitPolyn(&P3); InitPolyn(&P4), InitPolyn(&P5);
        CreatPolyn(&P3, 4); CreatPolyn(&P4, 3);
        printf("P3: ");
        PrintPolyn(P3);
        printf("P4: ");
        PrintPolyn(P4);
        printf("\n");

        MultiplyPolyn(P3, P4, &P5);

        printf("After multi, P5: ");
        PrintPolyn(P5);
        printf("\n");
}
运行结果
******** init ********
********* create value **************
请输入6项系数和参数, 格式:
coef exp
1 0
-2 1
4 3
6.2 5
-10.4 29
16 356
********* console value **********
1.00x^0-2.00x^1+4.00x^3+6.20x^5-10.40x^29+16.00x^356
*************** length **************
P length is: 6
*************** destroy **************
after destory, P postion is: (nil)
********** polyn add ******************
请输入5项系数和参数, 格式:
coef exp
1 0
-9 5
3 7
5 8
10 10
请输入6项系数和参数, 格式:
coef exp
3 0
9 2
9 5
-4.2 7
1 8
-15 12
P1: 1.00x^0-9.00x^5+3.00x^7+5.00x^8+10.00x^10
P2: 3.00x^0+9.00x^2+9.00x^5-4.20x^7+1.00x^8-15.00x^12
After add, P1: 4.00x^0+9.00x^2-1.20x^7+6.00x^8+10.00x^10-15.00x^12
*********** polynnomail multi********
请输入4项系数和参数, 格式:
coef exp
9 0
-10 1
7 2
6 3
请输入3项系数和参数, 格式:
coef exp
-5 0
4 1
-2 3
P3: 9.00x^0-10.00x^1+7.00x^2+6.00x^3
P4: -5.00x^0+4.00x^1-2.00x^3
After multi, P5: -45.00x^0+86.00x^1-75.00x^2-20.00x^3+44.00x^4-14.00x^5-12.00x^6
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,198评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,663评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,985评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,673评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,994评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,399评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,717评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,407评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,112评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,371评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,891评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,255评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,881评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,010评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,764评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,412评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,299评论 2 260

推荐阅读更多精彩内容