数据结构之广义表

源代码见:点击打开链接

1.定义

    广义表是对线性表的扩展,在线性表中,表中元素具有原子性,不可分解。如果允许表中的元素具有某种结构,这就引入了广义表的概念。广义表的定义如下:

    它是n(n>0)个数据元素a0,a1,……,an-1组成的有限序列,记为GList=(a0,a1,……,an-1),其中,ai(0<=i<n)是原子或子广义表,原子是不可分解的数据元素。

    语法图如下:

    

    举个例子:

中国(北京,上海,江苏(南京,苏州),浙江(杭州))

    

2.数据结构

    结构:

                广义表节点(data数据域,child子表地址域,next后继结点地址域)

    举例:已知三个有名广义表

              L(a,b)

              T(c,L(a,b))

              G(d,L(a,b),T(c,L(a,b)))

G的存储结构如下:


    

    为什么需要头节点?便于在表头增加删除结点。如果不要头结点,那么对广义表的表头添加删除,将可能影响其他广义表中元素。比如,上面G的存储结构改为不要头结点的方式。如下:


    如果此时通过G访问子表L并删除L中的第一个结点a后,G中L结点的child指向原a结点的后继结点b。而这样的删除并没有影响到T表中的L结点的child域。如下:


3.广义表的设计实现

    广义表的基本操作:遍历,求深度,插入元素,删除元素,查找元素,判读是否为空广义表。

uml图如下:


说明:

head:广义表头结点

GenList<T>():初始化广义表,也就是让head=new GenNode<T>();

boolean depth():求广义表的深度

int insert(int i,T t):插入原子作为第i个元素,如果插入成功返回1,否则返回0

int insert(int i,GenList<T> gl):插入子广义表作为第i个元素,如果插入成功返回1,否则返回0

int remove(int i):删除第i个元素,删除成功返回1,否则返回0

T getElement(int i):获取广义表第i个元素

T setElement(int i,T t):将广义表的第i个元素设置为t。设置成功返回1,否则返回0


data:元素数据域,是一个T类型的数据

child:地址域,指向子广义表

next:地址域,指向后继结点(其实next(GenNode<T>)的类型可以和child(GenList<T>)的类型一样,因为他们都有共同特征,可以作为广义表的元素。只不过作为GenNode<T>类型的next没有作为GenList<T>类型的child一些操作方法。这让我想起了java设计模式的组合模式,这提供了一种实现广义表的另一种方法)

GenNode<T>():初始化data,child,next

GenNode<T>(T t):通过t,让data=t;

GenNode<T>(T t,GenList<T> c,GenNode<T> n):用t,c,n分别初始化data,child,next 


广义表的遍历(注意以下的广义表的遍历和求深度的方法都是针对再入表的,不适用于递归表,不信你试试!),采用的是递归的方法,其流程图如下:


代码如下:

public String toString() {
		return this.toString("");
	}

	public String toString(String str) {
		str += "(";
		for (GenNode<T> p = this.head.getNext(); p != null; p = p.getNext()) {
			if (p.getChild() == null) {
				str += p.getData().toString();
			} else {
				str += p.getChild().toString();
			}
			if (p.getNext() != null) {
				str += ",";
			}
		}
		return str + ")";
	}

测试代码:

GenList<Integer> L=new GenList<Integer>();
		L.insert(1);
		L.insert(2);
		GenList<Integer> T=new GenList<Integer>();
		T.insert(3);
		T.insert(L);
		GenList<Integer> G=new GenList<Integer>();
		G.insert(4);
		G.insert(L);
		G.insert(T);
		System.out.println(G.toString());

运行结果:


广义表求深度(针对再入表)的流程图如下:


代码如下:

public int depth() {
		int temp = 0;
		int max = 0;
		GenNode<T> p = this.head.getNext();
		for (; p != null; p = p.getNext(), temp = 0) {
			if (p.getChild() == null) {
				temp++;
			} else {
				temp = temp + 1 + (p.getChild()).depth();
			}

			if (max < temp) {
				max = temp;
			}

		}
		return max;
	}c

测试代码:

public class Main {

	/**
	 * @auther 冯利
	 * @version 创建时间:2018年5月25日  下午8:01:35
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		GenList<Integer> L=new GenList<Integer>();
		L.insert(1);
		L.insert(2);
		GenList<Integer> T=new GenList<Integer>();
		T.insert(3);
		T.insert(L);
		GenList<Integer> G=new GenList<Integer>();
		G.insert(4);
		G.insert(L);
		G.insert(T);
		//GenList<Integer> Z=new GenList<Integer>();
		//Z.insert(Z);
		//G.remove();
		System.out.println(G.toString());
		System.out.println(G.depth());
		System.out.println(L.toString());
		System.out.println(L.depth());
		System.out.println(T.toString());
		System.out.println(T.depth());
		//System.out.println(Z.toString());
		//System.out.println(Z.depth());
	}

运行结果:



GenList.java

package genList;

/**
 * 
 * @author 冯利
 * @version 创建时间:2018年5月24日 下午12:49:22
 * @param <T>
 *            原子结点类型
 */
public class GenList<T> {
	// 头结点
	private GenNode<T> head;

	// 表示广义表的大小(没有考虑深度)
	int count = 0;

	/**
	 * 初始化头结点
	 */
	public GenList() {
		head = new GenNode<T>();
	}

	/**
	 * 判读广义表是否为空
	 * 
	 * @auther 冯利
	 * @version 创建时间:2018年5月24日 下午1:05:01
	 * @return
	 */
	boolean isEmpty() {
		if (head == null || head.next == null) {
			return true;
		}
		return false;
	}

	public int depth() {
		int temp = 0;
		int max = 0;
		GenNode<T> p = this.head.getNext();
		for (; p != null; p = p.getNext(), temp = 0) {
			if (p.getChild() == null) {
				temp++;
			} else {
				temp = temp + 1 + (p.getChild()).depth();
			}

			if (max < temp) {
				max = temp;
			}

		}
		return max;
	}

	/**
	 * 求广义表的大小
	 * 
	 * @auther 冯利
	 * @version 创建时间:2018年5月24日 下午1:09:19
	 * @return
	 */
	int size() {
		return count;
	}

	/**
	 * 插入t作为广义表的第i个元素
	 * 
	 * @auther 冯利
	 * @version 创建时间:2018年5月24日 下午1:19:57
	 * @param i
	 * @param t
	 * @return
	 */
	int insert(int i, T t) {
		// 插入点位置大于广义表可插位置
		if (i > count) {
			return 0;
		}
		GenNode<T> temp = head;
		for (int j = 0; j < i; ++j) {
			temp = temp.next;
		}
		GenNode<T> n = new GenNode<T>(t);
		n.setNext(temp.getNext());
		temp.setNext(n);
		++count;
		return 1;

	}

	public int insert(int i, GenList<T> gl) {
		// 插入点位置大于广义表可插位置
		if (i > count) {
			return 0;
		}
		GenNode<T> temp = head;
		for (int j = 0; j < i; ++j) {
			temp = temp.next;
		}
		GenNode<T> n = new GenNode<T>();
		n.setNext(temp.getNext());
		n.setChild(gl);
		temp.setNext(n);
		++count;
		return 1;

	}

	public void insert(GenList<T> gl) {
		insert(count, gl);
	}

	public void insert(T t) {
		insert(count, t);
	}

	public String toString() {
		return this.toString("");
	}

	public String toString(String str) {
		str += "(";
		for (GenNode<T> p = this.head.getNext(); p != null; p = p.getNext()) {
			if (p.getChild() == null) {
				str += p.getData().toString();
			} else {
				str += p.getChild().toString();
			}
			if (p.getNext() != null) {
				str += ",";
			}
		}
		return str + ")";
	}

	public int remove(int i) {
		// 插入点位置大于广义表可插位置
		if (i >= count) {
			return 0;
		}
		GenNode<T> temp = head;
		for (int j = 0; j < i; ++j) {
			temp = temp.next;
		}
		temp.setNext(temp.getNext().getNext());
		--count;
		return 1;

	}

	public void remove() {
		remove(count - 1);
	}

	GenNode<T> getElement(int i) {
		// 插入点位置大于广义表可插位置
		if (i >= count) {
			return null;
		}
		GenNode<T> temp = head;
		for (int j = 0; j < i; ++j) {
			temp = temp.next;
		}
		return temp.getNext();

	}

	public void setElement(int i, T t) {
		// 插入点位置大于广义表可插位置
		if (i >= count) {
			return;
		}
		GenNode<T> temp = head;
		for (int j = 0; j < i; ++j) {
			temp = temp.next;
		}
		GenNode<T> n = new GenNode<T>(t);
		n.setNext(temp.getNext().getNext());
		temp.setNext(n);
		return;

	}

	/**
	 * 
	 * @author 冯利
	 * @version 创建时间:2018年5月24日 下午12:49:37
	 * @param <T>
	 */
	class GenNode<T> {
		private T data;
		private GenList<T> child;
		private GenNode<T> next;

		public GenNode() {
			data = null;
			child = null;
			next = null;
		}

		public GenNode(T t, GenList<T> c, GenNode<T> n) {
			data = t;
			child = c;
			next = n;
		}

		public GenNode(T t) {
			data = t;
			child = null;
			next = null;
		}

		public T getData() {
			return data;
		}

		public void setData(T data) {
			this.data = data;
		}

		public GenList<T> getChild() {
			return child;
		}

		public void setChild(GenList<T> child) {
			this.child = child;
		}

		public GenNode<T> getNext() {
			return next;
		}

		public void setNext(GenNode<T> next) {
			this.next = next;
		}

	}
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值