目录
二叉树由于结构的递归特性(即一棵树的子树仍然为一棵树),所以其大部分算法都是以递归形式进行的。本文将从非递归的角度与思路出发,实现java二叉树的三序遍历(前序遍历,中序遍历,后序遍历)。
零、本文中模拟实现的二叉树源码
class TreeNode {
public char val;
public TreeNode left;
public TreeNode right;
//TreeNode的构造方法
public TreeNode(char val) {
this.val = val;
}
}
class MyBinaryTree {
//人为拼接构造一颗二叉树的方法
public TreeNode creatTree() {
TreeNode A = new TreeNode('A');
TreeNode B = new TreeNode('B');
TreeNode C = new TreeNode('C');
TreeNode D = new TreeNode('D');
TreeNode E = new TreeNode('E');
TreeNode F = new TreeNode('F');
TreeNode G = new TreeNode('G');
TreeNode H = new TreeNode('H');
TreeNode I = new TreeNode('I');
A.left = B;
A.right = C;
B.left = D;
B.right = E;
C.left = F;
C.right = G;
E.right = H;
F.left = I;
return A;//返回根节点A
}
//查找二叉树中是否包含值为key的节点的方法
public TreeNode find(TreeNode root, char key) {
//空节点返回空
if (root == null) {
return null;
}
//找到key值节点则返回
if (root.val == key) {
return root;
}
//递归左子树
TreeNode leftVal = find(root.left, key);
if (leftVal != null) {
return leftVal;
}
//递归右子树
TreeNode rightVal = find(root.right, key);
if (rightVal != null) {
return rightVal;
}
//程序全部运行结束说明没有招到值为key的节点
return null;
}
//前序遍历方法
public void preOrder(TreeNode root) {
//空节点返回
if (root == null) {
return;
}
//打印根节点
System.out.print(root.val + " ");
//递归左子树
preOrder(root.left);
//递归右子树
preOrder(root.right);
}
//中序遍历方法
public void inOrder(TreeNode root) {
//空节点返回
if (root == null) {
return;
}
//递归左子树
inOrder(root.left);
//打印根节点
System.out.print(root.val + " ");
//递归右子树
inOrder(root.right);
}
//后序遍历方法
public void postOrder(TreeNode root) {
//空节点返回
if (root == null) {
return;
}
//递归左子树
postOrder(root.left);
//递归右子树
postOrder(root.right);
//打印根节点
System.out.print(root.val + " ");
}
//获取树中的节点个数的方法
public int getSize(TreeNode root) {
//空节点返回0
if (root == null) {
return 0;
}
//递归左子树和右子树(+1为根节点个数)
int size = 1 + getSize(root.left) + getSize(root.right);
return size;
}
//获取二叉树中叶子节点个数的方法
public int getLeafNodeCount(TreeNode root) {
//空节点返回0
if (root == null) {
return 0;
}
//叶子节点返回1
if (root.left == null && root.right == null) {
return 1;
}
//递归左子树和右子树
int count = getLeafNodeCount(root.left) + getLeafNodeCount(root.right);
return count;
}
//获取第k层(根节点层数为0)的节点个数的方法
public int getKthLevelNodeCount(TreeNode root, int k) {
//空节点返回0
if (root == null) {
return 0;
} else if (k == 0) {
//本层节点返回1
return 1;
}
//递归左子树和右子树
return getKthLevelNodeCount(root.left, k - 1) + getKthLevelNodeCount(root.right, k);
}
//获取二叉树的深度的方法
public int getHight(TreeNode root) {
//空节点返回-1
if (root == null) {
return -1;
}
//递归左子树
int leftHeight = getHight(root.left);
//递归右子树
int rightHeight = getHight(root.right);
//返回其中最大值
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
}
一、前序遍历的非递归实现
由二叉树前序递归遍历的特点可知,在前序遍历中整体为自下而上的遍历顺序,并且输出根节点为最高优先级,向左子树递归为次高优先级,向右子树遍历为最低优先级(即根节点不为空优先输出根节点,否则左子树不为空优先向左子树递归,否则最后向右子树递归)。所以我们可以通过借助栈来模拟自下而上的遍历顺序以及非递归的算法来模拟递归中优先级的思路实现前序遍历。
1.代码示例:
public class InOrderNot {
//非递归方式实现前序遍历的方法
public void inOrderNot(TreeNode root){
//创建一个新的栈
Stack<TreeNode>stack=new Stack<>();
//用cur记录当前遍历节点
TreeNode cur=root;
//根据先序遍历从下到上的顺序可知,若cur不为空或者栈不为空循环继续,使得cur从下至上遍历
while(cur!=null||!stack.isEmpty()){
while(cur!=null){
stack.push(cur);
//向左子树遍历为最高优先级
cur=cur.left;
}
//弹出此节点,用top记录,以便向打印此节点和右子树遍历
TreeNode top=stack.pop();
//输出根节点值为次高优先级
System.out.print(top.val+" ");
//向右子树遍历为最低优先级
cur=top.right;
}
}
//main方法用于测试代码
public static void main(String[] args) {
MyBinaryTree myBinaryTree=new MyBinaryTree();
InOrderNot inOrderNot=new InOrderNot();
//人为创建一棵二叉树
TreeNode root=myBinaryTree.creatTree();
//递归方法实现中序遍历演示
System.out.print("递归实现: ");
myBinaryTree.inOrder(root);
System.out.println();
System.out.println("*****************************");
System.out.print("非递归实现:");
inOrderNot.inOrderNot(root);
}
}
2.与递归算法的比对演示:
测试代码为main方法中代码,结果如下:
二、中序遍历的非递归实现
同前序遍历,由二叉树中序递归遍历的特点可知,在中序遍历中整体为自下而上的遍历顺序,并且向左子树递归为最高优先级,输出根节点为次高优先级,向右子树遍历为最低优先级(即左子树不为空优先向左子树递归,否则根节点不为空优先输出根节点,否则最后向右子树递归)。所以我们可以通过借助栈来模拟自下而上的遍历顺序以及非递归的算法来模拟递归中优先级的思路实现中序遍历。
1.代码示例:
public class InOrderNot {
//非递归方式实现中序遍历的方法
public void inOrderNot(TreeNode root){
//创建一个新的栈
Stack<TreeNode>stack=new Stack<>();
//用cur记录当前遍历节点
TreeNode cur=root;
//根据先序遍历从下到上的顺序可知,若cur不为空或者栈不为空循环继续,使得cur从下至上遍历
while(cur!=null||!stack.isEmpty()){
while(cur!=null){
stack.push(cur);
//向左子树遍历为最高优先级
cur=cur.left;
}
//弹出此节点,用top记录,以便向打印此节点和右子树遍历
TreeNode top=stack.pop();
//输出根节点值为次高优先级
System.out.print(top.val+" ");
//向右子树遍历为最低优先级
cur=top.right;
}
}
//main方法用于测试代码
public static void main(String[] args) {
MyBinaryTree myBinaryTree=new MyBinaryTree();
InOrderNot inOrderNot=new InOrderNot();
//人为创建一棵二叉树
TreeNode root=myBinaryTree.creatTree();
//递归方法实现中序遍历演示
System.out.print("递归实现: ");
myBinaryTree.inOrder(root);
System.out.println();
System.out.println("*****************************");
System.out.print("非递归实现:");
inOrderNot.inOrderNot(root);
}
}
2.与递归算法的比对演示:
三、后序遍历的非递归实现
同前序遍历与中序遍历,由二叉树后序递归遍历的特点可知,在后序遍历中整体为自下而上的遍历顺序,并且向左子树递归为最高优先级,向右子树遍历为次高优先级,输出根节点为最低优先级(即左子树不为空优先向左子树递归,否则右子树不为空优先向右子树递归,否则最后输出根节点)。所以我们可以通过借助栈来模拟自下而上的遍历顺序以及非递归的算法来模拟递归中优先级的思路实现后序遍历。
1.代码示例:
public class PostOrderNot {
//通过非递归方式实现后序遍历的方法
public void postOrderNot(TreeNode root){
//创建一个新的栈
Stack<TreeNode>stack=new Stack<>();
//用cur记录当前遍历节点
TreeNode cur=root;
//用prev记录上一个已经输出过的节点,避免进入死循环
TreeNode prev=null;
//根据先序遍历从下到上的顺序可知,若cur不为空或者栈不为空循环继续,使得cur从下至上遍历
while(cur!=null||!stack.isEmpty()){
while(cur!=null){
stack.push(cur);
//向左子树遍历为最高优先级
cur=cur.left;
}
//获取此节点,用top记录,(不可像前中序遍历那样弹出,因为输出根节点值为最低优先级,若此时就弹出则无法再输出)以便右子树遍历和打印此节点
TreeNode top=stack.peek();
if(top.right!=null&&top.right!=prev){
//向右子树遍历为次高优先级
cur=top.right;
}else{
//输出根节点值为最低优先级
System.out.print(top.val+" ");
//此节点已经输出,将其弹出
stack.pop();
//用prev记录上一个已经输出过的节点,避免进入死循环
prev=top;
}
}
}
//main方法用于测试代码
public static void main(String[] args) {
MyBinaryTree myBinaryTree=new MyBinaryTree();
PostOrderNot postOrderNot=new PostOrderNot();
//人为创捷一棵树
TreeNode root=myBinaryTree.creatTree();
//递归方法实现后序遍历演示
System.out.print("递归实现: ");
myBinaryTree.postOrder(root);
System.out.println();
System.out.println("*****************************");
System.out.print("非递归实现:");
postOrderNot.postOrderNot(root);
}
}
2.与递归算法的比对演示:
以上便是Java二叉树三序遍历的非递归实现的全部内容,如有不当,敬请斧正!