浅谈数据结构之树的基础算法(二)
二叉树遍历
前序遍历: 先访问根节点,然后遍历左子树,最后遍历右子树
中序遍历: 先遍历左子树,然后遍历根节点,最后遍历右子树
后续遍历: 先遍历左子树,然后遍历右子树,最后便利根节点
层次遍历: 从上到下逐层遍历,在同一层中,按从左到右的顺序遍历
前序遍历
中序遍历
后续遍历
层序遍历
二叉树非递归遍历算法
数据结构类TreeNode定义
public class TreeNode {
public String value;
public TreeNode left;
public TreeNode right;
public TreeNode(String value) {
this.value = value;
}
}
四种遍历算法实战
public class Traverse {
/**
* 非递归实现前序遍历
* 先访问根节点,然后遍历左子树,最后遍历右子树
* @param head
*/
public static void preOrder(TreeNode head) {
if (null != head) {
// 采用栈来存储遍历过程,利用栈的先进后数据结构
Stack<TreeNode> stack = new Stack();
// 先把根节点压栈,然后开始遍历
stack.push(head);
while (!stack.isEmpty()) {
TreeNode pop = stack.pop();
System.out.print(pop.value + " ");
// 必须先判断右节点,在判断左节点,右节点先入站,则后出栈,刚好满足先遍历左节点,在遍历右节点
if (pop.right != null) {
stack.push(pop.right);
}
if (pop.left != null) {
stack.push(pop.left);
}
}
}
}
/**
* 非递归实现中序遍历
* 先遍历左子树,然后遍历根节点,最后遍历右子树
* @param head
*/
public static void inOrder(TreeNode head) {
if(head != null) {
Stack<TreeNode> stack = new Stack();
while (!stack.isEmpty() || head != null) {
if (head != null) {
//先把根节点入栈,然后再把左子树全部压栈,直到叶子节点,然后执行else弹出
stack.push(head);
head = head.left;
} else {
head = stack.pop();
System.out.print(head.value + " ");
head = head.right;
}
}
}
}
/**
* 非递归实现后续遍历
* 先遍历左子树,然后遍历右子树,最后便利根节点
* @param head
*/
public static void postOrder(TreeNode head) {
if (null != head) {
Stack<TreeNode> stack1 = new Stack();
Stack<TreeNode> stack2 = new Stack();
stack1.push(head);
while (!stack1.isEmpty()) {
TreeNode pop = stack1.pop();
stack2.push(pop);
if (pop.left != null) {
stack1.push(pop.left);
}
if (pop.right != null) {
stack1.push(pop.right);
}
}
while (!stack2.isEmpty()) {
System.out.print(stack2.pop().value + " ");
}
}
}
/**
* 非递归实现层次遍历
* 从上到下逐层遍历,在同一层中,按从左到右的顺序遍历
* @param head
*/
public static void levelOrder(TreeNode head) {
if (head != null) {
// 采用队列的数据结构特点实现遍历
Queue<TreeNode> queue = new ArrayDeque<>();
queue.offer(head);
while (!queue.isEmpty()) {
int levelNum = queue.size();
for (int i = 0; i < levelNum; i++) {
TreeNode poll = queue.poll();
System.out.print(poll.value + " ");
if (poll.left != null) {
queue.offer(poll.left);
}
if (poll.right != null) {
queue.offer(poll.right);
}
}
}
}
}
public static void main(String[] args) {
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");
TreeNode J = new TreeNode("J");
TreeNode K = new TreeNode("K");
A.left = B;
A.right = C;
B.left = D;
B.right = E;
D.left = H;
D.right = I;
E.right = J;
C.left = F;
C.right = G;
F.right = K;
System.out.print("前序遍历:");
preOrder(A);
System.out.println();
System.out.print("中序遍历:");
inOrder(A);
System.out.println();
System.out.print("后序遍历:");
postOrder(A);
System.out.println();
System.out.print("层次遍历:");
levelOrder(A);
}
前序遍历:A B D H I E J C F K G
中序遍历:H D I B E J A F K C G
后序遍历:H I D J E B K F G C A
层次遍历:A B C D E F G H I J K
二叉树递归遍历算法
层次递归遍历由于控制结束条件比较复杂,因此不在此讨论,实现上多以队列的数据结构辅助遍历
public class Traverse {
/**
* 递归实现前序遍历
* 先访问根节点,然后遍历左子树,最后遍历右子树
* @param head
*/
public static void recursionPreOrder(TreeNode head) {
// 终止条件
if (null == head) {return;}
System.out.print(head.value + " ");
recursionPreOrder(head.left);
recursionPreOrder(head.right);
}
/**
* 递归实现中序遍历
* 先遍历左子树,然后遍历根节点,最后遍历右子树
* @param head
*/
public static void recursionInOrder(TreeNode head) {
// 终止条件
if(null == head) {return;}
recursionInOrder(head.left);
System.out.print(head.value + " ");
recursionInOrder(head.right);
}
/**
* 递归实现后续遍历
* 先遍历左子树,然后遍历右子树,最后便利根节点
* @param head
*/
public static void recursionPostOrder(TreeNode head) {
// 终止条件
if (null == head) {return;}
recursionPostOrder(head.left);
recursionPostOrder(head.right);
System.out.print(head.value + " ");
}
public static void main(String[] args) {
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");
TreeNode J = new TreeNode("J");
TreeNode K = new TreeNode("K");
A.left = B;
A.right = C;
B.left = D;
B.right = E;
D.left = H;
D.right = I;
E.right = J;
C.left = F;
C.right = G;
F.right = K;
System.out.print("前序遍历:");
recursionPreOrder(A);
System.out.println();
System.out.print("中序遍历:");
recursionInOrder(A);
System.out.println();
System.out.print("后序遍历:");
recursionPostOrder(A);
}
}
前序遍历:A B D H I E J C F K G
中序遍历:H D I B E J A F K C G
后序遍历:H I D J E B K F G C A