树-孩子兄弟表示法的实现

1.什么是树

树状图是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:
每个节点有零个或多个子节点;没有父节点的节点称为根节点;每一个非根节点有且只有一个父节点;除了根节点外,每个子节点可以分为多个不相交的子树;

图解(灵魂画师)

2.树的相关知识

节点的度:一个节点含有的子树的个数称为该节点的度;
叶节点或终端节点:度为0的节点称为叶节点;
非终端节点或分支节点:度不为0的节点;
双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点;
孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点;
兄弟节点:具有相同父节点的节点互称为兄弟节点;
树的度:一棵树中,最大的节点的度称为树的度;
节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
树的高度或深度:树中节点的最大层次;
堂兄弟节点:双亲在同一层的节点互为堂兄弟;
节点的祖先:从根到该节点所经分支上的所有节点;
子孙:以某节点为根的子树中任一节点都称为该节点的子孙。
森林:由m(m>=0)棵互不相交的树的集合称为森林;

遍历表达法有3种方法:先序遍历、中序遍历、后序遍历

定义一棵树的根结点层次为1,其他节点的层次是其父结点层次加1。一棵树中所有结点的层次的最大值称为这棵树的深度。

3.树的实现

树的实现主要有三个:

1.父节点表示法:该方法主要思路是,每个节点存储父节点的位置,这样就构成一棵树

2.孩子链表示法:该方法的主要思路是,每个节点用数组存储孩子位置,不过这个表示法有个致命的缺陷,就是造成大量空间上的浪费,因为数组最大的长度必定和最多的度相等,但是并不是每个子树都有那么多度,所以造成空间上的浪费;

3.兄弟孩子节点表示法:该方法主要思路是:每个节点存储孩子,兄弟节点位置,本次就用这个表示法实现

下面代码只实现了添加功能,有空再补上其他功能,其他功能也是大同小异,至于为什么有个flag变量,因为我觉得树里存在重复的变量,所以用flag来唯一标识一个树


package Tree;

/*
 * 树的整体
 * @author WLNSSS
 * @time 2017.12.22
 * */
public class MyTree<T> {

	// 记录根树
	private Node root;

	// 记录节点数
	private int nodeCount;
	
	// 记录节点标识的位置
	private int superFlag;

	public MyTree(T data) {
		//初始化,构造器先装配一个根节点
		root = new Node(data);
	}
	// 在指定位置添加节点
	public void add(T data, int flag) {

		// 定位到指定的位置
		Node point = getNodePost(flag);

		// 错误检查,判断是否是空,如果空抛出异常
		if (point == null) {
			throw new NullPointerException("没有此元素");
		} else {

			// 判断孩子节点空或非空,然后进行不同的操作
			if (point.getChlid() == null) {
				point.setChlid(new Node(data));
			}

			if (point.getChlid() != null) {
				Node temp = point.getChlid();

				Node newNode = new Node(data);
				newNode.setBrother(temp);

				point.setChlid(newNode);

			}
			
			// 元素标识+1
			flag++;
		}
	}

	// 定位节点位置,找出该节点
	public Node getNodePost(int flag) {

		// 调用另外一个复用方法实现
		return getNodePost(flag, root);

	}

	// 定位节点位置,找出该节点
	private Node getNodePost(int flag, Node ponit) {

		// 节点指针,先从root节点开始递归
		Node point = root;

		// 当递归到一个元素的flag等于要查找的flag则返回当前的指针
		if (point.flag == flag) {
			return point;
		}

		// 若兄弟节点非空,则递归取出元素
		if (point.getBrother() != null) {
			return getNodePost(flag, point.getBrother());
		}

		// 若子节点非空,则递归取出元素
		if (point.getChlid() != null) {
			return getNodePost(flag, ponit.getChlid());
		}

		// 若没找到则返回null
		return null;
	}

	/*
	 * 树的节点(内部类)
	 */
	private class Node {

		// 存储的数据
		T data;

		

		// 子节点位置
		Node chlid;

		// 兄弟节点位置
		Node brother;

		// 唯一标识该节点的变量
		int flag;
		
		public T getData() {
			return data;
		}

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

		public Node getChlid() {
			return chlid;
		}

		public void setChlid(Node chlid) {
			this.chlid = chlid;
		}

		public Node getBrother() {
			return brother;
		}

		public void setBrother(Node brother) {
			this.brother = brother;
		}

		public Node(T data) {
			this(data, null, null,superFlag);
		}

		public Node(T data, Node chlid, Node brother,int flag) {

			this.data = data;
			this.chlid = chlid;
			this.brother = brother;
			this.flag = flag;
		}
		
		

	}
	
	
	public static void main(String[] args) {
		MyTree<Integer> myTree = new MyTree(12);
		myTree.add(1,0);
		myTree.add(2,0);
		System.out.println(myTree.root.chlid.brother.getData());
	}

}



  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值