关于树的一些总结

最近学习java的相关内容,涉及到数据结构中树的一些操作,先总结一下,以后慢慢完善

树的主要操作有:

  1. 基本操作(添加,删除,查找一个结点)
  2. 遍历(前序,中序,后序,层序)
  3. 创建一颗树(根据前序遍历的格式;根据前序和中序遍历);销毁树
  4. 判断一颗树是否平衡;判断两棵树是否相等
  5. 获取树的高度和宽度
  6. .等等。。。
代码如下:


/*定义树的结点*/
class BTNode{
	char data;
	BTNode leftNode;
	BTNode rightNode;
	public BTNode(){}
	public BTNode(char data) {
		this.data = data;
	}
}
/**
* 定义树的数据结构
*/
public class BTree{
	private BTNode root;
	public BTree() {}
	/*初始化根节点*/
	public BTree(char rootData) {
		this.root = new BTNode(rootData);
	}
	
	/*根据前序遍历创建树*/
	public BTree(char[] arr){
		this.arr = arr;
		this.root = createTree();
	}

	//使用递归,查找一个结点
	public BTNode search(BTNode root, char data){
		BTNode temp = null;
		if(root != null){
			if (root.data == data) {
				return root;
			}else {
				temp = search(root.leftNode, data);
				if(temp == null)
					return search(root.rightNode, data);
			}
		}
		return temp;
	}

	//在指定的结点上增加一个结点,type为0时添加左结点,为1时添加右结点
	public void add(char parentData, char data, int type){
		BTNode node = new BTNode(),tempNode;
		//找到parentData的结点
		tempNode = search(root, parentData);
		if(tempNode != null){
			node.data = data;
			if (type == 0)
				tempNode.leftNode = node;
			if (type == 1)
				tempNode.rightNode = node;
		}else {
			System.out.println("找不到指定的结点!");
		}	
	}
	
	/**
	 * 清除树
	 * @param root
	 */
	public void clear(BTNode root){
		if (root != null) {
			clear(root.leftNode);
			clear(root.rightNode);
			root = null;
		}
	}
	/**
	 * 层序遍历
	 * @param root
	 */
	private void levelInner(BTNode root){
		//定义队列来存储各层的结点,maxlen各层最大结点数
		BTNode[] temp = new BTNode[MAXLEN];
		int head = 0, tail = 0;
		
		BTNode t;
		//入队
		if (root != null ) {
			tail = (tail + 1) % MAXLEN;
			temp[tail] = root;
		}
		while(head != tail){
			//处理结点
			head = (head +1) % MAXLEN;
			t = temp[head];
			System.out.println("处理结点数据"+ t.data);
			//添加结点
			if (t.leftNode != null) {
				temp[++tail % MAXLEN] = t.leftNode;
			}
			if (t.rightNode != null) {
				temp[++ tail % MAXLEN] = t.rightNode;	
			}
		}
	}
	//包装一下
	public void levelOrder(){
		levelInner(this.root);
	}
	/**
	 * 前序遍历
	 * @param root
	 */
	private void dlrInner(BTNode root){
		if (root != null) {
			System.out.println(root.data);
			dlrInner(root.leftNode);
			dlrInner(root.rightNode);
		}
	}
	public void preOrder(){
		dlrInner(this.root);
	}
	/**
	 * 中序遍历
	 * @param root
	 */
	private void ldrInner(BTNode root){
		if (root != null) {
			ldrInner(root.leftNode);
			System.out.println(root.data);
			ldrInner(root.rightNode);
		}
	}
	public void inOrder(){
		ldrInner(this.root);
	}
	/**
	 * 后序遍历
	 * @param root
	 */
	private void ltdInner(BTNode root){
		if (root != null) {
			ltdInner(root.leftNode);
			ltdInner(root.rightNode);
			System.out.println(root.data);
		}
	}
	public void postOrder(){
		ltdInner(this.root);
	}
	
	/*根据前序遍历格式创建一个树
	1 2 4 6 0 0 7 0 0 5 8 0 0 9 0 0 3 0 0
	要使用两个成员变量,如果用c实现更方便,可以传入指针创建*/
	private char[] arr;
	private int i;
	private BTNode createTree(){			
		BTNode node = null;
		if(i>=arr.length||arr[i] ==0){
			i++;
			return null;
		}else{
			node =  new BTNode(arr[i++]);
			node.leftNode = createTree();
			node.rightNode = createTree();
		}
		return  node;
	}
	//根据前序遍历和中序遍历创建一棵树,定义成静态类
	private static BTNode createTreeInner(String preOrder,String inOrder, int len) throws Exception{
		if(preOrder == null&& inOrder== null)
			return null;
		BTNode node = new BTNode(preOrder.charAt(0));
		//在中序遍历中寻找根结点
		int i =0;
		while(preOrder.charAt(0)!=inOrder.charAt(i)){
			i++;
			if(i>=len) throw new Exception("Error");
		}

		//创建左子树
		if(i>0)
			node.leftNode = createTreeInner(preOrder.substring(1), inOrder, i);
		//创建右子树
		if(i<len-1)
			node.rightNode = createTreeInner(preOrder.substring(i+1), inOrder.substring(i+1), len-i-1);
		return node;
	}
	public static BTree createTree(String preOrder,String inOrder) throws Exception{
		BTree btree = new BTree();
		btree.setRoot(createTreeInner(preOrder, inOrder, inOrder.length()));
		return btree;
	}
	/**
	 * 获取树的宽度
	 * @param root
	 * @return
	 */
	public int getWidth(BTNode root){
		int currentCount = 1,count=0;
		BTNode temp;
		LinkedList<BTNode> ll = new LinkedList<BTNode>();
		ll.offer(root);
		while(currentCount!=0){
			while(currentCount!=0){
				temp = ll.poll();
				if(temp.leftNode!=null){
					ll.offer(temp.leftNode);
				}
				if(temp.rightNode != null){
					ll.offer(temp.rightNode);
				}
				currentCount--;
			}
			currentCount = ll.size();
			//保存最多的结点
			if(currentCount>count)
				count = currentCount;
		}
		return count;
	}
	/**
	 * 判断两棵树是否相同
	 * @param a
	 * @param b
	 * @return
	 */
	private boolean equalInner(BTNode a, BTNode b){
		if(a==null&&b!=null||a!=null&&b==null)
			return false;
		else if(a!=null&&b!=null){
			if(a.data != b.data){
				return false;
			}else if(!equalInner(a.leftNode, b.leftNode)){
				return false;
			}else if(!equalInner(a.rightNode, b.rightNode)){
				return false;	
			}
		}
		return true;
	}

	public boolean equals(BTree tree){
		if(equalInner(root, tree.getRoot())){
			return true;
		}
		return false;
	}
	
	/**
	 * 获取树的深度
	 * @param root
	 * @return
	 */
	public int getDeep(BTNode root){
		int deepleft ,deepright;
		if (root == null) {
			return 0;
		}
		deepleft = getDeep(root.leftNode);
		deepright = getDeep(root.rightNode);
		if (deepleft >= deepright) {
			return ++deepleft;
		}else{
			return ++deepright;
		}
	}
	
	/**
	 * 判断树是否是平衡树
	 * @param root
	 * @return
	 */
	//方法一:先获取树的高度,然后才判断,由高到底(效率不高,java可方便实现)
	private boolean isBalanceInner(BTNode root){
		if(root == null){
			return true;
		}
		int leftHeight = getDeep(root.leftNode);
		int rightHeight = getDeep(root.rightNode);
		int diff = leftHeight - rightHeight;
		if(diff>1||diff<-1){
			return false;
		}
		return isBalanceInner(root.leftNode)&&isBalanceInner(root.rightNode);
	}
	//包装一下
	public boolean isBalance(){
		return isBalanceInner(this.root);	
	}
	
	//方法二:利用后序遍历的特征,一次性获取,由低到高
	//需要定义一个辅助类
	private class Depth {
		int height;
	}
	private boolean isBalanceInner(BTNode node,Depth d){
	   if(node==null){
	      d.height=0;
	      return true;
	   }
	   Depth right=new Depth();
	   Depth left = new Depth();
	   if(isBalanceInner(node.leftNode,left)&&isBalanceInner(node.rightNode,right)){
	       int diff = left.height-right.height;
	       if(diff<=1||diff>=-1){//绝对值小于等于1
	        //如果是平衡树,才有必要算深度,然后看上级是不是平衡树
	          d.height=left.height>right.height?left.height:right.height;
	          return true;
	       }
	   }
	   return false;
	}
	//包装一下
	public boolean isBalance2(BTNode root){
		return isBalanceInner(root,new Depth());
	}
	public BTNode getRoot(){
		return this.root;
	}
	public void setRoot(BTNode root){
		this.root = root;
	}
}


说明:有的代码是参考c实现的,java和c在实现上确实有很多不同的地方,尤其是树的递归调用,java中不能引用基本变量,只能是对象,所以在实现上与c相比,不太方便


树的其他操作以后遇到再慢慢补上。。。。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值