数据结构与算法-----重构二叉树

给你一颗二叉树,然后让你用代码实现创建的过程,紧接着用代码实现它的前序,中序,后序遍历。

例如给妮这样一颗二叉树


代码如下(注释很清楚)

package jzoffer;

/*
 *二叉树链式存储
 *@author LSM
 */
public class Tree {
	private TreeNoder root = null; //先定义一个根节点
	
	

	public Tree() {
		root = new TreeNoder(1, "rootNode(A)"); //在初始化的时候吧根节点初始化为A key当然赋值为1
	}
	 /** 
     * 创建一棵二叉树 
     * <pre> 
     *           A 
     *     B          C 
     *  D     E            F 
     *  </pre> 
     * @param root 
     * @author LSM 
     */  
	public void createTree(TreeNoder treeNoder){    //参数主要就是为了给根节点加节点
		TreeNoder treeNoderB = new TreeNoder(2, "B"); //看上面的图
		TreeNoder treeNoderC = new TreeNoder(3, "C");
		TreeNoder treeNoderD = new TreeNoder(4, "D");
		TreeNoder treeNoderE = new TreeNoder(5, "E");
		TreeNoder treeNoderF = new TreeNoder(6, "F");
		
		treeNoder.leftChild = treeNoderB;
		treeNoder.rightChild = treeNoderC;
		treeNoder.leftChild.leftChild = treeNoderD;
		treeNoder.rightChild.rightChild = treeNoderF;
		treeNoder.leftChild.rightChild = treeNoderE;  //这样真的好麻烦这就算完成了
	}
	
	public boolean isEmpty() {            //这个就是判断根节点是否为null
		return root==null;
	}
	
	
	public int height(){  //主要为了后边调用方便 再不用写root了
		return height(root);
	}
	public int height(TreeNoder treeNoderHeight){  //这里也是递归的方法
		if(treeNoderHeight == null){
			return 0;                      //空树的高度为0
		}else{
			int i = height(treeNoderHeight.leftChild);
			int j = height(treeNoderHeight.rightChild);
			return (i<j)?(j+1):(i+1);     //仔细揣摩下这句话的意思
		}
	}
	//主要为了后边调用方便 再不用写root了
	public int size(){
		return size(root);
	}
	public int size(TreeNoder treeNoderSize){
		if(treeNoderSize == null){
			return 0;
		}else{
			return 1+size(treeNoderSize.leftChild)+size(treeNoderSize.rightChild); //叶子节点都是0 再加上自身 自己揣摩
		}
	}
	
	public TreeNoder parent(TreeNoder treeNoderParent){
		if(treeNoderParent == null){
			return null;
		}
		//这个方法和下面的方法是连着的,只不过为了更方便吧
		//其实完全可以只用写下面一个方法,但是如果只写下面一个方法时候
		//你每次的参数就必须写一个root 这就很烦了 
		return  (root == null || root == treeNoderParent)?null:parent(root, treeNoderParent);
	}
	public TreeNoder parent(TreeNoder treeNoderParent,TreeNoder treeNoderSize){
		if(treeNoderParent == null){  //上面也有可能有一种情况就是 根节点root本身就为空那 那我们肯定就自己返回了
			return null;
		}
		if(treeNoderParent.leftChild == treeNoderSize  ||treeNoderParent.rightChild == treeNoderSize){
			return treeNoderSize;//如果的根节点的左边的孩子和右边的孩子的话,那么这个节点的双亲节点肯定就是根节点。
		}
		TreeNoder treeNoderP;
		//递归在左子树中查找
		if((treeNoderP = parent(treeNoderParent.leftChild, treeNoderSize))!= null){ //判断左子树
			return treeNoderP;
		}else{
		//递归在右子树中查找
			return parent(treeNoderParent.rightChild, treeNoderSize);
		}
	}
	//得到一个节点的左孩子节点
	public TreeNoder getLeftChildNode(TreeNoder leftChildNode){
		return (leftChildNode!=null)?leftChildNode.leftChild:null;
	}
	//得到一个节点的右孩子节点
	public TreeNoder getRightChildNode(TreeNoder RightChildNode){
		return (RightChildNode!=null)?RightChildNode.rightChild:null;
	}
	public TreeNoder getRoot(){
		return root;
	}
	//在释放某个节点的时候,该节点的左右子树都已经释放
	//所以应该采用后续遍历,当访问某个节点时候,将该节点存储的控件释放
	public void destroy(TreeNoder treeNoderElement){
		if(treeNoderElement != null){
			//删除左子树
			destroy(treeNoderElement.leftChild); 
			//删除右子树
			destroy(treeNoderElement.rightChild);
			//最后要将这个节点也就是 相对根节点置null 也就是删除
			treeNoderElement = null;
		}
	}
	//这个是输出这棵树
	public void traverse(TreeNoder treeNoder){
		//先带有一个标志
		System.out.println("KEY" + treeNoder.key + "--name:" + treeNoder.data);
		//然后就是老套路递归左子树
		traverse(treeNoder.leftChild);
		//紧接着右子树
		traverse(treeNoder.rightChild);
	}
	//前序遍历--------
	public void preOrder(TreeNoder treeNoder){
		//前序遍历第一下肯定是输出根节点的嘛
		if(treeNoder != null){
			//这个方法就是输出一下根节点,至于为什么要写一个方法 还是为了方便调用呗
			//以后左子树也要调用这个方法,右边的也是
			visted(treeNoder);
			//按照前序遍历的规则肯定就是先根再左边再右边
			preOrder(treeNoder.leftChild); 
			preOrder(treeNoder.rightChild);
		}
		
	}
	//接下来中序遍历 就是按照 "左根右"的方式
	public void inOrder(TreeNoder treeNoder){
		if(treeNoder != null){
			inOrder(treeNoder.leftChild);
			visted(treeNoder);
			inOrder(treeNoder.rightChild);
		}
	}
	//接下来后序遍历 就是按照 "左右根"的方式
	public void postOrder(TreeNoder treeNoder){
		if(treeNoder != null){
			postOrder(treeNoder.leftChild);
			postOrder(treeNoder.rightChild);
			visted(treeNoder);
		}
	}
	
	public void visted(TreeNoder treeNoder){
		treeNoder.isVisted = true;
		System.out.println("KEY" + treeNoder.key + "--name:" + treeNoder.data);
	}
	
	public static void main(String[] args) {
		Tree t = new Tree();
		t.createTree(t.root);
		System.out.println("这棵树的size为" + t.size());
		System.out.println("这棵树的高为" + t.height());
		System.out.println("*******(前序遍历)-LSM-[ABDECF]遍历*****************");
		t.preOrder(t.root);
		System.out.println("*******(中序遍历)-LSM-[DBEACF]遍历*****************");  
		t.inOrder(t.root);
	    System.out.println("*******(后序遍历)-LSM-[DEBFCA]遍历*****************");  
	    t.postOrder(t.root);
	}
}
/*
 * 二叉树节点的数据结构
 * @author LSM
 */
 class TreeNoder{
	int key = 0;           //这个主要是为了记录他遍历的顺序
	String data = null;    //这个主要是为了记录他节点的数据
	boolean isVisted = false; //先设置为false
	TreeNoder leftChild  = null;
	TreeNoder rightChild = null;
	
	public TreeNoder(int key ,String data){
		this.key  = key;
		this.data = data;
		this.leftChild  = null;
		this.rightChild = null;
	}
}

结果


 

猜你喜欢

转载自blog.csdn.net/lsm18829224913/article/details/80276071