您的位置:首页 > 理论基础 > 数据结构算法

数据结构基础(三)广义表

2016-01-02 14:32 309 查看
广义表是线性表的推广。区别在于:线性表的元素仅限于原子项;而广义表的元素即可以是原子项,也可以是广义表。

概念

定义

广义表是n (n>=0)个元素a1,a2,a3,…,an的有限序列,其中ai或者是原子项,或者是一个广义表(子表)。不为空时,a1为表头(Header),其余元素组成的表(a2,a3,……,an)是LS的表尾(Tail)

结构

采用链式结构,节点分为原子节点(tag,atom),以及表节点(tag,hp,tp)

tag:0为原子节点,1为表节点

atom:原子节点的值

hp:子表表头

tp:子表表尾

递归特性

由表头、表尾的定义可知:任何一个非空广义表其表头可能是原子,也可能是列表,而其表尾必定是列表。每个表尾又可以继续分为表头,表尾……

实现代码

注意点:

代码中实现了广义表的创建,插入,获取深度、长度,输出广义表字符串等功能。

采用了递归思想实现创建,获取深度。

依照广义表定义,创建时可以每次把字符串分为表头和表尾,依次创建每个表头的节点,最终实现广义表。但考虑到这样做递归次数太多,代码中修改成只递归表节点。

package test;

import java.util.ArrayList;
import java.util.List;

/**
* 广义表
*/
public class GList {

/**
* 广义表的头节点
*/
private Node hNode;
/**
* 广义表的尾部节点,方便添加节点
*/
private Node lastNode;
/**
* 广义表长度
*/
private int length = 0;;

/**
* 广义表节点
*/
private static class Node {
// 0为值节点,1为广义表节点
public int tag;
//原子节点使用的值域
public String atom;
//表节点使用的表头
public Node hp;
//指向下一个节点
public Node tp;

public Node(int tag, String atom) {
this.tag = tag;
this.atom = atom;
}

public Node(int tag, Node hp) {
this.tag = tag;
this.hp = hp;
}

}

/**
* 空构造
*/
public GList() {
hNode = lastNode = null;
}

/**
* 依据字符串构造出广义表
*
* @param gl
*/
public GList(String gl) {
hNode = createGList(gl);
lastNode = getTailNode();
}

/**
* 返回广义表长度
*
* @return
*/
public int getLength() {
return length;
}

/**
* 向广义表中添加元素
* @param n
*/
public void add(Node n) {
length++;
if (lastNode == null) {
hNode = lastNode = n;
return;
}
lastNode = lastNode.tp = n;
}

/**
* 返回广义表头节点
* @return
*/
public Node getHead() {
return hNode;
}

/**
* 返回广义表尾部节点
* @return
*/
public Node getTailNode() {
if (lastNode != null)
return lastNode;

Node n = hNode;
length = 1;
while (n != null && n.tp != null) {
n = n.tp;
length++;
}
return n;
}
/**
* 返回广义表的尾节点
* @return
*/
public GList getTail() {
GList gList=new GList();
gList.hNode=hNode.tp;
return gList;
}

/**
* 获取广义表深度
* @return
*/
public int getGListDepth() {
if (hNode == null)
return 0;
return 1 + getDepth(hNode);
}

@Override
public String toString() {
return doList(hNode);
}

/**
* 以一节点为头节点获取深度
* @param n
* @return
*/
private int getDepth(Node n) {
if (n == null)
return 0;
//如为原子节点则深度为0,表节点=子表深度加1
int depth = (n.tag == 0 ? 0 : 1 + getDepth(n.hp));
//递归比较相邻节点深度
int depthNext = getDepth(n.tp);
return depth > depthNext ? depth : depthNext;
}

/**
* 以一节点为头节点返回生成的广义表字符串
* @param n
* @return
*/
private String doList(Node n) {
if (n == null)
return null;
String result = "(";
boolean isBegin = false;
while (n != null) {
//原子节点直接拼接其atom值
if (n.tag == 0) {
if (isBegin == false) {
result += n.atom;
isBegin = true;
} else {
result += "," + n.atom;
}
}
//表节点进行递归
else {
if (isBegin == false)
result += doList(n.hp);
else {
result += "," + doList(n.hp);
}
}
n = n.tp;
}
result = result.substring(0, result.length()) + ")";
return result;
}

/**
* 根据字符串生成广义表
* @param gl
* @return 返回生成广义表的头结点
*/
private Node createGList(String gl) {
Node hN = null;
Node n = null;
//获取初步分割后的节点集合,此时表节点atom为表字符串,hp未指定
List<Node> list = splitGL(gl);

int size = list.size();
//将表节点hp指定,并连接相邻节点
for (int i = 0; i < size; i++) {
n = list.get(i);
if (n.tag == 1) {
n.hp = createGList(n.atom);
}
if (i > 0)
list.get(i - 1).tp = n;
}
hN = list.get(0);
return hN;
}

/**
* 将广义表字符串单元分割,每个划分单元放入一个Node,划分的字符串放入Node.atom
* @param gl
* @return
*/
private List<Node> splitGL(String gl) {
// 去除左右两边括号
gl = gl.substring(1, gl.length() - 1).trim();
// 最后加上','方便末尾片段的分割
char[] gchar = (gl + ",").toCharArray();
//标记分割字符单元有几个括号
int flag = 0;
//分割字符单元生成的Node集合
List<Node> list = new ArrayList<Node>();
//分割字符单元
String segment = "";

for (int i = 0; i < gchar.length; i++) {
if (gchar[i] == '(')
flag++;
else if (gchar[i] == ')')
flag--;
//若一个字符单元结束
if ((gchar[i] == ',' && flag == 0)) {
if (segment.contains("("))
list.add(new Node(1, segment));
else
list.add(new Node(0, segment));
segment = "";
continue;
}
segment += gchar[i];
}

return list;
}

public static void main(String[] args) {
GList gList = new GList(
"(aa,(aa,bb,cc,(aaa)),c,(aa,(ccc,(eeee)),dd),k)");
gList.add(new Node(0, "haha"));
System.out.println(gList);
System.out.println(gList.getGListDepth());
System.out.println(gList.getLength());
System.out.println("-----------------");
GList gList2 = new GList("(a,b)");
System.out.println(gList2);
System.out.println(gList2.getGListDepth());
System.out.println(gList2.getLength());

}

}/**output:
(aa,(aa,bb,cc,(aaa)),c,(aa,(ccc,(eeee)),dd),k,haha)
4
6
-----------------
(a,b)
1
2*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: