广义表是对线性表的扩展——线性表存储的所有的数据都是原子的(一个数或者不可分割的结构),且所有的数据类型相同。而广义表是允许线性表容纳自身结构的数据结构。

广义表定义:

广义表是由n个元素组成的序列:LS = (a1,a2, ... an);其中 ai是一个原子项或者是一个广义表。n是广义表的长度。若ai是广义表,则称为LS的子表。

广义表表头和表尾:  若广义表LS不空,则a1,称为LS的表头,其余元素组成的子表称为表尾。

广义表的长度: 若广义表不空,则广义表所包含的元素的个数,叫广义表的长度。

广义表的深度: 广义表中括号的最大层数叫广义表的深度。

例如:

对广义表LS=((),a,b,(a,b,c),(a,(a,b),c))

表头为子表LSH = ();

表尾为子表LST = (a,b,(a,b,c),(a,(a,b),c));

广义表LS的长度:5

广义表LS的深度:3

对于广义表的操作都是建立在已经构建好的广义表上,那么如何通过一个广义表字符串构造一个广义表?

广义表的存储结构——广义表有多重存储结构,以下只讲代码中使用的存储结构,代码中采用以下存储结构:

tag data pH pT

tag    :tag == 0 ; 表示该节点为原子节点 。tag == 1 ; 表示该节点为表节点

data  :data是原子节点的数据,为表节点时该值域无效。

pH    :广义表的表头——是一个表节点或原子节点。

pT    :广义表的表尾——必定是一个表节点 或者 null。

表节点存储结构选择好了,那么如何来构造广义表呢?(比如:LS = ((),a,b,(a,b,c),(a,(a,b),c))), 根据以下规则,构造出来的广义表如下图:

header表示表头 , 带圈的指针表示由该符号创建的对应的节点(为了图片清晰有些节点没有画)。

对于一个广义表总有一个header节点指向该表的表节点,一个node表示当前正在操作的节点。

当遇到‘(’ 时构造一个表节点,并且将该符号压栈charStack,如果栈中的数据长度 > 1 , 表明广义表的深度加深一层 ,此时将该节点压入栈nodeStack,并且让node的pH节点指向新构造的节点。其代码如下:

if (ts.charAt(i) == mStartSymb) {
tmpNode = new Node(null, null, TAG_TABLE, null);
// tableNode = tableNode.mPt;
symbStack.push(ts.charAt(i));
if (symbStack.size() > 1) {
nodeStck.push(tableNode);
tableNode.mPh = tmpNode;
tableNode = tableNode.mPh;
} else {
tableNode.mPt = tmpNode;
tableNode = tableNode.mPt;
}
}

其中mStartSymb 表示广义表的 '表起始指示符' ,  symbStack.push(ts.charAt(i));将 '表起始指示符压栈' , 接下来判断symbStack栈的大小,代码:

nodeStck.push(tableNode);
tableNode.mPh = tmpNode;
tableNode = tableNode.mPh;

将当前的表节点压栈 , 接着表头指向新的node , 当前节点向前滑动一个位置。

当遇到原子节点符号(如:’a‘) 时,则创建一个原子节点,并且让表头指向该节点,其代码如下:

else {
itemNode = new Node(null, null, TAG_ITEM, ts.charAt(i));
tableNode.mPh = itemNode;
}

当遇到符号 ’,‘ 时构造一个表节点,让当前节点的表尾指向新的节点,其代码如下:

else if (ts.charAt(i) == ',') {
tableNode.mPt = new Node(null, null, TAG_TABLE, null);
tableNode = tableNode.mPt;
}

当遇到符号 ')' 时,做两件事

1、如果  symbStack 的长度 > 1 , 表明此时并没有回到表的最外层,肯定存在一个nodeStack中的节点需要出栈,接着让与之对应的 ’(‘ 符号出栈,其代码如下:

else if (ts.charAt(i) == mEndSymb) {
if (symbStack.isEmpty()) {
throw new IllegalArgumentException(
"IllegalArgumentException in constructor GeneralizedTable!...");
}
if (symbStack.size() > 1) {
tableNode = nodeStck.pop();
}
symbStack.pop();
}

当表字符串结束,切symStack的长度为0时,表明是一个格式正确的表字符串,否则说明该表字符串的格式错误,不予处理。

至此,一个广义表就构造OK了。根据上述原理,构造一个广义表的完整代码如下:

public GeneralizedTable(String genTable) {
if (genTable == null) {
throw new NullPointerException(
"genTable is null in constructor GeneralizedTable!...");
}
initTable(genTable);
} private void initTable(String genTable) {
String ts = genTable.replaceAll("\\s", "");
int len = ts.length();
Stack<Character> symbStack = new Stack<Character>();
Stack<Node> nodeStck = new Stack<Node>();
initSymbolicCharactor(ts);
mGenTable = new Node(null, null, TAG_TABLE, null);
Node itemNode, tableNode = mGenTable, tmpNode;
for (int i = 0; i < len; i++) {
if (ts.charAt(i) == mStartSymb) {
tmpNode = new Node(null, null, TAG_TABLE, null);
// tableNode = tableNode.mPt;
symbStack.push(ts.charAt(i));
if (symbStack.size() > 1) {
nodeStck.push(tableNode);
tableNode.mPh = tmpNode;
tableNode = tableNode.mPh;
} else {
tableNode.mPt = tmpNode;
tableNode = tableNode.mPt;
}
} else if (ts.charAt(i) == mEndSymb) {
if (symbStack.isEmpty()) {
throw new IllegalArgumentException(
"IllegalArgumentException in constructor GeneralizedTable!...");
}
if (symbStack.size() > 1) {
tableNode = nodeStck.pop();
}
symbStack.pop();
} else if (ts.charAt(i) == ',') {
tableNode.mPt = new Node(null, null, TAG_TABLE, null);
tableNode = tableNode.mPt;
} else {
itemNode = new Node(null, null, TAG_ITEM, ts.charAt(i));
tableNode.mPh = itemNode;
}
} if (!symbStack.isEmpty()) {
throw new IllegalArgumentException(
"IllegalArgumentException in constructor GeneralizedTable!...");
}
} private void initSymbolicCharactor(String ts) {
mStartSymb = ts.charAt(0);
switch (mStartSymb) {
case '(':
mEndSymb = ')';
break;
case '{':
mEndSymb = '}';
break;
case '[':
mEndSymb = ']';
break;
default:
throw new IllegalArgumentException(
"IllegalArgumentException ---> initSymbolicCharactor");
}
}

注释:本代码中支持 ( , )  , { , } ,  [ , ]  为"广义表标示符"的广义表字符串(默认是())。

求广义表的长度: 根据广义表长度的定义,该表的长度,等于原子节点或表节点的个数,即 header.pT != null 的个数 , 其代码如下:

public int length() { // 广义表的长度
if (mGenTable == null || mGenTable.mPt == null) {
return -1;
}
int tLen = 0;
Node node = mGenTable;
while (node.mPt != null) {
node = node.mPt;
if (node.mPh == null && node.mPt == null) {
break;
}
tLen++;
}
return tLen;
}

广义表的深度:因为广义表由
表头
表尾 组成 , 所以 , 广义表的深度是 表头、表尾中的最大深度。由此定义,得到如下代码:

public int depth() { // 广义表的深度
if (mGenTable == null) {
throw new NullPointerException("Generalized Table is null !.. ---> method depth");
}
return depth(mGenTable);
} private int depth(Node node) {
if (node == null || node.mTag == TAG_ITEM) {
return 0;
}
int depHeader = 0, depTear = 0;
depHeader = 1 + depth(node.mPh);
depTear = depth(node.mPt);
return depHeader > depTear ? depHeader : depTear;
}

广义表的表头:广义表的第一项称为表头,表头可能是一个原子项和广义表。但是不管如何,他都是第一个的pH指向的内容:其代码如下:

public GeneralizedTable getHeader() {
if (isEmpty())
return null;
Node node = mGenTable.mPt;
GeneralizedTable gt = new GeneralizedTable();
gt.mGenTable.mPt = node.mPh;
return gt;
}

广义表的表尾:广义表的表尾必定是一个广义表,但不管由什么子表组成,都是广义表的pT所指向的内容:求解广义表表尾的代码如下:

public GeneralizedTable getTear() {
if (isEmpty())
return null;
Node node = mGenTable.mPt;
GeneralizedTable gt = new GeneralizedTable();
gt.mGenTable.mPt = node.mPt;
return gt;
}

打印广义表的内容:这里打印广义表内容是指,打印所有原子项中的数据,一个深度优先打印的代码如下:

public void print() {
print(mGenTable);
} private void print(Node node) {
if (node == null) {
return;
}
if (node.mTag == 0) {
System.out.print(node.mData.toString() + " \t");
}
print(node.mPh);
print(node.mPt); }

下面是整个广义表操作的代码:

import java.util.Stack;

/**
* 广义表操作:
* 1、广义表的构造 :
* 1.1 构造一个空的广义表
* 1.2 根据现有的广义表,构造一个新的广义表
* 1.3 根据广义表字符串构造一个广义表
* 2、广义表的深度
* 3、广义表的长度
* 4、按照深度优先顺序打印广义表
* 5、求广义表表头
* 6、求广义表表尾
*
*/
public class GeneralizedTable { public static final int TAG_ITEM = 0; // 原子节点
public static final int TAG_TABLE = 1; // 表节点
/*
* 广义表支持的符号包括'(' , ')' , '{' , '}' , '[' , ']'
* 广义表表示符号,使用字符串构造广义表时第一个字符必须是'(', '{' , '[' 之一 并以')' , '}' , ']' 之一结束,
* 并且各符号相对应
*/
private char mStartSymb = '(';
private char mEndSymb = ')';
private Node mGenTable; public GeneralizedTable() {
mGenTable = new Node(null, null, TAG_TABLE, null);
} // 使用广义表 src 构造一个新的广义表
public GeneralizedTable(GeneralizedTable src) {
if (src != null) {
mGenTable = src.mGenTable;
} } /**
* @param genTable
*/
public GeneralizedTable(String genTable) {
if (genTable == null) {
throw new NullPointerException(
"genTable is null in constructor GeneralizedTable!...");
}
initTable(genTable);
} private void initTable(String genTable) {
String ts = genTable.replaceAll("\\s", "");
int len = ts.length();
Stack<Character> symbStack = new Stack<Character>();
Stack<Node> nodeStck = new Stack<Node>();
initSymbolicCharactor(ts);
mGenTable = new Node(null, null, TAG_TABLE, null);
Node itemNode, tableNode = mGenTable, tmpNode;
for (int i = 0; i < len; i++) {
if (ts.charAt(i) == mStartSymb) {
tmpNode = new Node(null, null, TAG_TABLE, null);
// tableNode = tableNode.mPt;
symbStack.push(ts.charAt(i));
if (symbStack.size() > 1) {
nodeStck.push(tableNode);
tableNode.mPh = tmpNode;
tableNode = tableNode.mPh;
} else {
tableNode.mPt = tmpNode;
tableNode = tableNode.mPt;
}
} else if (ts.charAt(i) == mEndSymb) {
if (symbStack.isEmpty()) {
throw new IllegalArgumentException(
"IllegalArgumentException in constructor GeneralizedTable!...");
}
if (symbStack.size() > 1) {
tableNode = nodeStck.pop();
}
symbStack.pop();
} else if (ts.charAt(i) == ',') {
tableNode.mPt = new Node(null, null, TAG_TABLE, null);
tableNode = tableNode.mPt;
} else {
itemNode = new Node(null, null, TAG_ITEM, ts.charAt(i));
tableNode.mPh = itemNode;
}
} if (!symbStack.isEmpty()) {
throw new IllegalArgumentException(
"IllegalArgumentException in constructor GeneralizedTable!...");
}
} private void initSymbolicCharactor(String ts) {
mStartSymb = ts.charAt(0);
switch (mStartSymb) {
case '(':
mEndSymb = ')';
break;
case '{':
mEndSymb = '}';
break;
case '[':
mEndSymb = ']';
break;
default:
throw new IllegalArgumentException(
"IllegalArgumentException ---> initSymbolicCharactor");
}
} public void print() {
print(mGenTable);
} private void print(Node node) {
if (node == null) {
return;
}
if (node.mTag == 0) {
System.out.print(node.mData.toString() + " \t");
}
print(node.mPh);
print(node.mPt); } public int depth() { // 广义表的深度
if (mGenTable == null) {
throw new NullPointerException("Generalized Table is null !.. ---> method depth");
}
return depth(mGenTable);
} private int depth(Node node) {
if (node == null || node.mTag == TAG_ITEM) {
return 0;
}
int depHeader = 0, depTear = 0;
depHeader = 1 + depth(node.mPh);
depTear = depth(node.mPt);
return depHeader > depTear ? depHeader : depTear;
} public int length() { // 广义表的长度
if (mGenTable == null || mGenTable.mPt == null) {
return -1;
}
int tLen = 0;
Node node = mGenTable;
while (node.mPt != null) {
node = node.mPt;
if (node.mPh == null && node.mPt == null) {
break;
}
tLen++;
}
return tLen;
} public GeneralizedTable getHeader() {
if (isEmpty())
return null;
Node node = mGenTable.mPt;
GeneralizedTable gt = new GeneralizedTable();
gt.mGenTable.mPt = node.mPh;
return gt;
} public GeneralizedTable getTear() {
if (isEmpty())
return null;
Node node = mGenTable.mPt;
GeneralizedTable gt = new GeneralizedTable();
gt.mGenTable.mPt = node.mPt;
return gt;
} public boolean isEmpty() {
if (mGenTable == null) {
return true;
}
Node node = mGenTable.mPt;
return node == null || node.mPh == null;
} public class Node {// 广义表节点
Node mPh; // 广义表的表节点
Node mPt; // 广义表表尾节点
int mTag; // mTag == 0 , 院子节点 ; mTag == 1 , 表节点 。
Object mData; // 广义表的数据值 public Node(Node ph, Node pt, int tag, Object data) {
mPh = ph;
mPt = pt;
mTag = tag;
mData = data;
}
} /**
* @param args
*/
public static void main(String[] args) {
// String tStr = "((),(a,b,c),a,d,((d,g,(c))),(k,g),c)";
String p = "((),a,b,(a,b,c),(a,(a,b),c))";
String p2 = "((()),2)";
// String space = "()";
String big = "{{a,b},{{a,g},{h},{a,n,f,{a,b,c}}},c}";
String middle = "[[p],[[d,f,[g]]],[h],[2]]";
GeneralizedTable gTab = new GeneralizedTable(middle);
// GeneralizedTable header, tear;
// // gTab.print();
// // System.out.println();
System.out.println("length: " + gTab.length());
System.out.println("depth: " + gTab.depth());
//
// header = gTab.getHeader();
// if (header != null) {
// System.out.println("header: ");
// header.print();
// }
// tear = gTab.getTear();
//
// if (tear != null) {
// System.out.println("tear: ");
// tear.print();
// }
// gTab.print();
// System.out.println();
// GeneralizedTable gTab4 = null;
// GeneralizedTable gTab2 = new GeneralizedTable(gTab4);
// gTab2.print();
// gTab2 = new GeneralizedTable(gTab);
// gTab2.print();
} }

广义表的内容就先写到这里 , 后续有新内容再补充 。

广义表操作 (ava实现)——广义表深度、广义表长度、打印广义表信息的更多相关文章

  1. CoreData多表操作.

    这次给大家带来的是CoreData多表操作的使用. 首先我们要对CoreData来进行多表操作我们先要创建至少两个实体在工程中. 在创建完成这两个对应的工程实体文件和工程中的类文件后我们现在需要创建一 ...

  2. 数据库 -- mysql表操作

    一,存储引擎介绍 存储引擎即表类型,mysql根据不同的表类型会有不同的处理机制 详见:https://www.cnblogs.com/peng104/p/9751738.html 二,表介绍 表相当 ...

  3. 数据库_mysql多表操作

    多表操作        实际开发中,一个项目通常需要很多张表才能完成.例如:一个商城项目就需要分类表(category).商品表(products).订单表(orders)等多张表.且这些表的数据之间 ...

  4. Hive 基本语法操练(一):表操作

    Hive 和 Mysql 的表操作语句类似,如果熟悉 Mysql,学习Hive 的表操作就非常容易了,下面对 Hive 的表操作进行深入讲解. **(1)先来创建一个表名为student的内部表** ...

  5. Django-website 程序案例系列-18 多表跨表操作优化

    详解Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化 在数据库有外键的时候,使用 select_related() 和 pref ...

  6. Mysql常用表操作 | 单表查询

    160905 常用表操作 1. mysql -u root -p 回车 输入密码   2. 显示数据库列表 show databases     3. 进入某数据库 use database data ...

  7. Sql Server系列:数据表操作

    表是用来存储数据和操作数据的逻辑结构,用来组织和存储数据,关系数据库中的所有数据都表现为表的形式,数据表由行和列组成.SQL Server中的数据表分为临时表和永久表,临时表存储在tempdb系统数据 ...

  8. MySQL连表操作之一对多

    引入 当我们在数据库中创建表的时候,有可能某些列中值内容量很大,而且重复. 例子:创建一个学生表,按学校年纪班级分,表的内容大致如下: id name partment 1 xxx x学校x年级x班级 ...

  9. 学习MySQL之单表操作(二)

    ##单表操作 ##创建表 CREATE TABLE t_employee( empno ), ename ), job ), MGR ), Hiredate DATE DEFAULT '0000-00 ...

随机推荐

  1. 【Unity/Kinect】显示Kinect摄像头内容,屏幕显示环境背景及人体投影

    最近学习用Unity做些体感小游戏,使用Kinect的Unity插件,结合一些官方Demo学习(网上资源用Unity做的较少,蛋疼).插件及其Demo就在Unity商店里搜Kinect即可找到,其中下 ...

  2. mysql按年度、季度、月度、周、日统计查询的sql语句

    本文介绍一些mysql中用于查询的sql语句,包括按年度.季度.月度.周.日统计查询等,有需要的朋友,可以参考下. 一.年度查询 查询 本年度的数据   SELECT * FROM blog_arti ...

  3. Hive UDF IP解析(二):使用geoip2数据库自定义UDF

    开发中经常会碰到将IP转为地域的问题,所以以下记录Hive中自定义UDF来解析IP. 使用到的地域库位maxmind公司的geoIP2数据库,分为免费版GeoLite2-City.mmdb和收费版Ge ...

  4. Ubuntu之命令壁纸

  5. AOP(Aspect Oriented Programming),即面向切面编程

    AOP AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.OOP引入 ...

  6. e558. 在Applet中多图片交互显示

    This is the simplest applet to animate an array of images. In practice, you should use double-buffer ...

  7. jQuery数组处理详解(转)

    1. $.each(array, [callback]) 遍历[常用] 解释: 不同于例遍 jQuery 对象的 $.each() 方法,此方法可用于例遍任何对象(不仅仅是数组哦~). 回调函数拥有两 ...

  8. linux -- ubuntu 14.10开机出现错误“Error found when loading /root/.profile”解决

    修改完root权限自动登录后,发现开机出现以下提示: Error found when loading /root/.profile stdin:is not a tty ………… 解决方法:在终端中 ...

  9. linux -- Ubuntu报错“unable to locate package...”

    有时候在Ubuntu命令行中执行安装某个文件的时候,如:sudo apt-get install xinit ,报 “unable to locate package...” 错误,解决办法如下 1. ...

  10. Yii2框架加入API Modules

    一.环境部署 1. read fucking Yii Documents. http://www.yiichina.com/doc/guide/2.0 2. 了解依赖注入模式 Java描写叙述: ht ...