数据结构基础(三)广义表
2016-01-02 14:32
309 查看
广义表是线性表的推广。区别在于:线性表的元素仅限于原子项;而广义表的元素即可以是原子项,也可以是广义表。
tag:0为原子节点,1为表节点
atom:原子节点的值
hp:子表表头
tp:子表表尾
代码中实现了广义表的创建,插入,获取深度、长度,输出广义表字符串等功能。
采用了递归思想实现创建,获取深度。
依照广义表定义,创建时可以每次把字符串分为表头和表尾,依次创建每个表头的节点,最终实现广义表。但考虑到这样做递归次数太多,代码中修改成只递归表节点。
概念
定义:
广义表是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*/
相关文章推荐
- 小猪的数据结构辅助教程——3.2 栈与队列中的链栈
- C/C++,数据结构单链表(采用C++"引用"方法)(寻找节点、在某处插入结点、删除某位置结点)
- C/C++,数据结构实现两个链表的合并(尾插法建立单链表,求链表长度,直接插入排序)
- 数据结构_2:链表:STL
- 数据结构_2:链表:C++
- 数据结构_2:链表:C语言练习
- 学数据结构,是不是一定要先学离散数学
- 数据结构学习——队列
- 数据结构链表总结一
- linux系统的体系结构以及文件数据结构
- 数据结构学习笔记——顺序存储结构
- 09 链表中找出倒数第k个数 & 找出链表正中间的数据
- 8皇后以及N皇后算法探究,回溯算法的JAVA实现,非递归,数据结构“栈”实现
- 数据结构学习——栈
- poj 1988 Cube Stacking 数据结构 并查集
- 数据结构_2:链表:C语言
- 【Java数据结构】链表
- python 数据结构常用的模块
- 小猪的数据结构辅助教程——3.1 栈与队列中的顺序栈
- 【数据结构】之队列的java实现(二)