一.简述

  利用链表表示稀疏多项式,并基于之前的一些操作(编程实现上还是有所不同的)组合新的操作实现一元多项式的表示及相加。

  二.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一元多项式的表示及相加的更多相关文章

  1. 数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值

    一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚, ...

  2. 数据结构算法C语言实现(五)---2.3重新定义线性链表及其基本操作

    一.简述 ...由于链表在空间的合理利用上和插入.删除时不需要移动等的优点,因此在很多场合下,它是线性表的首选存储结构.然而,它也存在着实现某些基本操作,如求线性表的长度时不如顺序存储结构的缺点:另一 ...

  3. 数据结构算法C语言实现(二)---2.3线性表的链式表示和实现之单链表

    一.简述 [暂无] 二.头文件 #ifndef _2_3_part1_H_ #define _2_3_part1_H_ //2_3_part1.h /** author:zhaoyu email:zh ...

  4. 数据结构算法C语言实现(二十七)--- 7.2图的遍历

    一.简述 栈与队列,DFS与BFS.仅以连接表为例实现. 二.头文件 BFS要用到的头文件 //3_4_part1.h /** author:zhaoyu email:zhaoyu1995.com@g ...

  5. 数据结构算法C语言实现(二十)--- 6.3.1遍历二叉树

    一.简述 二叉树的遍历主要是先序.中序.后序及对应的递归和非递归算法,共3x2=6种,其中后序非递归在实现上稍复杂一些.二叉树的遍历是理解和学习递归及体会栈的工作原理的绝佳工具! 此外,非递归所用的栈 ...

  6. 数据结构算法C语言实现(十二)--- 3.4循环队列&队列的顺序表示和实现

    一.简述 空队列的处理方法:1.另设一个标志位以区别队列是空还是满:2.少用一个元素空间,约定以队列头指针在队尾指针下一位置上作为队列呈满的状态的标志. 二.头文件 //3_4_part1.h /** ...

  7. 数据结构算法C语言实现(十一)--- 3.4队列的链式表示和实现

    一.简介 FIFO. 二.头文件 //3_4_part1.h /** author:zhaoyu email:zhaoyu1995.com@gmail.com date:2016-6-9 note:r ...

  8. 数据结构算法C语言实现(十)--- 3.3栈与递归的实现

    一.简介 汉诺塔问题是递归的一个典型例子,而且书上的讲解很详细,对理解C语言函数及函数传参的工作机制很有帮助,值得一看.而且,递归在我看来和分治.DP.贪心等一样是十分优美的思想,值得学习!!! 二. ...

  9. 数据结构算法C语言实现(七)--- 3.1栈的线性实现及应用举例

    一.简述 栈,LIFO.是操作受限的线性表,和线性表一样有两种存储表示方法.下面以顺序存储为例,实现. 二.ADT 暂无. 三.头文件 //3_1.h /** author:zhaoyu email: ...

随机推荐

  1. DWZ中Tree树形菜单的treeCheck如何获取返回值解决方案

    最近在对DWZ和asp.net MVC3进行整合,其中遇到了很多问题,总算一一解决了,今天就说说题目所示的问题解决方案. 想做一个基于角色的权限管理,要对每一个Action进行权限控制.就想用DWZ的 ...

  2. Spring Security笔记:登录尝试次数限制

    今天在前面一节的基础之上,再增加一点新内容,默认情况下Spring Security不会对登录错误的尝试次数做限制,也就是说允许暴力尝试,这显然不够安全,下面的内容将带着大家一起学习如何限制登录尝试次 ...

  3. PhoneGap奇怪的现象:File FileTransfer download, 手机相册检测不到下载下来的图片(解决)

    我有个从服务器下载相片的功能在使用 File FileTransfer download api时,碰到了很奇怪的现象:图片已经从服务器里下载了,手机文件夹里也可以看到下载过来的图片,但是我的手机相册 ...

  4. 深入理解OOP(第一天):多态和继承(初期绑定和编译时多态)

    在本系列中,我们以CodeProject上比较火的OOP系列博客为主,进行OOP深入浅出展现. 无论作为软件设计的高手.或者菜鸟,对于架构设计而言,均需要多次重构.取舍,以有利于整个软件项目的健康构建 ...

  5. javascript 中加’var‘和不加'var'的区别,你真的懂吗?

    没看之前千万别说我是标题党,这个问题真的有好多淫都不懂!!! 大家都看了很多文章,都说避免隐式声明全局变量,就是说声明变量前必须加'var',那加了'var'和不加'var'到底有啥区别呢? 先来看一 ...

  6. js的浅拷贝和深拷贝

    转载:http://www.jb51.net/article/91906.htm //深拷贝,并且把合并后的值放到第二个参数里 function deepCopy(p, c) { var c = c ...

  7. TRUNK的作用功能.什么是TRUNK

    TRUNK的作用功能.什么是TRUNK(转)  [复制链接]   发表于 2011-11-24 11:01 | 来自  51CTO网页 在技术领域中把TRUNK翻译为中文是“主干.干线.中继线.长途线 ...

  8. Hibernate之Annotation(注解的方式,非映射)

    在hibernate 3.0之后,可以建立一个符合JPA标准的Annotation,以hibernate3.3.2GA为例 Annotation 以 hibernate Annotation 3.3. ...

  9. if -else 条件语句原理

    #!/usr/bin/python # coding utf-8 name = '?' if name == 'python': print('欢迎BOSS') else: print('输入错误')

  10. android -- 之PopupWindow的使用

    LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE); View contentVi ...