一、二叉树对象
public class Node {
public Node left;
public Node right;
public String value;
public Node() {
super();
}
public Node(String value) {
super();
this.value = value;
}
}
二、递归遍历
递归过程中每个节点到达三次,存在前中后三种顺序。时间复杂度O(N),空间复杂度O(N)
2.1 前序遍历
public static void preOrder(Node head) {
if(head == null) {
return;
}
System.out.print(head.value);
preOrder(head.left);
preOrder(head.right);
}
2.2 中序遍历
public static void midOrder(Node head) {
if(head == null) {
return;
}
midOrder(head.left);
System.out.print(head.value);
midOrder(head.right);
}
2.3 后续遍历
public static void afterOrder(Node head) {
if(head == null) {
return;
}
afterOrder(head.left);
afterOrder(head.right);
System.out.print(head.value);
}
三、非递归方式
前序遍历与中序遍历需要基于栈结构。后续遍历使用到两个栈结构。时间复杂度O(N),空间复杂度O(N)
3.1 前序遍历
public static void preOrderByStack(Node head) {
Stack<Node> stack = new Stack<>();
stack.push(head);
while(!stack.empty()) {
Node node = stack.pop();
System.out.print(node.value);
if(node.right != null) {
stack.push(node.right);
}
if(node.left != null) {
stack.push(node.left);
}
}
}
3.2 中序遍历
public static void midOrderByStack(Node head) {
Stack<Node> stack = new Stack<>();
while(!stack.empty() || head != null) {
if(head != null) {
stack.push(head);
head = head.left;
} else {
head = stack.pop();
System.out.print(head.value);
head = head.right;
}
}
}
3.3 后续遍历
public static void afterOrderByStack(Node head) {
Stack<Node> stack = new Stack<>();
Stack<Node> result = new Stack<>();
stack.push(head);
while (!stack.empty()) {
head = stack.pop();
result.push(head);
if(head.left != null) {
stack.push(head.left);
}
if(head.right != null) {
stack.push(head.right);
}
}
while (!result.empty()) {
System.out.print(result.pop().value);
}
}
四、按层遍历
按层遍历使用到辅助队列,时间空间复杂度为O(N)
public static String serialByLevel(Node head) {
if (head == null) {
return "#!";
}
String res = head.value + "!";
Queue<Node> queue = new LinkedList<>();
queue.offer(head);
while (!queue.isEmpty()) {
head = queue.poll();
if (head.left != null) {
res += head.left.value + "!";
queue.offer(head.left);
} else {
res += "#!";
}
if (head.right != null) {
res += head.right.value + "!";
queue.offer(head.right);
} else {
res += "#!";
}
}
return res;
}
五、Morris遍历
Morris遍历时间复杂度O(N),空间复杂度O(1)
三条原则:
1、current节点如果没有左孩子,current向右移
2、current节点有左孩子,找到左子树的最右节点记为mostRight,如果mostRight的右指针为空,让其指向current,current向左移。
3、如果mostRight的右指针为current,让其为空,current向右移动。
5.1 前序遍历
public static void morrisPre(Node head) {
if (head == null) {
return;
}
Node current = head;
Node mostRight = null;
while (current != null) {
mostRight = current.left;
if (mostRight != null) {
while (mostRight.right != null && mostRight.right != current) {
mostRight = mostRight.right;
}
if (mostRight.right == null) {
mostRight.right = current;
System.out.print(current.value + " ");
current = current.left;
continue;
} else {
mostRight.right = null;
}
} else {
System.out.print(current.value + " ");
}
current = current.right;
}
System.out.println();
}
5.2 中序遍历
public static void morrisIn(Node head) {
if (head == null) {
return;
}
Node cur1 = head;
Node cur2 = null;
while (cur1 != null) {
cur2 = cur1.left;
if (cur2 != null) {
while (cur2.right != null && cur2.right != cur1) {
cur2 = cur2.right;
}
if (cur2.right == null) {
cur2.right = cur1;
cur1 = cur1.left;
continue;
} else {
cur2.right = null;
}
}
System.out.print(cur1.value + " ");
cur1 = cur1.right;
}
System.out.println();
}
5.3 后续遍历
public static void morrisPos(Node head) {
if (head == null) {
return;
}
Node cur1 = head;
Node cur2 = null;
while (cur1 != null) {
cur2 = cur1.left;
if (cur2 != null) {
while (cur2.right != null && cur2.right != cur1) {
cur2 = cur2.right;
}
if (cur2.right == null) {
cur2.right = cur1;
cur1 = cur1.left;
continue;
} else {
cur2.right = null;
printEdge(cur1.left);
}
}
cur1 = cur1.right;
}
printEdge(head);
System.out.println();
}
public static void printEdge(Node head) {
Node tail = reverseEdge(head);
Node cur = tail;
while (cur != null) {
System.out.print(cur.value + " ");
cur = cur.right;
}
reverseEdge(tail);
}
public static Node reverseEdge(Node from) {
Node pre = null;
Node next = null;
while (from != null) {
next = from.right;
from.right = pre;
pre = from;
from = next;
}
return pre;
}