广义表
广义表的定义
广义表的存储结构
广义表的M元多项式
广义表的递归算法
一、广义表的定义:
广义表(Lists,又称列表)是一种非线性的数据结构,是线性表的一种推广。
广义表一般记作 LS = (d1,d2,....,dn);
其中LS是广义表的名称,n是它的长度;
单元素(数据元素)和子表(广义表)
表头(第一个元素d1)、表尾(剩余元素组成的表)
二、广义表的存储结构:
首先我们看一下顺序存储结构,如:单元素、子表、单元素、子表、子表……
可以看出这样存储很复杂,你不知道要分配多少存储空间给一个元素。
链式存储结构:
每个数据元素用一个结点表示。(两种类型的结点:表结点和元素结点)
(头尾链表存储表示)
可以看到,结点内容包含这些信息
表结点:标志域、指示表头的指针域、指示表尾的指针域
元素结点:标志域、值域
这种结构的三个好处:
指针域的作用是用来判断列表是否为空
容易分清列表中单元素和子表所在层次--?如下图中:BC在同一层,BC的内容在同一层。
最高层的表结点个数即为列表的长度--?比如说D的长度为3,表示元素A,B,C公3个。
其中D为共享表,E为递归表。
(扩展线性链表存储表示)
另一种结点结构的链表表示列表
表结点和原子结点均由三个域组成:标志域、指示表头的指针域和指示表尾的指针域;原子结点的三个域为:标志域、值域和指示表尾的指针域。
一元多项式--线性表
一元多项式可以很容易的表示为线性表如:2X^8-9X5+5*X2+8,构成的线性表为{{2,8}, {-9,5}, {5,2}, {8,0}}
M元多项式---广义表 关联?
广义表的递归算法(对于非递归表且无共享子表的广义表)(递归:基本项 和 归纳项)
可实现广义表的三种操作:
1、求广义表的深度 即表中括弧的重数。
将广义表分解成n个子表,分别(递归)求得每个子表的深度。(递归的终止条件是空表和单元素)
3种情况的广义表的深度分别为:
空表的深度=1;
原子的深度=0;
广义表的深度= Max{子表的深度}+1;
具体实现:
2、复制广义表
3种情况的广义表复制:
空表直接复制;
原结点直接复制得到;
复制表头+表尾 (使用递归)
具体实现:
3、建立广义表的存储结构
3种情况:
空表的情况;
单字符建立的子表(一个原子结点)的情况;
由最简单的子表组合成广义表:广义表与子表的关系,相邻两个子表的关系。
//广义表,包括广义表的建立,求深度,复制; 采用的是将广义表划分为"头"和"尾"的模式。
//这些操作以"(((a,b),(c,d)),(e,(f,g),h),z)"形式的字符串为基础.一对括号代表一个表.
public class GLists {
//节点类型
public static int ATOM = 0;
public static int LIST = 1;
public int tag;//用于区分节点
public Object atom;//原子类型
public GLists hp, tp;//指向表头和表尾
//建立广义表"(((a,b),(c,d)),(e,(f,g),h),z)"这样形式的字符串为内通建立广义表
//同样采用递归方式。结束条件是空表和原子。
//递归建立表头和表尾
public static GLists createGList(GLists L, String s) {
System.out.println(s);
GLists p = null;
GLists q = null;
if (s.equals("()")) {
L = null;//如果是空表
}
else {
L = new GLists();
if (s.length() == 1) {
L.tag = ATOM;
L.atom = s.charAt(0);
}//创建单原子广义表
else {
L.tag = LIST;
p = L;
String sub = s.substring(1, s.length() - 1);
do {//小尾中脱出头,循环建立同一层次的结点
Temp temp = new Temp(sub);
String hsub = sever(temp);
sub = temp.string;
p.hp = createGList(p.hp, hsub);
q = p;//hsub是头建立头
if (!sub.isEmpty()) {//如果有尾
p = new GLists();
p.tag = LIST;
q.tp = p;
}
} while (!sub.isEmpty());
q.tp = null;
}
}
return L;
}
//该函数处理(((a,b),(c,d)),(e,(f,g),h),z)后,hstr = ((a,b),(c,d)) str = (e,(f,g),h),z.
//等于把表头和表尾分开
public static String sever(Temp t) {
String str = t.string;
int n = str.length();
int i = 0;
int k = 0;
char ch;
String hstr = null;
do {
ch = str.charAt(i);
i++;
if (ch == '(') {
k++;
} else if (ch == ')') {
k--;
}
} while (i < n && (ch != ',' || k != 0));
if (i < n) {
hstr = str.substring(0, i - 1);
str = str.substring(i);
} else {
hstr = str;
str = "";
}
t.string = str;
return hstr;
}
//求广义表的深度
public static int GetDeepth(GLists L) {
if (L == null) {
return 1;//空表
}
if (L.tag == ATOM) {
return 0;//原子
}
int max = 0;
GLists p = L;
for (; p != null; p = p.tp) {//求同一层的光仪表元素的最大深度
int tem = GetDeepth(p.hp);
if (tem > max) {
max = tem;
}
}
return max + 1;
}
//复制广义表
public static GLists Copy(GLists M, GLists L) {//复制广义表,把L复制到M
if (L == null) {
M = null;//空表
} else {
M = new GLists();
M.tag = L.tag;
if (M.tag == ATOM) {
M.atom = L.atom;
} else {
M.hp = Copy(M.hp, L.hp);//复制头
M.tp = Copy(M.tp, L.tp);//复制尾
}
}
return M;
}
public static void main(String[] args) {
GLists L = null;
String s = "(((a,b),(c,d)),(e,(f,g),h),z)";
//建表
L = GLists.createGList(L, s);
//求表深度
int len = GLists.GetDeepth(L);
System.out.println(len);
//表复制
GLists M = null;
M = GLists.Copy(M, L);
}
}
//为了应对值传递,只能传递引用拷贝,无法传递“地址”的问题
class Temp {
String string = "";
public Temp(String s) {
string = s;
}
}