java循环树_【Java】 二叉树的遍历(递归与循环+层序遍历)

在【Java】 大话数据结构(9) 树(二叉树、线索二叉树)一文中,已经实现了采用递归方法的前、中、后序遍历,本文补充了采用循环的实现方法、以及层序遍历并进行了一个总结。

递归实现

/*

* 前序遍历

*/

public void preOrder() {

preOrderTraverse(root);

System.out.println();

}

private void preOrderTraverse(BiTNode node) {

if(node==null)

return;

System.out.print(node.data);

preOrderTraverse(node.lchild);

preOrderTraverse(node.rchild);

}

/*

* 中序遍历

*/

public void inOrder() {

inOrderTraverse(root);

System.out.println();

}

private void inOrderTraverse(BiTNode node) {

if(node==null)

return;

inOrderTraverse(node.lchild);

System.out.print(node.data);

inOrderTraverse(node.rchild);

}

/*

* 后序遍历

*/

public void postOrder() {

postOrderTraverse(root);

System.out.println();

}

private void postOrderTraverse(BiTNode node) {

if(node==null)

return;

postOrderTraverse(node.lchild);

postOrderTraverse(node.rchild);

System.out.print(node.data);

}

非递归实现(迭代)

非递归实现,需要先创建一个栈,利用其特性来进行储存和输出。

前序遍历,先输出当前点的值,一直沿着左子树进行读取,没左子树就在右子树重复上述过程。

中序遍历与前序遍历基本一致,只是输出值的代码位置不同。

后序遍历由于要左右子树输出完后才能输出根结点,所以增加一个栈进行标记是否完成左右子树的输出,其余思想基本类似。

下面代码中,要注意node的结点位置和stack.peek()的位置关系。

此外,在后序非递归遍历的过程中,栈中保留的是当前结点的所有祖先。这是和先序及中序遍历不同的。在某些和祖先有关的算法中,此算法很有价值。

/**

* 前序遍历(非递归)

*/

public void preOrder2() {

preOrder2(root);

System.out.println();

}

private void preOrder2(BiTNode node) {

Stack stack = new Stack();

while(node!=null||!stack.isEmpty()) {

while(node!=null) {

System.out.print(node.data);

stack.push(node);

node=node.lchild;

}

node=stack.pop().rchild;

}

}

/**

* 中序遍历

*/

public void inOrder2() {

inOrder2(root);

System.out.println();

}

private void inOrder2(BiTNode node) {

Stack stack = new Stack();

while(node!=null||!stack.isEmpty()) {

while(node!=null) {

stack.push(node);

node=node.lchild;

}

node=stack.pop();

System.out.print(node.data);

node=node.rchild;

}

}

/**

* 后序遍历

*/

public void postOrder2() {

postOrder2(root);

System.out.println();

}

private void postOrder2(BiTNode node) {

Stack stack = new Stack();

Stack tag = new Stack();

//下面这段注释也能实现,与后面未注释部分基本一致。代表了自己的思考过程,就不删除了

//while(node!=null||!stack.isEmpty()) {

//while(node!=null){

//stack.push(node);

//tag.push(0);

//node=node.lchild;

//}

//注释中的tag用于标记当前结点是否完成左右子结点遍历(所以用0,1表示)

//while(!tag.isEmpty()&&tag.peek()==1) { //栈顶节点的左右子结点已完成遍历

//System.out.print(stack.pop().data);

//tag.pop();

//}

//if(!tag.isEmpty()) { //上面和这里的 !flag.isEmpty() 不可省略,不然会出错。

//tag.pop();

//tag.push(1);

//node=stack.peek().rchild;

//}

//}

/*后序遍历时,分别从左子树和右子树共两次返回根结点(用tag表示次数),

* 只有从右子树返回时才访问根结点,所以增加一个栈标记到达结点的次序。

*/

while(node!=null||!stack.isEmpty()) {

if(node!=null){

stack.push(node);

tag.push(1); //第一次访问

node=node.lchild;

}else {

if(tag.peek()==2) {

System.out.print(stack.pop().data);

tag.pop();

}else {

tag.pop();

tag.push(2); //第二次访问

node=stack.peek().rchild;

}

}

}

}

20191104:前序和后序的非递归遍历还可以合理利用栈的性质来实现,与上面的稍有不同。

前序:

public List preorderTraversal(TreeNode root) {

ArrayList list = new ArrayList();

Stack stk = new Stack<>();

stk.push(root);

while(!stk.isEmpty()){

TreeNode node = stk.pop();

if(node==null)

continue;

list.add(node.val);

stk.push(node.right);

stk.push(node.left);

}

return list;

}

后序:

public List postorderTraversal(TreeNode root) {

LinkedList list = new LinkedList();

Stack stk = new Stack<>();

stk.push(root);

while(!stk.isEmpty()){

TreeNode node = stk.pop();

if(node==null)

continue;

list.addFirst(node.val); //LinkedList's method. If using ArrayList here,then using 'Collections.reverse(list)'' in the end;

stk.push(node.left);

stk.push(node.right);

}

return list;

}

层序遍历

合理利用队列的性质即可。

public void levelOrder() {

BiTNode node =root;

LinkedList> list = new LinkedList<>();

list.add(node);

while(!list.isEmpty()) {

node=list.poll();

System.out.print(node.data);

if(node.lchild!=null)

list.offer(node.lchild);

if(node.rchild!=null)

list.offer(node.rchild);

}

}

完整代码(含测试代码)

package BiTree;

import java.util.LinkedList;

import java.util.Stack;

class BiTNode{

E data;

BiTNode lchild,rchild;

public BiTNode(E data) {

this.data=data;

this.lchild=null;

this.rchild=null;

}

}

public class BiTree {

private BiTNode root;

public BiTree() {

//root=new BiTNode(null, null, null);

root=null;

}

/*

* 前序遍历

*/

public void preOrder() {

preOrderTraverse(root);

System.out.println();

}

private void preOrderTraverse(BiTNode node) {

if(node==null)

return;

System.out.print(node.data);

preOrderTraverse(node.lchild);

preOrderTraverse(node.rchild);

}

/*

* 中序遍历

*/

public void inOrder() {

inOrderTraverse(root);

System.out.println();

}

private void inOrderTraverse(BiTNode node) {

if(node==null)

return;

inOrderTraverse(node.lchild);

System.out.print(node.data);

inOrderTraverse(node.rchild);

}

/*

* 后序遍历

*/

public void postOrder() {

postOrderTraverse(root);

System.out.println();

}

private void postOrderTraverse(BiTNode node) {

if(node==null)

return;

postOrderTraverse(node.lchild);

postOrderTraverse(node.rchild);

System.out.print(node.data);

}

//===============循环遍历===============

/**

* 前序遍历(非递归)

*/

public void preOrder2() {

preOrder2(root);

System.out.println();

}

private void preOrder2(BiTNode node) {

Stack stack = new Stack();

while(node!=null||!stack.isEmpty()) {

while(node!=null) {

System.out.print(node.data);

stack.push(node);

node=node.lchild;

}

node=stack.pop().rchild;

}

}

/**

* 中序遍历

*/

public void inOrder2() {

inOrder2(root);

System.out.println();

}

private void inOrder2(BiTNode node) {

Stack stack = new Stack();

while(node!=null||!stack.isEmpty()) {

while(node!=null) {

stack.push(node);

node=node.lchild;

}

node=stack.pop();

System.out.print(node.data);

node=node.rchild;

}

}

/**

* 后序遍历

*/

public void postOrder2() {

postOrder2(root);

System.out.println();

}

private void postOrder2(BiTNode node) {

Stack stack = new Stack();

Stack tag = new Stack();

//while(node!=null||!stack.isEmpty()) {

//while(node!=null){

//stack.push(node);

//tag.push(0);

//node=node.lchild;

//}

//这里的tag用于标记当前结点是否完成左右子结点遍历(所以用0,1表示)

//while(!tag.isEmpty()&&tag.peek()==1) { //栈顶节点的左右子结点已完成遍历

//System.out.print(stack.pop().data);

//tag.pop();

//}

//if(!tag.isEmpty()) { //上面和这里的 !flag.isEmpty() 不可省略,不然会出错。

//tag.pop();

//tag.push(1);

//node=stack.peek().rchild;

//}

//}

/*后序遍历时,分别从左子树和右子树共两次返回根结点(用tag表示次数),

* 只有从右子树返回时才访问根结点,所以增加一个栈标记到达结点的次序。

*/

while(node!=null||!stack.isEmpty()) {

if(node!=null){

stack.push(node);

tag.push(1); //第一次访问

node=node.lchild;

}else {

if(tag.peek()==2) {

System.out.print(stack.pop().data);

tag.pop();

}else {

tag.pop();

tag.push(2); //第二次访问

node=stack.peek().rchild;

}

}

}

}

//=========层序遍历============

public void levelOrder() {

BiTNode node =root;

LinkedList> list = new LinkedList<>();

list.add(node);

while(!list.isEmpty()) {

node=list.poll();

System.out.print(node.data);

if(node.lchild!=null)

list.offer(node.lchild);

if(node.rchild!=null)

list.offer(node.rchild);

}

}

public static void main(String[] args) {

BiTree aBiTree = new BiTree();

aBiTree.root=new BiTNode("A");

aBiTree.root.lchild=new BiTNode("B");

aBiTree.root.rchild=new BiTNode("C");

aBiTree.root.lchild.rchild=new BiTNode("D");

//BiTree aBiTree = new BiTree();

//aBiTree.root=new BiTNode("A");

//aBiTree.root.lchild=new BiTNode("B");

//aBiTree.root.lchild.lchild=new BiTNode("C");

//aBiTree.root.lchild.lchild.lchild=new BiTNode("D");

//aBiTree.root.lchild.rchild=new BiTNode("E");

//aBiTree.root.lchild.rchild.lchild=new BiTNode("F");

//aBiTree.root.lchild.rchild.lchild.rchild=new BiTNode("G");

//aBiTree.root.lchild.rchild.lchild.rchild.rchild=new BiTNode("H");

System.out.println("————前序————");

aBiTree.preOrder();

aBiTree.preOrder2();

System.out.println("————中序————");

aBiTree.inOrder();

aBiTree.inOrder2();

System.out.println("————后序————");

aBiTree.postOrder();

aBiTree.postOrder2();

System.out.println("————层序遍历————");

aBiTree.levelOrder();

}

}

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

————前序————

ABDC

ABDC

————中序————

BDAC

BDAC

————后序————

DBCA

DBCA

————层序遍历————

ABCD

遍历结果

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值