JAVA从零开始之数据结构与算法二叉树的创建和遍历(2)

import java.util.Scanner;
import java.util.Stack;
import java.util.Queue;
import java.util.LinkedList;

class TreeNode{
	//左节点
	private TreeNode lchild;
	//右节点
	private TreeNode rchild;
	//数据
	private int data;
	//非递归后序遍历助记
	private boolean flag;
	
	//构造函数
	public TreeNode(){
		this.lchild = null;
		this.rchild = null;
		this.data = 0;
		this.flag = false;
	}

	public TreeNode(int value){
		this(null,null,value);
	}

	public TreeNode(TreeNode lchild,TreeNode rchild,int value){
		this.lchild = lchild;
		this.rchild = rchild;
		this.data = value;
		this.flag = false;
	}

	
	//set值
	public void setData(int value){
		this.data = value;
	}
	public void setLchild(TreeNode lchild){
		this.lchild = lchild;
	}

	public void setRchild(TreeNode rchild){
		this.rchild = rchild;
	}
	
	public void setFlag(boolean t){
		this.flag = t;
	}


	//get值
	public int getData(){
		return this.data;
	}
	
	public TreeNode getLchild(){
		return this.lchild;
	}

	public TreeNode getRchild(){
		return this.rchild;
	}
	
	//getFlag
	public boolean getFlag(){
		return flag;
	}

	//判isFlag
	public boolean isFlag(){
		return flag == true;
	}

	//判空
	public boolean isEmptyLchild(){
		return lchild == null;
	}

	public boolean isEmptyRchild(){
		return rchild == null;
	}
}

public class BiTreeNode{
	//定义二叉树的跟节点
	private TreeNode root;
	
	//构造函数
	public BiTreeNode(){
		this.root = null;
	}

	public BiTreeNode(TreeNode root){
		this.root = root;
	}
	
	//通过键盘输入前序创建二叉树
	private TreeNode createBiTree(){
		int value;
		TreeNode newBiTree = null;

		Scanner scan = new Scanner(System.in);

		//while((value = scan.nextInt()) != 0){
			value = scan.nextInt();
			if(value == 0){
				return newBiTree;
			}

			newBiTree = new TreeNode(value);		//先给根赋值
			newBiTree.setLchild(createBiTree());	//递归创建左孩子节点
			newBiTree.setRchild(createBiTree());	//最后创建右孩子节点
		return newBiTree;
	}
	//将创建的二叉树根节点赋值给root根节点
	public void create(){
		if(root != null){
			System.out.println("root isnot null!");
			return;
		}
		this.root = createBiTree();
	}
	
	//按节点顺序创建二叉树 
	//列表法,先为每个数组元素创建对应节点
	//再依序号关联引用
	public void createInsertLink(int[] a){
		if(this.root != null){
			System.out.println("root isnot null!");
			return;
		}
		LinkedList<TreeNode> nodelist = new LinkedList<TreeNode>();
		TreeNode node = null;
		
		//将每一个数组的值依次转换为Node节点
		for(int i=0;i<a.length;i++){
			node = new TreeNode(a[i]);
			nodelist.add(node);
		}
		
		//下标从0开始的二叉树 左孩子节点为2*i+1,右孩子节点为2*i+2,最后一个非终端节点索引为n/2-1
		for(int parentindex=0;parentindex<(a.length/2-1);parentindex++){
			nodelist.get(parentindex).setLchild (
								nodelist.get(parentindex*2+1));
			nodelist.get(parentindex).setRchild( 
								nodelist.get(parentindex*2+2));
		}

		//最后一个非终端节点必有左孩子
		int lastparent = a.length/2 - 1;
		nodelist.get(lastparent).setLchild(
								nodelist.get(lastparent*2 + 1));
		
		//总结点数为奇数时,最后一个非终端节点才有右孩子
		if(a.length % 2 == 1){
			nodelist.get(lastparent).setRchild(
								nodelist.get(lastparent*2 + 2));
		}
		this.root = nodelist.get(0);
	}

	//前序遍历
	public void preOrder(){
		TreeNode node = this.root;
		System.out.println("print preOrder start:");
		this.showPreBiTree(node);
		System.out.println("print finish!");
	}
	
	private void showPreBiTree(TreeNode node){
		if(node != null){
			System.out.println(node.getData());
			showPreBiTree(node.getLchild());
			showPreBiTree(node.getRchild());
		}
	}
	
	//中序遍历
	public void inOrder(){
		TreeNode node = this.root;
		System.out.println("print inOrder start:");
		this.showInBiTree(node);
		System.out.println("print finish!");
	}

	private void showInBiTree(TreeNode node){
		if(node != null){
			showInBiTree(node.getLchild());
			System.out.println(node.getData());
			showInBiTree(node.getRchild());
		}
	}
	
	//后序遍历
	public void postOrder(){
		TreeNode node = this.root;
		System.out.println("print postOrder start:");
		this.showPostBiTree(node);
		System.out.println("print finish!");
	}

	public void showPostBiTree(TreeNode node){
		if(node != null){
			showPostBiTree(node.getLchild());
			showPostBiTree(node.getRchild());
			System.out.println(node.getData());
		}
	}

	//非递归遍历
	//非递归前序遍历 DLR
	public void preOrderStack(){
		Stack<TreeNode> s = new Stack<TreeNode>();
		TreeNode node = this.root;
		System.out.println("print preOrder start:");
		
		while(node != null || !s.empty()){
			//如果当前节点不为空,打印节点数据,指针指向左孩子继续往左走  DLR
			if(node != null){
				System.out.println("value= " +node.getData());
				s.push(node);
				node = node.getLchild();
			}
			//如果当前节点为空,则出栈,退回一格,指向右节点DLR
			else{
				node = s.pop();
				node = node.getRchild();
			}
		}
		System.out.println("print finish!");
	}

	//非递归中序序遍历 LDR
	public void inOrderStack(){
		Stack<TreeNode> s = new Stack<TreeNode>();
		TreeNode node = this.root;
		System.out.println("print InOrder start:");

		//如果节点不为空或者栈不为空,则可继续遍历
		while(node != null || !s.empty()){
			if(node != null){
				s.push(node);
				node = node.getLchild();
			}
			//如果节点为空,则出栈,输出,指向右节点,相当于此处时根节点,比右孩子先输出
			else{
				node = s.pop();
				System.out.println("value= " +node.getData());
				node = node.getRchild();
			}
		}
		System.out.println("print finish!");
	}
	
	//非递归后序遍历 LRD
	public void postOrderStack(){
		Stack<TreeNode> s = new Stack<TreeNode>();
		TreeNode node = this.root;
		TreeNode temp;
		System.out.println("print postOrder start:");


		//如果节点不为空或者栈不为空,则可继续遍历
		while(node != null || !s.empty()){
			//如果node不为空,一口气走到底,此时最左字树位于栈顶
			while(node != null){
				node.setFlag(true);
				s.push(node);
				node = node.getLchild();
			}

			//访问右孩子->右孩子的左子树->直到把第一个L的双亲的右边子数全部遍历完毕
			if(!s.empty()){
				//取出栈顶元素,如果是第一次访问,则标记为第二次访问,然后入栈 继续访问该节点右字树
				temp = s.pop();
				if(temp.isFlag()){
					//标记第二次访问
					temp.setFlag(false);
					s.push(temp);
					//如栈后指向节点的右孩子,因为此时该双亲左节点已经遍历完毕
					node = temp.getRchild();
				}
				//如果是第二次访问,则打印输出
				else{
					System.out.println("value = " + temp.getData());
					node = null;
				}
			}
		}
		System.out.println("print finish!");
	}

	//层次遍历
	public void levelOrderTree(){
		TreeNode node = this.root;
		TreeNode leveaLast = this.root;
		Queue<TreeNode> q = new LinkedList<TreeNode>();
		boolean flag =true;
		TreeNode nodebackup = new TreeNode(0);
		
		int i = 0;
		node.setFlag(true);
		q.offer(node);
		
		while(q.peek() != null){
			node = q.poll();
			//设置层结束标志
			if(node.getFlag() == flag){
				System.out.print("\nthe " + (++i) + " levle:\t");
				flag = flag == false;
			}
				System.out.print(node.getData() + "\t");
			if(node.getLchild() != null){
				node.getLchild().setFlag(flag);
				q.offer(node.getLchild());
			}

			if(node.getRchild() != null){
				node.getRchild().setFlag(flag);
				q.offer(node.getRchild());
			}
		}
		System.out.println("\nprint finish!");
	}

	//非递归后序遍历二叉树
	//首先root节点入栈
	//循环:当前节点等于栈顶节点,如果该节点左右字树为空,或者前一个访问节点不为空且当前节点的左右字树有一个等于前一个打印的节点(表示已经遍历过一遍了,回退当中)
	//则出栈栈顶节点,打印输出
	//否则继续压右孩子如栈,再压左孩子如栈
	public void postOrderStack2(){
		Stack<TreeNode> s = new Stack<TreeNode>();
		TreeNode node = this.root;
		TreeNode cur;//当前访问节点
		TreeNode pre = null;//前一次访问的节点
		System.out.println("print postOrder2 start:");
		
		s.push(node);
		while(!s.empty()){
			cur = s.peek();
			if((cur.isEmptyLchild() && cur.isEmptyRchild()) ||				//如果当前节点的左右左右节点为空(前进过程,走到底了)
			   (pre != null && (pre == cur.getLchild() || pre == cur.getRchild()))){	//或者前一个节点不为空且前一个节点等于当前节点的左孩子或者右孩子(回退过程)
					System.out.println("value = " + cur.getData());
					s.pop();
					pre = cur;
			   }
			else{
				if(!cur.isEmptyRchild())					//先右孩子压栈
					s.push(cur.getRchild());
				if(!cur.isEmptyLchild())					//左孩子压栈
					s.push(cur.getLchild());
			}
		}
		System.out.println("print finish!");
	}
	
	public static void main(String[] args){
		int value;
		int a[] = {11504,3,42,42,8,183,22,238,85,18,22,18,31,1504,3,42,42,8,183,22,238,85,18,22,18,31504,3,42,42,8,183,22,238,85,18,22,18,31};

		TreeNode newNode = new TreeNode();
		BiTreeNode bitTree = new BiTreeNode();
		//bitTree.create();
		bitTree.createInsertLink(a);
		bitTree.preOrder();
		bitTree.inOrder();
		bitTree.postOrder();
		bitTree.preOrderStack();
		bitTree.inOrderStack();
		bitTree.postOrderStack();
		bitTree.levelOrderTree();
		bitTree.postOrderStack2();
	}
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值