Java 实现二叉树的先序、中序、后序、层序遍历,用递归和非递归方法
欢迎大佬指导
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
public class BinaryTree { //二叉树的实现类
private class Node { //数据结构中必须有Node类
@SuppressWarnings({ "rawtypes", "unused" })
private Comparable data;
private Node left;
private Node right;
@SuppressWarnings("rawtypes")
public Node(Comparable data2) { //constructor
this.data = data2;
}
@SuppressWarnings("unchecked")
public void add(Node newNode) { //添加节点
if (this.data.compareTo(newNode.data) > 0) { //如果小于当前节点值,放在左儿子
if (this.left == null) { //如果左儿子为空
this.left = newNode;
} else { //如果左儿子不为空,继续向下递归实现
this.left.add(newNode);
}
} else { //如果大于或等于当前节点值,放在右儿子
if (this.right == null) {
this.right = newNode;
} else {
this.right.add(newNode);
}
}
}
public void toArrayNode() { //中序遍历
if (this.left!=null) { //有左节点
this.left.toArrayNode();
}
BinaryTree.this.retData[BinaryTree.this.foot++] = this.data;
if (this.right!=null) {
this.right.toArrayNode();
}
}
public void PretoArray() { //先序遍历
BinaryTree.this.retData[BinaryTree.this.foot++] = this.data;
if (this.left!=null) {
this.left.PretoArray();
}
if (this.right!=null) {
this.right.PretoArray();
}
}
public void PosttoArray() { //后序遍历
if (this.left!=null) {
this.left.PosttoArray();
}
if (this.right!=null) {
this.right.PosttoArray();;
}
BinaryTree.this.retData[BinaryTree.this.foot++] = this.data;
}
}
//*********** 编写BinaryTree操作 ***********
private Node root; //必须保留根节点
private int count = 0; //保留节点个数
private int foot = 0; //数组下标
private Object [] retData ;
@SuppressWarnings("rawtypes")
public void add(Object obj) { //添加数据
Comparable data = (Comparable)obj; //转型位Comparable类型,不然会报错
Node newNode = new Node(data); //把当前数值添加位Node类
if (this.root == null) { //如果根节点为空,添加为根节点
this.root = newNode;
} else {
this.root.add(newNode); //否则交给 Node类实现
}
this.count ++;
}
public Object [] toArray() { //中序输出节点数值
if ( this.count > 0 ) {
this.foot = 0; //输出标记(下标),
this.retData = new Object[this.count];
this.root.toArrayNode();
return this.retData ;
} else {
return null;
}
}
public Object [] PretoArray() { //先序输出节点数值
if (this.count > 0) {
this.foot = 0;
this.retData = new Object[this.count];
this.root.PretoArray();
return this.retData;
} else {
return null;
}
}
public Object[] PosttoArray() { //后序输出节点数值
if (this.count > 0) {
this.foot = 0;
this.retData = new Object[this.count];
this.root.PosttoArray();
return this.retData;
} else {
return null;
}
}
public Object[] LevertoArray() { //层序输出节点数值(数组)(非递归)
if (this.count > 0) {
Queue<Node> Q = new LinkedList<>();
this.foot = 0;
Q.add(this.root);
while (!Q.isEmpty()) {
int len = Q.size();
for (int i=0; i<len; i++) {
Node temp = Q.poll();
this.retData[foot++] = temp.data;
if (temp.left!=null) Q.add(temp.left);
if (temp.right!=null) Q.add(temp.right);
}
}
return this.retData;
} else {
return null;
}
}
public void LeverOrder() { //层序遍历(非递归)
if (this.count > 0) {
Queue<Node> Q = new LinkedList<>();
Q.add(this.root);
while (!Q.isEmpty()) {
int len = Q.size();
for (int i=0; i<len; i++) {
Node temp = Q.poll();
System.out.print(temp.data+" ");
if (temp.left!=null) Q.add(temp.left);
if (temp.right!=null) Q.add(temp.right);
}
}
} else {
return ;
}
}
/*
* 用栈实现循环先序遍历二叉树
* 这种实现类似于图的深度优先遍历(DFS)
* 维护一个栈,将根节点入栈,然后只要栈不为空,出栈并访问,接着依次将访问节点的右节点、左节点入栈。
* 这种方式应该是对先序遍历的一种特殊实现(看上去简单明了),但是不具备很好的扩展性,在中序和后序方式中不适用
*/
public void preOrderStack_1() { //先序遍历(非递归)
if (this.root==null)
return ;
Stack<Node> S = new Stack<>();
S.push(this.root);
while (!S.isEmpty()) {
Node temp = S.pop();
System.out.print(temp.data+" ");
if (temp.right!=null) S.push(temp.right);
if (temp.left!=null) S.push(temp.left);
}
}
/*
* 利用栈模拟递归过程实现循环先序遍历二叉树
* 这种方式具备扩展性,它模拟递归的过程,将左子树点不断的压入栈,直到null,然后处理栈顶节点的右子树
*/
public void preOrderStack_2() { //先序遍历(非递归)
Node t = this.root; //目的是使root始终是根节点
if (t==null)
return ;
Stack<Node> S = new Stack<>();
while (t!=null || !S.isEmpty()) {
while (t!=null) {
System.out.print(t.data+" ");
S.push(t);
t = t.left;
}
t = S.pop();
t = t.right;
}
}
/*
* 利用栈模拟递归过程实现循环中序遍历二叉树
* 思想和上面的preOrderStack_2相同,
* 只是访问的时间是在左子树都处理完直到null的时候出栈并访问。
*/
public void inOrderStack() { //中序遍历
Node t = this.root; //目的是使root始终是根节点
if (t==null)
return ;
Stack<Node> S = new Stack<>();
while (t!=null || !S.isEmpty()) {
while (t!=null) {
S.push(t);
t = t.left;
}
t = S.pop();
System.out.print(t.data+" ");
t = t.right;
}
}
}
Test 类
import java.util.Arrays;
public class Test_BinaryTree {
public static void main(String[] args) {
BinaryTree bt = new BinaryTree();
bt.add("4");
bt.add("7");
bt.add("6");
bt.add("2");
bt.add("1");
bt.add("3");
bt.add("5");
System.out.println("数组递归实现先序遍历 " + Arrays.toString(bt.PretoArray()));
System.out.println("数组递归实现中序遍历(按从小到大排序) " + Arrays.toString(bt.toArray()));
System.out.println("数组递归实现后序遍历 " + Arrays.toString(bt.PosttoArray()));
System.out.println("数组非递归实现层序遍历 " + Arrays.toString(bt.LevertoArray()));
System.out.print("非递归实现层序遍历 ");
bt.LeverOrder();
System.out.print("\n非递归实现先序遍历 ");
bt.preOrderStack_1();
System.out.print("\n非递归实现先序遍历 ");
bt.preOrderStack_2();
System.out.print("\n非递归实现中序遍历 ");
bt.inOrderStack();
}
}
结果
数组递归实现先序遍历 [4, 2, 1, 3, 7, 6, 5]
数组递归实现中序遍历(按从小到大排序) [1, 2, 3, 4, 5, 6, 7]
数组递归实现后序遍历 [1, 3, 2, 5, 6, 7, 4]
数组非递归实现层序遍历 [4, 2, 7, 1, 3, 6, 5]
非递归实现层序遍历 4 2 7 1 3 6 5
非递归实现先序遍历 4 2 1 3 7 6 5
非递归实现先序遍历 4 2 1 3 7 6 5
非递归实现中序遍历 1 2 3 4 5 6 7
有些来源于博客https://blog.csdn.net/kerryfish/article/details/24309617