C语言数据结构实现——一元多项式的基本运算
问题描述:
第一种算法:顺序存储结构实现——顺序表
(1)算法思路:
算法要实现两个一元多项式相关的相关运算,相加、相减、相乘。首先我们要选取一种存储结构来存放我们多项式的每一项,我们可以采用顺序存储结构中的顺序表来实现多项式的存储。用一个数组a存储多项式的相关数据:数组分量a[i]表示项 X^i前的系数,用数组分量下标对应相应项的指数,我们的数组分量值就是对应这一项的系数。
例如,f(x)=6+8X+2X2+6*X5,可以用一个顺序表来表示:
这种方法在一般情况下对一元多项式实现相关运算是比较方便的。我们顺序表实现两个一元多项式的相加,只要把两个数组的对应分量相加就行了,代码很容易实现,同理多项式的减法也较容易实现。实现两个一元多项式的乘法,我们首先选定一个多项式,让它的每一项另一个多项式的每一项依次相乘,乘完后用一个临时顺序表来保存得到的结果,将得到的所有临时顺序表相加起来就是两个多项式相乘的结果。
但是用顺序表来实现也存在重大的问题,就是在多项式比较稀疏的情况下(多项式有较高的阶,但是只有很少的非零项。),算法的时间和空间效率比较差。例如: f(x)=1+2X+3X^3000,表示这个多项式的顺序表要采用一个大小至少为3001的数组,但是这个数组中的大部分数据为0,只有3项不为零,空间浪费严重。而且我们要遍历这个存储多项式的顺序表,要遍历3001次,时间复杂度较高。这主要是顺序表实现该算法的缺点。
(2)算法代码:
#include<stdio.h>#include<stdlib.h>#define maxsize 100typedef struct node {int a[maxsize];int length;} list;//初始化顺序表list* creat_list(){struct node* L;L = (list*)malloc(sizeof(struct node));L->length = 0;return L;}void input(list* L)//一元多项式的输入{int i;printf("请输入此多项式的项数:");scanf("%d", &L->length);for (i = 0; i < L->length; i++){printf("请输入此多项式X^%d项的系数: ", i);scanf("%d", &L->a[i]);}printf("\n");}void output(struct node* L) //一元多项式的输出{int i, t = 0;for (i = L->length - 1; i >= 0; i--){if (L->a[i] == 0){t++;continue;}else{if (i == 0){if (L->a[i] < 0)printf("%d", L->a[i]);elseprintf("+%d", L->a[i]);}else if (0 < i && i < L->length - 1){if (i == 1){if (L->a[i] < 0)printf("%d*X", L->a[i]);elseprintf("+%d*X", L->a[i]);}else{if (L->a[i] < 0)printf("%d*X^%d", L->a[i], i);elseprintf("+%d*X^%d", L->a[i], i);}}else if (i == L->length - 1){if (i == 1){printf("%d*X", L->a[i]);}elseprintf("%d*X^%d", L->a[i], i);}}}if (t == L->length){printf("0\n");}printf("\n");}list* sum(list* L1, list* L2) //实现两个一元多项式的相加操作{int i, h;struct node* p;list* L3;L3 = creat_list();if (L1->length <= L2->length){p = L1;h = L2->length - L1->length;}else{p = L2;h = L1->length - L2->length;}for (i = 0; i < p->length; i++){L3->a[i] = L1->a[i] + L2->a[i];L3->length++;}if (h != 0){if (p == L1){for (i = L1->length; i <= L2->length - 1; i++){L3->a[i] = L2->a[i];L3->length++;}}elsefor (i = L2->length; i <= L1->length - 1; i++){L3->a[i] = L1->a[i];L3->length++;}}return L3;}list* poor(list* L1, list* L2)//实现两个一元多项式的相减操作{int i, h;struct node* p;list* L;L = creat_list();h = L1->length - L2->length;if (h <= 0){p = L1;}else{p = L2;}for (i = 0; i < p->length; i++){L->a[i] = L1->a[i] - L2->a[i];L->length++;}if (h != 0){if (p == L2){for (i = L2->length; i <= L1->length - 1; i++){L->a[i] = L1->a[i];L->length++;}}if (p == L1){for (i = L1->length; i <= L2->length - 1; i++){L->a[i] = -1 * (L2->a[i]);L->length++;}}}return L;}list* multiply(list* L1, list* L2) //实现两个多项式的相乘{int i, j, k;list* L;L = creat_list();for (i = 0; i <= L1->length - 1; i++){list* p = creat_list();p->length = i + L2->length;for (k = 0; k <= p->length - 1; k++){p->a[k] = 0;}for (j = 0; j <= L2->length - 1; j++){p->a[i + j] = L1->a[i] * L2->a[j];}L = sum(L, p);}return L;}void show(){printf("\t\t 指令集合\n");printf("\n\t1 《《《《《 一元多项式的加法运算\n");printf("\n\t2 《《《《《 一元多项式的减法运算\n");printf("\n\t3 《《《《《 一元多项式的乘法运算\n");}void main(){int i, h;list* P;list* L[2];for (i = 0; i < 2; i++){L[i] = creat_list();printf("\t请输入第%d个一元多项式\n", i + 1);input(L[i]);printf("第%d个一元多项式的表达式为:\n", i + 1);printf("\tF%d(X)=", i + 1);output(L[i]);printf("\n\n");}show();printf("请对两个多项式选择相关运算指令:\n");scanf("%d", &h);switch (h){case 1:P = sum(L[0], L[1]);printf("两个一元多项式的和为:\n\tF3(X)=");output(P);break;case 2:printf("两个一元多项式的差为:\n\tF3(X)=");P = poor(L[0], L[1]);output(P);break;case 3:printf("两个一元多项式的乘积为:\n\tF3(X)=");P = multiply(L[0], L[1]);output(P);break;default:printf("指令错误!\n");}}
(3)代码运行结果:
加法运算:
减法运算:
乘法运算:
(4)代码分析:
从(2)中代码可以看出,实现一元多项式的加,减和乘运算的函数的时间复杂度为O(N2),所以我们整体算法的时间复杂度为:O(N2)。但是这种算法存在重大的问题,就是在多项式比较稀疏的情况下(多项式有较高的阶,但是只有很少的非零项。),算法的时间和空间效率比较差。例如: f(x)=1+2X+3X^3000,表示这个多项式的顺序表要采用一个大小至少为3001的数组,但是这个数组中的大部分数据为0,只有3项不为零,空间浪费严重。当我们要遍历这个存储多项式的顺序表,要遍历3001次,时间复杂度较高。当一元多项式中项中X的的指数过大时,算法的性能较差。
顺序存储结构—— 算法改进思路
在多项式比较稀疏的情况下(多项式有较高的阶,但是只有很少的非零项。)算法的时间和空间效率比较差,我们打算对其进行改进,我们主要提出了其改进思路。
采用顺序存储结构来表示一元多项式的非零项,多项式的每一项都有两个信息,系数和指数,因此我们可以用一个结构体数组来表示我们一元多项式,结构体数组的每一项表示一元多项式的一个非零项。数组的大小可以根据非零项的最多个数来确定,而并不是根据多项式的最高阶来确定。这种方法。对于稀疏多项式的情况下能够节省大量的空间。但是多项式并不是很稀疏,则节省空间的优势就没有了,反而会导致运算过于复杂。例如,我们用这种方法实现两个一元多项式的相加操作的具体过程为:首先我们应该对这两个多项式按指数对多项式进行排列(按指数依次大到小排列多项式的每一项),之后从头开始查看两个多项式的每一项,如果当前两项的指数不一样,则将两个多项式中指数较大的那一项给我们临时创建的结果多项式中 ;如果它们的指数一样而且对应系数和不为零,那么就将这两项的和与其指数放入到我们的结果多项式中。这种方法的运算较为复杂,而且用数组表示多项式的灵活性也不高。更进一步的解决方案就是利用 链式存储结构——单链表 来表示我们的多项式效果会更好,更具有灵活性。
第二种算法:链式存储结构实现——单链表
1)算法实现思路:
实现两个一元多项式相关的相关运算,相加、相减、相乘。可以选取链表来存放多项式的每一项的两项数据,每一次输入数据时向系统申请分配存储空间,每次存储只需要存放其系数和幂。两个多项式的项系数和幂分别存在两个链表中,在进行加、减、乘运算时首先找到不同链表中同类项(即幂相同的项),再进行系数的运算。例如链表A中存放数据2(系数) 1(幂),B中有一组数据5(系数) 1(幂)。在运算时我们首先需要在链表B中找到幂为1的数据,找到后用其系数进行运算,如上例中2+5=7,2-5=-3。 在进行乘法运算时依次拿出A链表中的项系数与B链表中的每一项系数依次相乘,并存放在一个新链表C中。 最后输出链表中的数据后需要释放其内存。
(2)算法代码:
#include<stdio.h>#include<string.h>#include<stdlib.h>#define OK 1#define NO 0#define MAXSIZE 20typedef char Excelelem;typedef struct Node{int xishu;int mi;struct Node *next;} LNode,*LinkList;typedef struct{Excelelem name[100];int length;LinkList next;} HeadList,*HeadLinkList;LinkList Init(int *n); //函数声明HeadLinkList HeadInit(char a[]);LinkList FIND(LinkList Head,int s);void ADD(HeadLinkList A,HeadLinkList B,HeadLinkList C);void SUB(HeadLinkList A,HeadLinkList B,HeadLinkList C);void Free(HeadLinkList Head);void cout(HeadLinkList Head);void MUL(HeadLinkList A,HeadLinkList B,HeadLinkList C);int main(){HeadLinkList A,B,C;int n;A=HeadInit("A多项式");printf("请输入%s:\n",A->name);A->next=Init(&A->length);B=HeadInit("B多项式");printf("请输入%s:\n",B->name);B->next=Init(&B->length);C=HeadInit("C多项式");C->next=NULL;printf("%s+%s:\n",A->name,B->name);ADD(A,B,C);cout(C);printf("%s-%s:\n",A->name,B->name);SUB(A,B,C);cout(C);printf("%s*%s:\n",A->name,B->name);MUL(A,B,C);cout(C);Free(A);Free(B);Free(C);free(A),free(B),free(C);return 0;}LinkList FIND(LinkList Head,int s)//查找链表中第一个系数大于ans的结点的前驱{if(Head->next == NULL || Head->next->mi > s)return Head;return FIND(Head->next,s);}LinkList Init(int *n)//初始化链表体{LinkList Head,p,q;int i=0;int a,b;Head=NULL;while(~scanf("%d",&a) && a!=0){scanf("%d",&b);q=(LinkList)malloc(sizeof(LNode));q->xishu=a;q->mi=b;if(*n==0 || Head->mi>b) q->next=Head,Head=q;else{p=FIND(Head,b);q->next=p->next;p->next=q;}*n++;}return Head;}HeadLinkList HeadInit(char *a)//初始化链表头{HeadLinkList Head;Head=(HeadLinkList)malloc(sizeof(HeadList));strcpy(Head->name,a);Head->length=0;return Head;}void ADD(HeadLinkList A,HeadLinkList B,HeadLinkList C)//多项式加法 O(n){LinkList qa=A->next,qb=B->next,p,q=NULL;Free(C);while(qa || qb){p=(LinkList)malloc(sizeof(LNode));if(qb==NULL || qa && qa->mi<qb->mi){*p=*qa;qa=qa->next;}else if(qa==NULL || qb && qa->mi>qb->mi){*p=*qb;qb=qb->next;}else{p->xishu=qb->xishu+qa->xishu;p->mi=qb->mi;qa=qa->next;qb=qb->next;}if(q==NULL) p->next=q,C->next=q=p;elsep->next=q->next,q->next=p,q=p;C->length++;}}void SUB(HeadLinkList A,HeadLinkList B,HeadLinkList C)//多项式减法 O(n){LinkList qa=A->next,qb=B->next,p,q=NULL;Free(C);while(qa!=NULL || qb!=NULL){p=(LinkList)malloc(sizeof(LNode));if(qb==NULL || qa && qa->mi<qb->mi){*p=*qa;qa=qa->next;}else if(qa==NULL || qb && qa->mi>qb->mi){*p=*qb;p->xishu*=-1;qb=qb->next;}else{*p=*qa;p->xishu-=qb->xishu;qa=qa->next;qb=qb->next;if(p->xishu==0){free(p);continue;}}if(q==NULL) p->next=q,C->next=q=p;elseq->next=p->next,q->next=p,q=p;C->length++;}}void MUL(HeadLinkList A,HeadLinkList B,HeadLinkList C)//多项式乘法 O(n^3){LinkList qa,qb,p,q;int a,b;Free(C);for(qa=A->next; qa; qa=qa->next){for(qb=B->next; qb; qb=qb->next){a=qa->xishu*qb->xishu;b=qa->mi+qb->mi;if(C->length){p=FIND(C->next,b);if(p->mi == b)p->xishu+=a;else{q=(LinkList)malloc(sizeof(LNode));q->xishu=a;q->mi=b;q->next=p->next;p->next=q;C->length++;}}else{p=(LinkList)malloc(sizeof(LNode));p->xishu=a;p->mi=b;p->next=C->next;C->next=p;C->length++;}}}}void Free(HeadLinkList Head)//释放链表体内存{LinkList q=Head->next,p;while (q){p=q;q=q->next;free(p);}Head->length=0;Head->next=NULL;return ;}void cout(HeadLinkList Head)//将链表数据域以多项式形势输出{LinkList q=Head->next;while(q){if(q->xishu>0 && q!=Head->next)printf("+");printf("%.1dx^(%.1d)",q->xishu,q->mi);q=q->next;}printf("\n");return ;}
**(3)代码运行结果:**
(4)代码分析:
该算法的时间复杂度为O(n²)。利用链表解决该问题的优点是处理离散程度较大的数据时(如f(x)=1+2X+3X^3000)可以大大节省空间,因为链表的存储地址不需要连续,可以根据需要动态分配空间。缺点则是在处理连续的数据时存储密度小(相比较顺序表而言)。
C语言数据结构实现——一元多项式的基本运算相关推荐
- 数据结构:一元多项式及其基本运算
1.实现方式:可采用线性表的顺序存储结构,但是当多项式的每个项的指数差别很大时,会浪费很多存储空间.所以采用链式存储方式表示,每一项可以表示成一个结点,结点的结构由存放系数的coef域,存放指数的ex ...
- 顺序表输入栈元素c语言,C语言数据结构之栈简单操作
C语言数据结构之栈简单操作 实验: 编写一个程序实现顺序栈的各种基本运算,并在此基础上设计一个主程序,完成如下功能: (1)初始化顺序栈 (2)插入元素 (3)删除栈顶元素 (4)取栈顶元素 (5)遍 ...
- C语言数据结构【手抄版】第三章 栈和队列
注意:文中彩色代码均在Visual Studio 2022编译器中编写,本文为C语言数据结构手抄版,文中有部分改动,非原创. 目录 注意:文中彩色代码均在Visual Studio 2022编译器中编 ...
- c语言将一个已知头结点的单链表逆序_C语言数据结构实现链表逆序并输出
C语言数据结构实现链表逆序并输出 将一个链表逆序并输出.我用了两种方法来实现,第一种是借助了一个新的空链表:第二种是在原来链表的基础上直接实现逆序. 实例代码: 头文件: #include #incl ...
- 数据结构c语言版第一章答案,《c语言数据结构》第一章概论自测题答案
<<c语言数据结构>第一章概论自测题答案>由会员分享,可在线阅读,更多相关<<c语言数据结构>第一章概论自测题答案(4页珍藏版)>请在人人文库网上搜索. ...
- 一些可运行的C语言数据结构代码
网上有很多C语言数据结构代码:有的不能运行:下面是一些能运行的,和运行截图:备用一下: 1 队列 #include<stdio.h> #include<stdlib.h>#de ...
- C语言数据结构学习用单元测试
药物名称: C语言数据结构学习用单元测试 主治: 本品是基于CUnit编写的.全部的.纯C的数据结构(ADT)各种实现的单元测试.主治基础不牢,水品增长缓慢.建议配合严蔚敏<数据结构>(C ...
- 用数据结构c语言写成绩排序,C语言数据结构 快速排序实例详解
C语言数据结构 快速排序实例详解 一.快速排序简介 快速排序采用分治的思想,第一趟先将一串数字分为两部分,第一部分的数值都比第二部分要小,然后按照这种方法,依次对两边的数据进行排序. 二.代码实现 # ...
- 厦门理工C语言实验报告8,厦门理工c语言数据结构实验
<厦门理工c语言数据结构实验>由会员分享,可在线阅读,更多相关<厦门理工c语言数据结构实验(15页珍藏版)>请在人人文库网上搜索. 1.数据结构实验报告 实验序号:6 实验项目 ...
最新文章
- 《Effective C#中文版:改善C#程序的50种方法》读书笔记
- 转: Linux 下修改oracle 的字符集:WE8ISO8859P1 修改为 ZHS16GBK
- vnc改ip_如何使用VNC进行远程桌面控制
- 与众不同 windows phone (22) - Device(设备)之摄像头(硬件快门, 自动对焦, 实时修改捕获视频)...
- Easy Tech:什么是I帧、P帧和B帧?
- Sequence Pair Weight
- mysql数据=_mysql 数据操作
- 看完这篇文章就知道为什么要使用 Node.js啦!
- Quartus II中通过调用IP核实现RS编解码
- window10 修改jdk版本,从jdk10降到jdk1.8,java -version版本没有变化的问题解决
- bootstrap datepicker 在bootstrap modal中不显示问题
- 程序设计框架图和框架加载流程
- base64编码将字符串转换为图片
- 怎样为Windows7系统设置快速启动栏
- 蛋糕甜品小程序有哪些,这3款小程序值得收藏!
- Chrome渲染分析之Rendering工具使用
- 手机巨头关注的5G,可不仅仅是5G网络那么简单!
- dataframe之按时间筛选数据
- JS删除对象中的某一属性
- 常用HTTP抓包工具Fiddler使用的12个小技巧,值得收藏!
热门文章
- 传统图像去噪方法(一)
- Table ‘数据库.数据库表‘ doesn‘t exist
- Telnet 服务 开启 步骤
- 白盒测试(单元测试JUnit使用断言assertThat中startsWith、endsWith方法)
- Matlab函数、子函数的定义方法
- 强烈推荐!几款windows效率工具,文件查找、资源管理器标签化,效率控必备
- 概率论:魏布斯分布Weibull cumulative distribution function
- 烽火ExMobi引领企业移动应用平台浪潮
- 地理坐标系和投影坐标系详解(及坐标系在ArcGIS中的应用)
- ul(有序列表)可以排序?