Java创建/遍历二叉树

import java.util.Scanner;
import static java.lang.System.*;
public class Tree
{
	class TreeNode
	{
		String data;	//元素数据
		TreeNode left;		//左子树结点
		TreeNode right;	//右子树结点
	}
	static final int MAXLEN=20;
	static Scanner input=new Scanner(System.in);
	TreeNode InitTree( )											//1初始化二叉树的根
	{
		TreeNode node=new TreeNode();
		if ( node!=null)
		{
			out.println("请先输入一个根结点数据:");
			node.data=input.next();
			node.left=null;
			node.left=null;
			return node;
		}
		else
			return null;
	}
	void Add( TreeNode treeNode)					//2.添加结点
	{
		TreeNode pnode=new TreeNode();
		TreeNode parent;
		String data;
		int menusel;
		if( pnode!=null )
		{
			out.println("请输入二叉树结点数据:");
			pnode.data=input.next();
			pnode.left=null;
			pnode.right=null;
			out.println("输入该结点的父节点数据:");
			data=input.next();
			
			parent=FindNode(treeNode ,data);
			if(parent==null)
			{
				out.println("未找到该父结点!");
				pnode=null;
				return ;
			}
			out.println("选择1.添加该结点到左子树 2.添加该结点到右子树!");
			menusel=input.nextInt();
			if(menusel==1 || menusel==2)
			{
				if(parent==null)
				{
					out.println("不存在父结点,请先设置父结点!");
				}
				else
				{
					if(menusel==1)
					{
						if (parent.left!=null)
							out.println("左子树结点不为空!");
						else
							parent.left=pnode;
					}
					else if(menusel==2)
					{
						if (parent.right!=null)
							out.println("右子树结点不为空!");
						else
							parent.right=pnode;
					}
				}
			}
		}
	}
	
	TreeNode FindNode(TreeNode treeNode ,String data)	//3.查找结点
	{
		TreeNode ptr;
		if(treeNode==null)
		{
			return null;
		}
		else
		{
			if(treeNode.data.equals(data))
			{
				return treeNode;
			}
			else
			{
				if( (ptr =FindNode(treeNode.left ,data))!=null )
				{
					return ptr;
				}
				else if ((ptr=FindNode (treeNode.right , data)) !=null)
				{
					return ptr;
				}
				else
				{
					return null;
				}
			}
		}
	}
	
	TreeNode LeftNode(TreeNode treeNode)					//4.获取左子树
	{
		if(treeNode!=null)
		{
			return treeNode.left;
		}
		else
		{
			return null;
		}
	}
	TreeNode RightNode(TreeNode treeNode)					//5.获取右子树
	{
		if(treeNode!=null)
		{
			return treeNode.right;
		}
		else
		{
			return null;
		}
	}
	boolean isEmpty(TreeNode treeNode)								//6.判断是否为空树
	{
		if(treeNode!=null)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	
	int Depth(TreeNode treeNode)											//7.获取树深度
	{
		int depleft ,depright;
		if(treeNode==null)
		{
			return 0;
		}
		else
		{
			depleft=Depth(treeNode.left);
			depright=Depth(treeNode.right);
			return Math.max(depleft+1,depright+1);
		}
	}
	void NodeData(TreeNode p)									//8.显示结点数据
	{
		out.print(p.data);
	}
	
	void LevelOrderTraversal(TreeNode treeNode)						//9.层次遍历
	{
		TreeNode p;
		TreeNode[] q=new TreeNode[MAXLEN];
		int head =0, tail=0;
		if(treeNode !=null)
		{
			tail=(tail+1)%MAXLEN;
			q[tail]=treeNode;
		}
		while(head!=tail)
		{
			head=(head+1)%MAXLEN;
			p=q[head];
			NodeData(p);
			out.print(" ");
			if(p.left !=null)
			{
				tail=(tail+1)%MAXLEN;
				q[tail]=p.left;
			}
			if(p.right != null)
			{
				tail=(tail+1)%MAXLEN;
				q[tail]=p.right;
			}
		}
	}
	void PreorderTraversal(TreeNode treeNode)		//10.先序遍历
	{
		if(treeNode !=null)
		{
			NodeData(treeNode);
			out.print(" ");
			PreorderTraversal(treeNode.left);
			PreorderTraversal(treeNode.right);
		}
	}
	void InorderTraversal(TreeNode treeNode)		//11.中序遍历
	{
		if(treeNode !=null)
		{
			InorderTraversal(treeNode.left);
			NodeData(treeNode);
			out.print(" ");
			InorderTraversal(treeNode.right);
		}
	}
	
	void PostorderTraversal(TreeNode treeNode)		//12.后序遍历
	{
		if(treeNode !=null)
		{
			PostorderTraversal(treeNode.left);
			PostorderTraversal(treeNode.right);
			NodeData(treeNode);
			out.print(" ");
		}
	}
	public static void main(String[] args)
	{
		TreeNode root=null;//新建根节点
		int n;
		Tree t=new Tree( );		//建树
		out.println("输入二叉树结点个数:");
		n=input.nextInt();
		root=t.InitTree();
		for(int i=0 ; i<n-1 ; i++)
		{
			t.Add(root);
		}
		out.println(t.Depth(root));
		t.LevelOrderTraversal(root);//层序遍历
		out.println();
		t.PreorderTraversal(root);//先序遍历
		out.println();
		t.InorderTraversal(root);//中序遍历
		out.println();
		t.PostorderTraversal(root);//后序遍历	
	}
}

### Java中实现二叉树中序遍历的方法 #### 方法概述 在Java中,可以通过多种方法实现二叉树的中序遍历。常见的方法包括递归、迭代以及莫里斯遍历(Morris Traversal)。以下是每种方法的具体实现。 --- #### 1. **递归实现** 递归是最直观的方式之一,其核心思想是按照“左子树 -> 根节点 -> 右子树”的顺序访问节点[^2]。 ```java public List<Integer> inorderTraversal(TreeNode root) { List<Integer> result = new ArrayList<>(); helper(root, result); return result; } private void helper(TreeNode node, List<Integer> resultList) { if (node != null) { helper(node.left, resultList); // 访问左子树 resultList.add(node.val); // 处理当前节点 helper(node.right, resultList); // 访问右子树 } } ``` 这种方法的时间复杂度为O(n),空间复杂度取决于递归调用栈的深度,最坏情况下为O(h),其中h为树的高度[^4]。 --- #### 2. **迭代实现** 为了减少递归带来的额外开销,可以使用显式的栈来模拟递归过程。这种方式同样遵循“左子树 -> 根节点 -> 右子树”的原则[^1]。 ```java import java.util.*; public List<Integer> inorderTraversalIterative(TreeNode root) { List<Integer> result = new ArrayList<>(); Stack<TreeNode> stack = new Stack<>(); TreeNode current = root; while (current != null || !stack.isEmpty()) { while (current != null) { // 将左子树压入栈中 stack.push(current); current = current.left; } current = stack.pop(); // 弹出并处理当前节点 result.add(current.val); current = current.right; // 转向右子树 } return result; } ``` 该方法的空间复杂度由使用的栈决定,时间复杂度仍为O(n)[^1]。 --- #### 3. **莫里斯遍历(Morris Traversal)** 莫里斯遍历是一种不需要额外存储空间的高效算法,通过修改树中的指针完成遍历。它利用叶子节点的空闲指针指向其他节点,从而避免了使用栈或递归[^2]。 ```java public List<Integer> morrisInorderTraversal(TreeNode root) { List<Integer> result = new ArrayList<>(); TreeNode current = root; while (current != null) { if (current.left == null) { // 如果没有左子树,则直接访问当前节点 result.add(current.val); current = current.right; } else { TreeNode predecessor = findPredecessor(current); // 找到前驱节点 if (predecessor.right == null) { // 建立临时链接 predecessor.right = current; current = current.left; } else { // 断开临时链接并访问当前节点 predecessor.right = null; result.add(current.val); current = current.right; } } } return result; } // 寻找当前节点的前驱节点 private TreeNode findPredecessor(TreeNode node) { TreeNode pre = node.left; while (pre.right != null && pre.right != node) { pre = pre.right; } return pre; } ``` 这种算法的空间复杂度为O(1),因为不依赖于任何额外的数据结构。 --- ### 性能对比 | 方法 | 时间复杂度 | 空间复杂度 | |---------------|------------|-------------| | 递归 | O(n) | O(h) | | 迭代(栈) | O(n) | O(h) | | 莫里斯遍历 | O(n) | O(1) | 以上表格展示了不同方法的性能特点,开发者可以根据实际需求选择合适的方案[^1]。 --- ### 结论 对于初学者来说,递归和基于栈的迭代方法更为直观易懂;而对于追求极致性能的应用场景,莫里斯遍历则是一个不错的选择。无论采用哪种方法,都应确保代码逻辑清晰且易于维护。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值