一、二叉树的的遍历
构建二叉树的数据结构
class BinaryTree{
int val;
BinaryTree left;
BinaryTree right;
public BinaryTree(int val){
this.val=val;
}
}
1、前序遍历
1.1递归实现
实现思路:**先根节点,再左节点,最后右节点。**构建递归时有两个要点需要特别注意,一是递归结束的条件,一是递归表达式(即递归如何进行下去)。
class Traversal{
public void preorderBT(BinaryTree root) {
//结束条件
if (root == null)
return;
System.out.print(root.val + " ");
preorderBT(root.left);
preorderBT(root.right);
}
}
1.2 非递归实现
实现思路:需要用到栈这种数据结构(为什么是栈,不是别的数据结构)。因为递归实现的过程就是程序自己在处理圧栈和弹栈,改用非递归实现时,用栈模拟系统的圧栈与弹栈,就可以了。
import java.util.List;
import java.util.ArrayList;
import java.util.Stack;
public List<Integer> preorderBT1(BinaryTree root) {
List<Integer> preorderResult = new ArrayList<>();
Stack<BinaryTree> stack = new Stack<>();
BinaryTree currentNode = root;
while (currentNode != null || !stack.isEmpty()) {
//对于前序遍历,需要一直往二叉树的左子树上走,直道左子树走完。在走左子树的过程中需要输出遇到节点的值
while (currentNode != null) {
preorderResult.add(currentNode.val);
stack.push(currentNode);
currentNode = currentNode.left;
}
//左边的节点都走完了,需要改变节点方向
if (!stack.isEmpty()) {
currentNode = stack.pop();
currentNode = currentNode.right;
}
}
return preorderResult;
}
2、中序遍历
2.1递归实现
实现思路:左子树—> 根结点 —> 右子树
public void inorderBT(BinaryTree root) {
//结束条件
if (root == null)
return;
inorderBT(root.left);
System.out.print(root.val + " ");
inorderBT(root.right);
}
2.2非递归实现
public List<Integer> inorderBT1(BinaryTree root) {
List<Integer> inorderResult = new ArrayList<>();
Stack<BinaryTree> stack = new Stack<>();
BinaryTree currentNode = root;
while (currentNode != null || !stack.isEmpty()) {
//一直向左,但是先不打印经历的节点的值
while (currentNode != null) {
stack.push(currentNode);
currentNode = currentNode.left;
}
//到达最左边,打印并改变方向
if (!stack.isEmpty()) {
currentNode = stack.pop();
inorderResult.add(currentNode.val);
currentNode = currentNode.right;
}
}
return inorderResult;
}
3、后序遍历
3.1递归实现
实现思路:左子树 —> 右子树 —> 根结点
public void postorderBT(BinaryTree root) {
if (root == null)
return;
postorderBT(root.left);
postorderBT(root.right);
System.out.print(root.val+" ");
}
3.2非递归实现
妙用前序遍历的非递归可以实现后序遍历的非递归实现,这里需要注意几点改变:后序时,先遍历右,再遍历左,最后将得到的结果反向就好了。
public List<Integer> postorderBT1(BinaryTree root) {
List<Integer> postorderResult = new ArrayList<>();
Stack<BinaryTree> stack = new Stack<>();
BinaryTree currentNode = root;
while (currentNode != null || !stack.isEmpty()) {
while (currentNode != null) {
postorderResult.add(currentNode.val);
stack.push(currentNode);
currentNode = currentNode.right;
}
if (!stack.isEmpty()) {
currentNode = stack.pop();
currentNode = currentNode.left;
}
}
Collections.reverse(postorderResult);
return postorderResult;
}
4、层次遍历
层次遍历,需要用到队列这种数据结构
import java.util.List;
import java.util.ArrayList;
import java.util.Deque;
import java.util.ArrayDeque;
public List<Integer> levelOrderBT(BinaryTree root) {
List<Integer> levelResult = new ArrayList<>();
Deque<BinaryTree> deque = new ArrayDeque<>();
if (root==null)
return levelResult;
deque.addLast(root);
BinaryTree currentNode = root;
while (!deque.isEmpty()){
currentNode = deque.pollFirst();
if (currentNode.left!=null)
deque.addLast(currentNode.left);
if (currentNode.right!=null)
deque.addLast(currentNode.right);
levelResult.add(currentNode.val);
}
return levelResult;
}
5、测试
public class TraversalTest {
//构架测试用的二叉树
public static BinaryTree createBT() {
BinaryTree node0 = new BinaryTree(6);
BinaryTree node1 = new BinaryTree(8);
BinaryTree node2 = new BinaryTree(5);
BinaryTree node3 = new BinaryTree(4);
BinaryTree node4 = new BinaryTree(3);
BinaryTree node5 = new BinaryTree(9);
BinaryTree node6 = new BinaryTree(1);
BinaryTree node7 = new BinaryTree(2);
node0.left = node1;
node0.right = node2;
node1.left = node3;
node1.right = node4;
node2.right = node5;
node4.left = node6;
node4.right = node7;
return node0;
}
static Traversal traversal = new Traversal();
@Test
public void preorderBT() {
BinaryTree root = TraversalTest.createBT();
traversal.preorderBT(root);
}
@Test
public void preorderBT1() {
BinaryTree root = TraversalTest.createBT();
List<Integer> list = traversal.preorderBT1(root);
System.out.println(list.toString());
}
}