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;
}
}
二叉树的各种先序中序后序层次遍历(递归,非递归)&&数组实现后序遍历详细代码
最新推荐文章于 2024-07-21 14:25:28 发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)