数据结构28:广义表及M元多项式
广义表,又称为列表。记作:
广义表可以看作是线性表的推广。两者区别是:线性表中的数据元素只能表示单个数据元素;广义表中的单个数据元素 ai ,既可以是单个元素,也可以是广义表。
原子和子表
在广义表中,单个元素被称为 “原子”;包含的广义表被称为 “子表”。
例如:
- A = () :A 表示一个广义表,只不过表是空的,广义表 A 的长度为 0。
- B = (e) :广义表 B 中只有一个原子 e ,长度为 1。
- C = (a,(b,c,d)) :广义表 C 中有两个元素,原子 a 和子表 (b,c,d) ,广义表C的长度为 2。
- D = (A,B,C) :广义表 D 中有三个元素:子表 A、B、C,长度为 3 ,这种表示方式等同于: D = ((),(e),(b,c,d)) 。
- E = (a,E) :广义表 E 中有两个元素,原子 a 和它本身,长度为 2 。这是一个递归的表,等同于:E = (a,(a,(a,…)))。
表头和表尾
当广义表不为空时,称表中的第一个元素为表的 “表头” ;剩余所有元素组成的表为 “表尾” 。
例如:上边例子中的 D = (A,B,C) ,子表 A 为广义表 D 的表头;而 (B,C) 组成的表为 D 的表尾。
非空广义表是由表头和表尾构成,反过来说也对:给定一个表头和表尾,可以唯一确定一个广义表。
广义表中结点结构
由于广义表中的数据元素类型分为原子和子表,难以使用顺序存储结构表示,所以通常采用链式存储结构。
根据原子和子表的不同,链式存储中的结点需要用两种不同的结构表示。对于原子来说,需要由两部分组成:标志位 + 值域(如图1(A));子表需要由三部分组成:标志位 + 指向表头的指针域 + 指向表尾的指针域(如图1(B))。

图1 广义表的链表结点结构
代码表示:
typedef struct GLNode
{
int tag; //标志域
union
{
char atom; //原子结点的值域
struct
{
struct GLNode *hp, *tp;
}ptr; //子表结点的指针域,hp指向表头;tp指向表尾
};
}*Glist;
例如,使用图1的链表结构表示广义表 C = (a,(b,c,d)),效果图为:

图2 广义表C的结构示意图
实现代码为:
Glist creatGlist(Glist C)
{
// 广义表C
C = (Glist)malloc(sizeof(Glist));
C->tag = ;
// 表头原子‘a’
C->ptr.hp = (Glist)malloc(sizeof(Glist));
C->ptr.hp->tag = ;
C->ptr.hp->atom = 'a';
// 表尾子表(b,c,d),是一个整体
C->ptr.tp = (Glist)malloc(sizeof(Glist));
C->ptr.tp->tag = ;
C->ptr.tp->ptr.hp = (Glist)malloc(sizeof(Glist));
C->ptr.tp->ptr.tp = NULL;
// 开始存放下一个数据元素(b,c,d), 表头为‘b’,表尾为(c,d)
C->ptr.tp->ptr.hp->tag = ;
C->ptr.tp->ptr.hp->ptr.hp = (Glist)malloc(sizeof(Glist));
C->ptr.tp->ptr.hp->ptr.hp->tag = ;
C->ptr.tp->ptr.hp->ptr.hp->atom = 'b';
C->ptr.tp->ptr.hp->ptr.tp = (Glist)malloc(sizeof(Glist));
// 存放子表(c,d),表头为c,表尾为d
C->ptr.tp->ptr.hp->ptr.tp->tag = ;
C->ptr.tp->ptr.hp->ptr.tp->ptr.hp = (Glist)malloc(sizeof(Glist));
C->ptr.tp->ptr.hp->ptr.tp->ptr.hp->tag = ;
C->ptr.tp->ptr.hp->ptr.tp->ptr.hp->atom = 'c';
C->ptr.tp->ptr.hp->ptr.tp->ptr.tp = (Glist)malloc(sizeof(Glist));
// 存放表尾d
C->ptr.tp->ptr.hp->ptr.tp->ptr.tp->tag = ;
C->ptr.tp->ptr.hp->ptr.tp->ptr.tp->ptr.hp = (Glist)malloc(sizeof(Glist));
C->ptr.tp->ptr.hp->ptr.tp->ptr.tp->ptr.hp->tag = ;
C->ptr.tp->ptr.hp->ptr.tp->ptr.tp->ptr.hp->atom = 'd';
C->ptr.tp->ptr.hp->ptr.tp->ptr.tp->ptr.tp = NULL;
return C;
}
结点结构的另一种表示方式
除了上边的那种表示结点的方式,还可以采用另外一种表示形式,不同在于:表结点和原子结点都添加了一个指向下一个数据元素的指针;而子表结点中只保留了指向表头结点的指针,删除了指向表尾的指针。

图3 广义表的另一种结点结构
代码表示为:
typedef struct GLNode
{
int tag; //标志域
union
{
int atom; //原子结点的值域
struct GLNode *hp; //子表结点的指针域,hp指向表头
};
struct GLNode *tp; //这里的tp相当于链表的next指针,用于指向下一个数据元素
}*Glist;
例如,用这种结构结构表示C = (a,(b,c,d)),效果图为:

图4 广义表C的结构示意图
实现代码:
Glist creatGlist(Glist C)
{
C = (Glist)malloc(sizeof(Glist));
C->tag = ;
C->hp = (Glist)malloc(sizeof(Glist));
C->tp = NULL;
// 表头原子a
C->hp->tag = ;
C->atom = 'a';
C->hp->tp = (Glist)malloc(sizeof(Glist));
C->hp->tp->tag = ;
C->hp->tp->hp = (Glist)malloc(sizeof(Glist));
C->hp->tp->tp = NULL;
// 原子b
C->hp->tp->hp->tag = ;
C->hp->tp->hp->atom = 'b';
C->hp->tp->hp->tp = (Glist)malloc(sizeof(Glist));
// 原子c
C->hp->tp->hp->tp->tag = ;
C->hp->tp->hp->tp->atom = 'c';
C->hp->tp->hp->tp->tp = (Glist)malloc(sizeof(Glist));
// 原子d
C->hp->tp->hp->tp->tp->tag = ;
C->hp->tp->hp->tp->tp->atom = 'd';
C->hp->tp->hp->tp->tp->tp = NULL;
return C;
}
总结
在编写代码时,一定要注意不要破坏广义表中数据元素之间的关系,例如:C1 = (a,b,c,d)和 C2 = (a,(b,c),d),两个广义表中数据元素是一样的,但是数据元素之间的关系不同,在 C1 中,各原子之间是并列的,而 C2 中,原子 a 和子表 (b,c) 和 d 是并列的。
补:M元多项式的表示
例如:
这是一个3元多项式(有3个变量:x,y,z),使用广义表表示M元多项式,首先需要对多项式做一下变形:
经过变形后,P(x,y,z)可以这样表示:
经过两轮转化后,P这个 3 元多项式分解成了由 A 多项式和 B 多项式组成的一元多项式(只有一个变元 z ),而 A 也变成了由 C 多项式和 D 多项式组成的一元多项式,…。
当全部转化成能用一元多项式表示时,每一个一元多项式只需要存储各项的指数和系数就可以了。
广义表中每个结点的构成如图5所示:

图5 多项式结点构成
代码表示:
typedef struct MPNode
{
int tag; //区分原子结点和子表结点(0代表原子;1代表子表)
int exp; //存放指数域
union
{
int coef; //存放多项式的系数
struct MPNode *hp; //当多项式系数为子表时,用它
};
struct MPNode *tp; //相当于线性链表的next,指向下一个数据元素
}*MPList;
实现代码:
MPList initP(MPList P)
{
char a[] = "xyz";
MPList F = (MPList)malloc(sizeof(MPList));
F->tag = ;
F->exp = ; // 表示F这个一员多项式中的变元位a[0],也就是x
F->hp = NULL;
F->tp = (MPList)malloc(sizeof(MPList));
F->tp->tag = ;
F->tp->exp = ; // x的指数为0
F->tp->coef = ; // 系数为2
F->tp->tp = NULL; // tp截止,说明F=2;
MPList E = (MPList)malloc(sizeof(MPList));
E->tag = ;
E->exp = ; // E中变元位a[0],即x
E->hp = NULL;
E->tp = (MPList)malloc(sizeof(MPList));
E->tp->tag = ;
E->tp->exp = ;
E->tp->coef = ;
E->tp->tp = (MPList)malloc(sizeof(MPList));
E->tp->tp->tag = ;
E->tp->tp->exp = ;
E->tp->tp->coef = ;
E->tp->tp->tp = NULL;// 截止,E=1*x4+6*x3(x后为它的指数)
MPList D = (MPList)malloc(sizeof(MPList));
D->tag = ;
D->exp = ;// D中变元为a[0],即x
D->hp = NULL;
D->tp = (MPList)malloc(sizeof(MPList));
D->tp->tag = ;
D->tp->exp = ;
D->tp->coef = ;
D->tp->tp = NULL; // 截止,D=3*x5(5是x的指数);
MPList C = (MPList)malloc(sizeof(MPList));
C->tag = ;
C->exp = ; // C中变元为a[0]=x;
C->hp = NULL;
C->tp = (MPList)malloc(sizeof(MPList));
C->tp->tag = ;
C->tp->exp = ;
C->tp->coef = ;
C->tp->tp = (MPList)malloc(sizeof(MPList));
C->tp->tp->tag = ;
C->tp->tp->exp = ;
C->tp->tp->coef = ;
C->tp->tp->tp = NULL; // C=1*x10+2*x6
MPList B = (MPList)malloc(sizeof(MPList));
B->tag = ;
B->exp = ; // B中变元为a[1]=y
B->hp = NULL;
B->tp = (MPList)malloc(sizeof(MPList));
B->tp->tag = ;
B->tp->exp = ;
B->tp->hp = E;
B->tp->tp = (MPList)malloc(sizeof(MPList));
B->tp->tp->tag = ;
B->tp->tp->exp = ;
B->tp->tp->hp = F;
B->tp->tp->tp = NULL; // B=E*y4+F*x1;
MPList A = (MPList)malloc(sizeof(MPList));
A->tag = ;
A->exp = ; // A中变元为a[1]=y;
A->hp = NULL;
A->tp = (MPList)malloc(sizeof(MPList));
A->tp->tag = ;
A->tp->exp = ;
A->tp->hp = C;
A->tp->tp = (MPList)malloc(sizeof(MPList));
A->tp->tp->tag = ;
A->tp->tp->exp = ;
A->tp->tp->hp = D;
A->tp->tp->tp = NULL; // A=C*y3+D*y2;
P = (MPList)malloc(sizeof(MPList));
P->tag = ;
P->exp = ; // 表示表元的数量
P->hp = (MPList)malloc(sizeof(MPList));
P->tp = NULL;
P->hp->tag = ;
P->hp->exp = ; // P中变元为a[2]=z;
P->hp->hp = NULL;
P->hp->tp = (MPList)malloc(sizeof(MPList));
P->hp->tp->tag = ;
P->hp->tp->exp = ;
P->hp->tp->hp = A;
P->hp->tp->tp = (MPList)malloc(sizeof(MPList));
P->hp->tp->tp->tag = ;
P->hp->tp->tp->exp = ;
P->hp->tp->tp->hp = B;
P->hp->tp->tp->tp = (MPList)malloc(sizeof(MPList));
P->hp->tp->tp->tp->tag = ;
P->hp->tp->tp->tp->exp = ;
P->hp->tp->tp->tp->coef = ;
P->hp->tp->tp->tp->tp = NULL; // P=A*z2+B*z1+15
return P;
}
数据结构28:广义表及M元多项式的更多相关文章
- javascript实现数据结构:广义表
原文:javascript实现数据结构:广义表 广义表是线性表的推广.广泛用于人工智能的表处理语言Lisp,把广义表作为基本的数据结构. 广义表一般记作: LS = (a1, a2, ..., an ...
- 数据结构:广义表的实现(Java)
广义表的简单理解在这篇博文中:https://blog.csdn.net/lishanleilixin/article/details/87364496,在此不做赘述. Java实现广义表: pack ...
- 数据结构 c++ 广义表
// CTest.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> #include &l ...
- 数据结构5.4_m元多项式的表示
三元多项式表示如下: P(x,y,z) = x10y3z2 + 2x6y3z2 + 3x5y2z2 + x4y4z + 6x3y4z + 2yz + 15 然后对式子进行变形: P(x,y,z)=(( ...
- 数据结构(C语言第2版)-----数组,广义表,树,图
任何一个算法的设计取决于选定的数据结构,而算法的实现依赖于采用的存储结构. 之前线性表的数据元素都是非结构的原子类型,元素的值是不可再分的.下面学习的这两个线性表是很特殊的,其中数据元素本身也可能是一 ...
- 数据结构算法C语言实现(十九)--- 5.5&5.6&5.7广义表
一.简述 传说Lisp的基本数据结构就是广义表,广义表也是具有典型递归属性的数据结构,此外,由于建表要处理字符串,用C语言处理起来也是一脸懵逼.....最后自己还想写一个将广义表还原成字符串的函数,一 ...
- 广义表操作 (ava实现)——广义表深度、广义表长度、打印广义表信息
广义表是对线性表的扩展——线性表存储的所有的数据都是原子的(一个数或者不可分割的结构),且所有的数据类型相同.而广义表是允许线性表容纳自身结构的数据结构. 广义表定义: 广义表是由n个元素组成的序列: ...
- 【C/C++】实现数据结构广义表
1. 广义表的定义 每个元素可以为Atom,原子,也可以为线性表. 线性表的推广.线性表元素有唯一的前驱和后继,为线性表,而广义表是多层次的线性表 表头:第一个元素,可能是 ...
- 数据结构(C语言版)-第4章 串、数组和广义表
补充:C语言中常用的串运算 调用标准库函数 #include<string.h> 串比较,strcmp(char s1,char s2) 串复制,strcpy(char to,char f ...
随机推荐
- 人脑和CPU
人类的数学运算没有计算机快是因为神经信号速度没有电信号快吗,电信号是光速吧. 不过人类的cpu大脑和存储硬盘和内存超过目前计算机n条街,虽然传输速度慢,但是传输量也是大的,其实计算机就是根据人脑设计的 ...
- Cordova 3.x 配置文件config.xml强制横屏
官方文档: http://cordova.apache.org/docs/en/3.5.0/config_ref_index.md.html#The%20config.xml%20File 添加 &l ...
- webpack3.x看这个就够了
本文介绍webpack3.x的使用 说明,本文前后连贯性很强,建议从头往后看 目录 开始 css文件打包 image文件打包 字体文件打包 json文件打包 csv文件和xml文件打包 多入口文件打包 ...
- jquery ajax中error返回错误解决办法
转自:https://www.jb51.net/article/72198.htm 进入百度搜索此问题,发现有人这么说了一句 Jquery中的Ajax的async默认是true(异步请求),如果想一个 ...
- Hadoop集群 能打开50070端口不能打开8088端口 web浏览器界面
两天时间,知道现在才把这个东西解决 解决的灵感来源于百度知道一句话谢谢这个哥们 谢谢这个哥们! 我的目录是在/home/hadoop/tmp 大家如果遇到这个问题,希望能按照我的办法去试一下 2 ...
- Redis Cluster 伪集群的搭建
简介 为何要搭建Redis集群?Redis是在内存中保存数据的,而我们的电脑一般内存都不大,这也就意味着Redis不适合存储大数据,适合存储大数据的是Hadoop生态系统的Hbase或者是MogoDB ...
- C语言基础问题总结
Double 类型用 %f 接受会产生错误,应该用%lf C语言中SIN,COS的参数为弧度,角度应先转换为弧度才能计算,否则出错 三角形的判断条件,任意两边长度和大于第三边 闰年判断条件整百年为40 ...
- 3-2 zk客户端连接关闭服务端,查看znode
使用ZooKeeper官方提供的Client来连接.路径类似的结构. 连接到我们的门户HOST. quota属于zookeeper.quota是子节点,zookeeper是父节点.quota其实是一个 ...
- Python_pip_03_安装模块出现错误时咋整
>在DOS窗口中到Python安装路径的scripts中执行 pip install pyperclip 出现错误 >>错误提示:Fatal error in launcher: ...
- 100200F Think Positive
传送门 题目大意 给你一个数n和长度为n的序列,序列中的每个数均为1或-1,如果一个点j对于任意的k都满足题目中给的式子,则j是一个合法位置,问这样的j有多少个 分析 这道题有两种方法,分别对应代码1 ...