二叉树,大家都很熟悉,这里我就不解释咯。今天记录一下二叉树的三种遍历方法(递归实现和非递归实现)
首先我们先定一个棵树
代码如下:
public class Node {
private String date;
private Node left;
private Node right;
private int level = 0; //层数
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
public Node() {
}
public static void setTreeNodes(Node node, int level) {
if (node.getLevel() >= 3) {
return;
}
node.setDate(UUID.randomUUID().toString());
Node left = new Node();
left.setLevel(level + 1);
Node right = new Node();
right.setLevel(level + 1);
left.setDate(UUID.randomUUID().toString());
right.setDate(UUID.randomUUID().toString());
node.setLeft(left);
node.setRight(right);
setTreeNodes(node.getLeft(), level + 1);
setTreeNodes(node.getRight(), level + 1);
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
}
改代码里面的静态方法是构造出一个又数据的二叉树。方便我们测试的时候使用。level属性是代表节点的层数,从0开始计算。
前序遍历:
(1)递归算法
/**
* 前序遍历(根 -> 左-> 右)时间复杂度为O(n),因为每个节点都要遍历。
* @param node
*/
public void preOrder(Node node) {
if (node == null) {
return;
}
System.out.println(node.getDate());
//左
preOrder(node.getLeft());
//右
preOrder(node.getRight());
}
(1)非递归:
public void preOrderNotRecursion(Node node) {
if (node == null) {
return;
}
Stack<Node> stack = new Stack<>();
//节点入栈
stack.push(node);
//栈不会空的话,一直循环
while (!stack.isEmpty()) {
//节点出栈
node = stack.pop();
//因为树的叶子节点下面的左右节点为空,所有需要判断null
if (node == null) {
continue;
}
System.out.println(node.getDate());
//左右儿子入栈
stack.push(node.getLeft());
stack.push(node.getRight());
}
}
中序遍历
(1)递归算法
/**
* 中序遍历 (左 -> 根 -> 右)
* @param node
*/
public void inOrder(Node node) {
if (node == null) {
return;
}
inOrder(node.getLeft());
System.out.println(node.getDate());
inOrder(node.getRight());
}
(2)非递归
/**
* 中序遍历非递归算法
* @param node
*/
public void inOrderNotRecursion(Node node) {
if (node == null) {
return;
}
Stack<Node> stack = new Stack<>();
while (!stack.isEmpty() || node != null) {
if (node != null) {
stack.push(node);
node = node.getLeft();
}else{
node = stack.pop();
System.out.println(node.getDate());
node = node.getRight();
}
}
}
后序遍历
(1)递归算法
/**
* 后序遍历
* @param node
*/
public void postOrder(Node node) {
if (node == null) {
return;
}
postOrder(node.getLeft());
postOrder(node.getRight());
System.out.println(node.getDate());
}
(2)非递归算法
public void postOrderNotRecursion(Node node) {
if (node == null) {
return;
}
//s2用于存放遍历后的节点(已排好顺序)
Stack<Node> s1 = new Stack<>();
Stack<Node> s2 = new Stack<>();
s1.push(node);
while (!s1.isEmpty()) {
node = s1.pop();
s2.push(node);
if (node.getLeft() != null) {
s1.push(node.getLeft());
}
if (node.getRight() != null) {
s1.push(node.getRight());
}
}
while (!s2.isEmpty()) {
System.out.println(s2.pop().getDate());
}
}
测试代码:
public static void main(String[] args) {
Node root = new Node();
Node.setTreeNodes(root, 0);
long start = System.currentTimeMillis();
//new TreeOrder().preOrder(root);
//new TreeOrder().preOrderNotRecursion(root);
//new TreeOrder().inOrder(root);
//new TreeOrder().inOrderNotRecursion(root);
new TreeOrder().postOrder(root);
System.out.println("-----------");
new TreeOrder().postOrderNotRecursion(root);
System.out.println("耗时:" + (System.currentTimeMillis() - start));
}