数据结构算法C语言实现(六)---2.4一元多项式的表示及相加
一.简述
利用链表表示稀疏多项式,并基于之前的一些操作(编程实现上还是有所不同的)组合新的操作实现一元多项式的表示及相加。
二.ADT
抽象数据类型一元多项式的定义
ADT Polyomail{
数据对象:D = {a[i]|a[i]属于TermSet, i = ,,...,m,m>=
TermSet中每个元素包含一个表示系数的实数和表示指数的整数}
数据关系
基本操作:
CreatPolyn(&P, m)
操作结果:输入 m 项的系数和指数,建立一元多项式 P
DestroyPolyn(&P)
初始条件:一元多项式 P 已存在
操作结果:销毁一元多项式P
PrintPolyn(P)
初始条件:一元多项式 P 已存在
操作结果:打印输出一元多项式 P
PolynLength(P)
初始条件:一元多项式 P 已存在
操作结果:返回一元多项式中 P 的项数
AddPolyn(&Pa, &Pb)
初始条件:一元多项式 Pa 和 Pb 已存在
操作结果:完成多项式相加运算,即:Pa = Pa + Pb,并销毁一元多项式 Pb
SubtractPolyn(&Pa, &Pb)
初始条件:一元多项式 Pa 和 Pb 已存在
操作结果:完成多项式相减运算,即 Pa = Pa - Pb,并销毁一元多项式 Pb
MultiplyPolyn(&Pa, &Pb)
初始条件:一元多项式 Pa 和 Pb 已存在
操作结果:完成多项式相乘运算,即 Pa = Pa x Pb,并销毁一元多项式 Pb
}ADT Polynomial
*/
三.头文件
//2_4.h
/**
《数据结构(C语言版)》 Page 37
....为此,从实际应用角度出发重新定义线性链表及其基本操作....
*/
/**
author:zhaoyu
email:zhaoyu1995.com@gmail.com
date:2016-6-6
note:realize my textbook <<数据结构(C语言版)>>
*/
#ifndef _2_4_H_
#define _2_4_H_
#include "head.h"
typedef struct{//项的表示,多项式的项作为LinkList的数据元素
float coef;//系数
int expn;//指数
}term, ElemType;//两个类型名:term用于本ADT,ElemType为LinkList的数据对象名
typedef struct LNode{
ElemType data;
struct LNode *next;
}*Link, *Position;
typedef struct{//链表类型
Link head, tail;//分别指向线性链表中的头结点和最后一个结点
int len;//指示线性链表中数据元素的个数
}LinkList;
typedef LinkList polynomial;//用带表头结点的有序链表表示多项式 int cmp(term a, term b)
{
//依据 a 的指数值 <(或=)(或>) b 的指数值 ,返回 -1 ,0, +1
if(a.expn < b.expn)
{
return -;
}
else if (a.expn == b.expn)
{
return ;
}
else
{
return ;
}
}
Status InitList(LinkList &L)
{
//构造一个空的线性表L
L.head = (Link)malloc(sizeof(struct LNode));
L.head->data.coef = 0.0;
L.head->data.expn = -;
L.head->next = NULL;
L.tail = L.head->next;
L.len = ;
}
Position GetHead(LinkList L)
{
//返回线性链表 L 中头结点的位置
return L.head;
}
Status SetCurElem(Link &p, ElemType e)
{
//已知 p 指向线性链表中的一个结点,用 e 更新 p 所指结点中数据元素的值
p->data.coef = e.coef;
p->data.expn = e.expn;
return OK;
}
Status LocateElem(LinkList L, ElemType e, Position &q, Status (* compare)(ElemType, ElemType))
{
//若有序链表 L 中存在与 e 满足判定函数 compare() 取值为 0 的函数
//则 q 指示 L 中第一个值为 e 的结点的位置,并返回 TRUE;否则 q 指示
//第一个与 e 满足compare() 取值>0的元素的前驱的位置,并返回FLASE
Link temp = L.head->next;
while (temp != NULL)
{
if ( == (* compare)(temp->data, e))
{
q = temp;
return TRUE;
}
temp = temp->next;
}
temp = L.head;
while (temp->next != NULL)
{
if ((* compare)(temp->next->data, e) > )
{
q = temp;
return FALSE;
}
temp = temp->next;
}
q = temp;
return FALSE;
}
Status MakeNode(Link &p, ElemType e)
{
//分配由 p 指向的值为 e 的结点,并返回 OK;若分配失败,则返回 ERROR
p = (Link)malloc(sizeof(struct LNode));
if (!p)
{
return ERROR;
}
p->data.coef = e.coef;
p->data.expn = e.expn;
p->next = NULL;
return OK;
}
Status InsFirst(Link &h, Link &s)
{
//已知 h 指向线性链表的头结点,将 s 所指节点插入在第一个结点之前
if (NULL == h)
{
return ERROR;
}
else
{
s->next = h->next;
h->next = s;
}
return OK;
}
ElemType GetCurElem(Link p)
{
//已知 p 指向线性链表中的一个节点,返回 p 所指结点中数据元素的值
if (p != NULL)
{
return p->data;
}
else
{
exit(ERROR);
}
}
/**
My Code
*/
Position NextPos(LinkList L, Link p)
{
//已知 p 指向线性链表 L 中的一个节点,返回 p 所指结点
//的直接后继的位置,若无后继,返回 NULL
Link q = L.head;
while (q->next != NULL)
{
if(q == p)
{
return p->next;
}
q = q->next;
}
return NULL;
}
Status DelFirst(Link &h, Link &q)
{
//已知 h 指向线性链表的头结点,删除链表中的第一个节点并以 q 返回
if (h == NULL)
{
return ERROR;
}
q = h->next;
h->next = q->next;
q->next = NULL;
return OK;
}
Status FreeNode(Link &p)
{
//释放 p 所指节点
p = NULL;//便于回收???释放后再次使用
free(p);
}
Status ListEmpty(LinkList L)
{
//若线性链表 L 为空,则返回 TRUE,否则返回 FALSE
if (L.head->next == NULL)
{
return TRUE;
}
else
{
return FALSE;
}
}
Status Append(LinkList &L, Link &s)
{
//将指针 s 所指(彼此以指针相链)的一串结点
//链接在线性链表 L 最后一个结点
Link q = L.head;
while (q->next != NULL)
{
q = q->next;
}
q->next = s;
int cnt = ;
Link temp = s;
while (temp != NULL)
{
cnt++;
if (NULL == temp->next)
{
L.tail = temp;//注意更新尾指针
}
temp = temp->next;//注意这一句要放在最后,否则可能访问非法内存
} L.len += cnt;
//注意要根据这一串结点长度增加链表长度
return OK;
}
void PrintPolyn(polynomial P)
{
Link temp = P.head->next;
while (temp != NULL)
{
printf("%.1f\t", temp->data.coef);
temp = temp->next;
}
printf("\n");
temp = P.head->next;
while (temp != NULL)
{
printf("%d\t", temp->data.expn);
temp = temp->next;
}
printf("\n");
}
/**
algorithm 2.22
*/
void CreatPolyn(polynomial &P, int m)
{
//输入 m 项的系数和指数,建立表示一元多项式的有序链表 P
InitList(P);
Link h = GetHead(P), s, q;
ElemType e;
e.coef = 0.0;
e.expn = -;
SetCurElem(h, e);//设置头结点中的数据元素
for (int i = ; i <= m; i++)
{//依次输入 m 个非零项
scanf("%f%d", &e.coef, &e.expn);
if (!LocateElem(P, e, q, (* cmp)))
{//当前链表中不存在该指数项
if (MakeNode(s, e))
{
InsFirst(q, s);
}
}
}
}//CreatePolyn
/**
algorithm 2.23
*/
void AddPolyn(polynomial &Pa, polynomial &Pb)
{
//多项式加法:Pa = Pa + Pb,利用两个多项式构成和多项式
Link ha = GetHead(Pa);
Link hb = GetHead(Pb);//pa 和 pb 分别指向 Pa 和 Pb 的头结点
Link qa = NextPos(Pa, ha);
Link qb = NextPos(Pb, hb);//qa 和 qb 分别指向 Pa 和 Pb 中当前节点
while (qa && qb)//qa 和 qb均非空
{
ElemType a = GetCurElem(qa);
ElemType b = GetCurElem(qb);//a、b为两表中当前比较元素
switch ((* cmp)(a, b))
{
case -://多项式 Pa 中当前节点的指数值小
{
ha = qa;
qa = NextPos(Pa, qa);//printf("%d\n", qa->data.expn);
break;
}
case ://两者的指数值相等
{
ElemType S = {a.coef + b.coef, a.expn};
if( != S.coef)
{//修改多项式 Pa 中当前节点
SetCurElem(qa, S);
ha = qa;
}
else
{//删除多项式中 Pa 当前节点
DelFirst(ha, qa);
FreeNode(qa);
}
DelFirst(hb, qb);
FreeNode(qb);
qa = NextPos(Pa, ha);
qb = NextPos(Pb, hb);
break;
}
case ://多项式 Pb 当前结点指数值小
{
DelFirst(hb, qb);
InsFirst(ha, qb);
qb = NextPos(Pb, hb);
ha = NextPos(Pa, ha);
break;
}
}//switch
}//while
if (!ListEmpty(Pb))
{
Append(Pa, qb);//链接 Pb 中剩余结点
}
FreeNode(hb);//释放 Pb 的头结点
}//AddPolyn
#endif
四.CPP文件
#include "2_4.h" int main(int argc, char const *argv[])
{
polynomial Pa, Pb, Pc;
int n;
printf("Input n\t");
scanf("%d", &n);
CreatPolyn(Pa, n);
printf("Pa\n");
PrintPolyn(Pa);
printf("Input n\t");
scanf("%d", &n);
CreatPolyn(Pb, n);
printf("Lb\n");
PrintPolyn(Pb);
AddPolyn(Pa, Pb);
printf("La + Lb\n");
PrintPolyn(Pa);
return ;
}
五.测试

六.小结
不要对着伪代码一行行敲代码,一定要在理解的基础上实现算法,否则敲错一个变量导致奇怪的错误也要大费周折才能找到。
数据结构算法C语言实现(六)---2.4一元多项式的表示及相加的更多相关文章
- 数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值
一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚, ...
- 数据结构算法C语言实现(五)---2.3重新定义线性链表及其基本操作
一.简述 ...由于链表在空间的合理利用上和插入.删除时不需要移动等的优点,因此在很多场合下,它是线性表的首选存储结构.然而,它也存在着实现某些基本操作,如求线性表的长度时不如顺序存储结构的缺点:另一 ...
- 数据结构算法C语言实现(二)---2.3线性表的链式表示和实现之单链表
一.简述 [暂无] 二.头文件 #ifndef _2_3_part1_H_ #define _2_3_part1_H_ //2_3_part1.h /** author:zhaoyu email:zh ...
- 数据结构算法C语言实现(二十七)--- 7.2图的遍历
一.简述 栈与队列,DFS与BFS.仅以连接表为例实现. 二.头文件 BFS要用到的头文件 //3_4_part1.h /** author:zhaoyu email:zhaoyu1995.com@g ...
- 数据结构算法C语言实现(二十)--- 6.3.1遍历二叉树
一.简述 二叉树的遍历主要是先序.中序.后序及对应的递归和非递归算法,共3x2=6种,其中后序非递归在实现上稍复杂一些.二叉树的遍历是理解和学习递归及体会栈的工作原理的绝佳工具! 此外,非递归所用的栈 ...
- 数据结构算法C语言实现(十二)--- 3.4循环队列&队列的顺序表示和实现
一.简述 空队列的处理方法:1.另设一个标志位以区别队列是空还是满:2.少用一个元素空间,约定以队列头指针在队尾指针下一位置上作为队列呈满的状态的标志. 二.头文件 //3_4_part1.h /** ...
- 数据结构算法C语言实现(十一)--- 3.4队列的链式表示和实现
一.简介 FIFO. 二.头文件 //3_4_part1.h /** author:zhaoyu email:zhaoyu1995.com@gmail.com date:2016-6-9 note:r ...
- 数据结构算法C语言实现(十)--- 3.3栈与递归的实现
一.简介 汉诺塔问题是递归的一个典型例子,而且书上的讲解很详细,对理解C语言函数及函数传参的工作机制很有帮助,值得一看.而且,递归在我看来和分治.DP.贪心等一样是十分优美的思想,值得学习!!! 二. ...
- 数据结构算法C语言实现(七)--- 3.1栈的线性实现及应用举例
一.简述 栈,LIFO.是操作受限的线性表,和线性表一样有两种存储表示方法.下面以顺序存储为例,实现. 二.ADT 暂无. 三.头文件 //3_1.h /** author:zhaoyu email: ...
随机推荐
- TinyFrame升级之九:实现复杂的查询
本章我们主要讲解如何实现一个复杂的查询.由于目前TinyFrame框架已经投入到了实际的项目生产中,所以我很乐意将项目中遇到的任何问题做以记录并备忘. 这章中,我们提到的查询界面如下所示: 其中,涉及 ...
- left join 条件区别
t1: num | name-----+------ 1 | a 2 | b 3 | c t2: num | value-----+------- 1 | xxx 3 ...
- Ace - Responsive Admin Template
Ace简介: Ace 是一个轻量.功能丰富.HTML5.响应式.支持手机及平板电脑上浏览的管理后台模板,基于CSS框架Bootstrap制作,Bootstrap版本更新至 3.0,Ace – Resp ...
- 利用PowerShell+Jenkins,实现项目的自动化部署
当项目越来越庞大,部署环境越来越多以后,就会越来越依赖于自动化.比如本人公司的项目,目前有6个web和4个windows service,同时本地有两套环境:开发自测试环境和QA测试环境.每次版本发布 ...
- Castle 多继承选择
Castle 多继承选择 很多时候,我们定义了一个接口,但是这个接口会有多种不同的,这时IOC构造函数注入的时候,就需要自动选择对应的实现. public interface ITestService ...
- redis连接数
1.应用程序会发起多少个请求连接?1)对于php程序,以短连接为主.redis的连接数等于:所有web server接口并发请求数/redis分片的个数.2)对于java应用程序,一般使用JedisP ...
- javascript生成GUID的代码
<script type="text/javascript"> var Guid = function(){}; Guid.prototype = { S4:funct ...
- git flow的使用
简介 Gitflow工作流程围绕项目发布定义了严格的分支模型.尽管它比Feature Branch Workflow更复杂一些,但它也为管理更大规模的项目提供了坚实的框架. 与Feature Bran ...
- div两栏等高布局
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- iOS开发--二维码的扫描
一.需要包含头文件 #import <AVFoundation/AVFoundation.h> 二.通过设置<AVCaptureMetadataOutputObjectsDelega ...