二叉树的各种先序中序后序层次遍历(递归,非递归)&&数组实现后序遍历详细代码

该博客详细介绍了如何使用Java实现二叉树的前序、中序、后序以及层次遍历,包括递归和非递归两种方式,并提供了相应的代码实现。此外,还展示了双栈后序遍历的实现。这对于理解二叉树遍历和数据结构操作非常有帮助。
摘要由CSDN通过智能技术生成
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;
//https://blog.csdn.net/skylibiao/article/details/81195219
//https://www.cnblogs.com/zhi-leaf/p/10813048.html
public class BinaryTreeTest {
	//节点
public BinaryTreeTest left;
public BinaryTreeTest right;
public BinaryTreeTest root;
//值
public Object data;
public BinaryTreeTest(BinaryTreeTest left,BinaryTreeTest right,Object data )
{
	this.left=left;
	this.right=right;
	this.data=data;
	
}
public BinaryTreeTest(Object val)
{
	this(null, null, val);
}
public BinaryTreeTest()
{
	
}
//创建节点
public void insert(Object[] arr)
{
	if(arr==null||arr.length<1) return ;
	else {
		BinaryTreeTest[] Biarr=new BinaryTreeTest[arr.length];
		for(int i=0;i<arr.length;i++)
		{
			Biarr[i]=new BinaryTreeTest(arr[i]);
		}
		//创建root节点方便待会调用root遍历
		root=Biarr[0];
		//arr[0]左边arr[1]右边arr[2] arr[1]左边arr[3]右边arr[4],arr[2]左边arr[5]右边arr[6]
		for(int i=0;i<arr.length/2;i++)
		{
//			new BinaryTreeTest(arr[i]).left=new BinaryTreeTest(arr[2*i+1]);//这种写法太麻烦了,可以构建一个BinaryTreeTest对象数组
		//进行越界检查
		if(2*i+1<arr.length)	Biarr[i].left=Biarr[2*i+1];
		if(2*i+2<arr.length)	Biarr[i].right=Biarr[2*i+2];
		}//end for
	}//end else
}//end method
//递归遍历
public void Recursivetravel(BinaryTreeTest root,int tavelkind)
{
	switch(tavelkind) {
	case 0:System.out.println("\n 前序遍历");Recursivetravelbefore(root);preOrderTraverse(root); break;
	case 1:System.out.println("\n 中序遍历");Recursivetravelmid(root);inOrderTraverse(root);break;
	case 2:System.out.println("\n 后序遍历");Recursivetravelafter(root);System.out.println("\n 双栈:");afterTraverseWithStack(root);System.out.println("\n 非递归 ");postOrderTraverse(root);break;
	case 3:System.out.println("\n 层次遍历");levelOrderTraverse(root);break;
	default:System.out.println("请输入1和2");
	}
}
//前序遍历
public void Recursivetravelbefore(BinaryTreeTest root)
{
//	System.out.println("前序遍历");
	if(root!=null) {
	System.out.print(root.data+" ");
	Recursivetravelbefore(root.left);
	Recursivetravelbefore(root.right);
	}
}
public void preOrderTraverse(BinaryTreeTest root)
{
	System.out.println("\n 非递归前序遍历");
	Stack<BinaryTreeTest> astack=new Stack<>();
	//不干扰root
	BinaryTreeTest nroot=root;
	while(nroot!=null||!astack.isEmpty())
	{
		if(nroot!=null)
		{
			//先打印root节点值
			System.out.print(nroot.data+" ");
			astack.push(nroot);
			//一直往左走
			nroot=nroot.left;
		}
		else
		{
			nroot=astack.pop();
			nroot=nroot.right;
		}
	}
}
//中序非递归遍历
public void inOrderTraverse(BinaryTreeTest root)
{
	System.out.println("\n 非递归中序遍历");
	Stack<BinaryTreeTest> astack=new Stack<>();
	//不干扰root
	BinaryTreeTest nroot=root;
	while(nroot!=null||!astack.isEmpty())
	{
		if(nroot!=null)
		{
			//把父节点保存,方便之后打印以及使得能够之后往右走
			astack.push(nroot);
			//一直往左走
			nroot=nroot.left;
		}
		else
		{
			
			nroot=astack.pop();
			//
			System.out.print(nroot.data+" ");
			nroot=nroot.right;
		}
	}
}
//中序遍历

public void Recursivetravelmid(BinaryTreeTest root)
{
//	System.out.println("中序遍历");
	if(root!=null) {
	
	Recursivetravelmid(root.left);
	System.out.print(root.data+" ");
	Recursivetravelmid(root.right);
	}
}
//后序非递归遍历
public void postOrderTraverse(BinaryTreeTest root)
{
	System.out.println("\n 非递归后序遍历");
	Stack<BinaryTreeTest> astack=new Stack<>();
	//不干扰root
	BinaryTreeTest nroot=root;
	astack.add(nroot);
	BinaryTreeTest pre=null;
	BinaryTreeTest cur;
	while(!astack.isEmpty())
	{
		cur=astack.peek();
		
		if(
				(cur.left==null&&cur.right==null)||
				(  (pre!=null)&&(pre==cur.left||pre==cur.right)  )
		 )
				{
			System.out.print(cur.data+" ");
			astack.pop();
			pre=cur;
				}//end if
		else
		{
			if(cur.right!=null) astack.push(cur.right);
			if(cur.left!=null) astack.push(cur.left);
			
		}//end else
		
	}
		
}
//双栈实现后序遍历
//用栈后序遍历,将后序序列反过来,就是先序先遍历右子树后遍历左子树的结果,因此这里使用两个栈,栈2用来反转结果(引用链接的,但是很明显这是用两个数组实现)
public void afterTraverseWithStack(BinaryTreeTest root){
	BinaryTreeTest stack1[] = new BinaryTreeTest[100];
	BinaryTreeTest stack2[] = new BinaryTreeTest[100];
	int top1 = -1;
	int top2 = -1;
	if(root != null){
		stack1[++top1] = root;
		//先序先遍历右子树
		while(top1 != -1){
			// Object[] input= {1,3,6,2,3,4,5,8,9,0,2};
			
			BinaryTreeTest node = stack1[top1];//stak1[0]=1
			System.out.println("stack1["+top1+"]"+"="+node.data);

			top1--;
			top2++;
			stack2[top2] = node;
			if(node.left != null){
				stack1[++top1] = node.left;
			}
			if(node.right != null){
				stack1[++top1] = node.right;
			}
		}
//		System.out.println(top1+";top2="+top2);
		while(top2 != -1){
			System.out.print(stack2[top2--].data+" ");
		}
//		System.out.println(top1+";top2="+top2);
	}
}

//版权声明:本文为CSDN博主「丶幻一」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
//原文链接:https://blog.csdn.net/qq_25956141/article/details/103877134
//后序遍历
/**
 * 根节点最后输出:(没有左孩子&&没有右孩子)||(左孩子被访问过||右孩子被访问过,栈弹出),要满足这些条件,
 * 前序和中序根节点不是放到最后输出,而后序遍历则是,因此要将右孩子左孩子入栈才能使得根节点最后输出.
 * 为什么入栈顺序是是右孩子->左孩子,因为栈先入后出,打印顺序是左孩子->右孩子,则入栈顺序要反过来
 * 如何知道左孩子右孩子是否被访问过?通过比较上一次弹出元素是不是栈顶元素的左孩子右孩子来确定
 * 没有左右子树?!!
 * @param root
 */
public void Recursivetravelafter(BinaryTreeTest root)
{
	
	if(root!=null) {
	
	Recursivetravelafter(root.left);
	
	Recursivetravelafter(root.right);
	System.out.print(root.data+" ");
	}
}
//层次遍历,使用队列
public void levelOrderTraverse(BinaryTreeTest root) {
    if (root == null) {
        return;
    }
    Queue<BinaryTreeTest> queue = new LinkedList<BinaryTreeTest>();
    queue.add(root);
    while(!queue.isEmpty())
    {
    	//不更改root
    	BinaryTreeTest temp=queue.poll();
    	System.out.print(temp.data+" ");
    	if(temp.left!=null)queue.add(temp.left);
    	if(temp.right!=null) queue.add(temp.right);
    	
    }
}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
    Object[] input= {1,3,6,2,3,4,5,8,9,0,2};
    BinaryTreeTest aa=new BinaryTreeTest();
    aa.insert(input);
//   int ascan=(int) (Math.random()*3);
   for(int ascan=0;ascan<4;ascan++) {
    	aa.Recursivetravel(aa.root,ascan);
   }
   
//    aa.root;
	}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值