樹的遍歷方式總體上有兩種:DFS和BFS;
其中DFS包含了前序、中序和后序遍歷,而BFS則為層次遍歷。
DFS的實現方式:
(1) 遞歸;
(2) 非遞歸,使用輔助棧;
遞歸程序
public class Recursion {
public void preorderRec(TreeNode root) {
if (root == null) {
return;
}
System.out.println(root.val); // visit the node
preorderRec(root.left);
preorderRec(root.right);
}
public void inorderRec(TreeNode root) {
if (root == null) {
return;
}
preorderRec(root.left);
System.out.println(root.val); // visit the node
preorderRec(root.right);
}
public void postorderRec(TreeNode root) {
if (root == null) {
return;
}
preorderRec(root.left);
preorderRec(root.right);
System.out.println(root.val); // visit the node
}
}
非遞歸程序
public class NoRecursion {
public void preorder(TreeNode root) {
if (root == null) {
return;
}
Stack<TreeNode> s = new Stack<TreeNode>();
TreeNode node = root;
while (node != null || !s.isEmpty()) {
while (node != null) {
System.out.println(node.val); // visit the node
s.push(node);
node = node.left;
}
if (!s.isEmpty()) {
node = s.pop();
node = node.right;
}
}
}
public void inorder(TreeNode root) {
if (root == null) {
return;
}
Stack<TreeNode> s = new Stack<TreeNode>();
TreeNode node = root;
while (node != null || !s.isEmpty()) {
while (node != null) {
s.push(node);
node = node.left;
}
if (!s.isEmpty()) {
node = s.pop();
System.out.println(node.val);
node = node.right;
}
}
}
public void postorder(TreeNode root) {
if (root == null) {
return;
}
Stack<TreeNode> s = new Stack<TreeNode>();
TreeNode node = root;
TreeNode pre = null;
while (node != null || !s.isEmpty()) {
while (node != null) {
s.push(node);
node = node.left;
}
if (!s.isEmpty()) {
node = s.peek();
if (node.right != null && node.right != pre) {
node = node.right;
} else {
node = s.pop();
pre = node; // pre point the last visited node
System.out.println(node.val); // visit the node
node = null;
}
}
}
}
}
其中,后序遍歷稍微困難了一點,主要原因在於在遍歷樹中節點的同時需要記錄最后訪問節點。舉例說明,如有一棵樹如下:
1
| \
2 3
\
4
后序遍歷的做法如下:
(1) 將根節點的左節點們依次加入棧中,最后棧頂元素為左子樹的最左節點;
(2) 拿到棧頂元素(此時不出棧),如果沒有右孩子並且右孩子沒有被訪問過,則出棧,此時標記下該出棧元素(表示該元素已被訪問過);否則節點指向其右孩子。然后到(1);
(3) 遍歷程序的結束條件為棧為空並且節點為空;
時間/空間復雜度分析
時間復雜度均為O(n);空間復雜度平均情況下為O(logn),最壞情況下為O(n).
BFS的實現方式:
層次遍歷,使用一個輔助隊列。
public void levelTraversal(TreeNode root){
if (root == null) {
return ;
}
Queue<TreeNode> q = new LinkedList<TreeNode>();
q.offer(root);
while (!q.isEmpty()) {
int size = q.size();
for (int i = 0; i < size; i++) {
TreeNode node = q.poll();
System.out.println(node.val); // visit the node
if (node.left!=null) {
q.offer(node.left);
}
if (node.right!=null) {
q.offer(node.right);
}
}
}
}
時間復雜度和空間復雜度均為O(n).
