DFS (Deep First Search) depth first search and BFS (Breath First Search) breadth first search
DFS: uses the stack structure, first in and last out, focusing on recursion and finding specific targets
BFS: queue structure is used, first in first out, focusing on the queue, which is suitable for large-scale search
Depth first of binary tree
Preorder traversal of binary tree
Middle order traversal of binary tree
Binary Tree Postorder Traversal
(the following solution takes middle order traversal as an example)
1. Recursion
Time complexity: O(n)
Space complexity: O(n)
First judge whether the root node exists, then traverse the left node, and finally traverse the right node
var inorderTraversal = function(root) { const res = []; const inorder = (root) => { if (!root) { return; } inorder(root.left); res.push(root.val); inorder(root.right); } inorder(root); return res; };
2. Iteration
Time complexity: O(n)
Space complexity: O(n)
Similar to method 1, the difference is that a stack is implicitly maintained during recursion, and the stack needs to be explicitly simulated during iteration. The rest of the implementation and details are the same
var inorderTraversal = function(root) { const res = []; const stk = []; while (root || stk.length) { while (root) { stk.push(root); root = root.left; } root = stk.pop(); res.push(root.val); root = root.right; } return res; };
3. Morris traversal
Time complexity: O(n)
Space complexity: O(1)
- If there is no left node, first add the value to the answer array, and then access the right node, that is, x = x.right
- If there is a left node, find the rightmost node on the left node (that is, the last node in the order traversal of the left subtree and the precursor node in the order traversal) and record it as a predecessor. According to whether the right node of the predictor is empty, perform the following operations:
- If the right node of \ textit {predicessor} predicessor is empty, point its right node to x, and then access the left node, that is, x = x.left
- If the right node of the predecessor is not empty, then its right node points to x, indicating that the left subtree has been traversed. We leave the right node of the predecessor empty, add the value of X to the answer array, and then access the right node of X, that is, x = x.right
- Repeat until the entire tree is accessed
var inorderTraversal = function(root) { const res = []; let predecessor = null; while (root) { if (root.left) { // The predecessor node is the current root node that moves one step to the left, and then moves all the way to the right until it cannot move predecessor = root.left; while (predecessor.right && predecessor.right !== root) { predecessor = predecessor.right; } // Let the right pointer of the predecessor point to root and continue to traverse the left subtree if (!predecessor.right) { predecessor.right = root; root = root.left; } // It means that the left subtree has been accessed. We need to disconnect the link else { res.push(root.val); predecessor.right = null; root = root.right; } } // If there is no left child, access the right child directly else { res.push(root.val); root = root.right; } } return res; };
Breadth traversal of binary tree
Sequence traversal of binary tree
Time complexity: O(n)
Space complexity: O(n)
var levelOrder = function(root) { const ret = []; if (!root) { return ret; } const q = []; q.push(root); while (q.length !== 0) { const currentLevelSize = q.length; ret.push([]); for (let i = 1; i <= currentLevelSize; ++i) { const node = q.shift(); ret[ret.length - 1].push(node.val); if (node.left) q.push(node.left); if (node.right) q.push(node.right); } } return ret; };