public static void TreeTraversal() { //Define a binary tree. // 1 // / \ // 2 3 // / \ / \ // 4 5 6 7 TreeNode root = new TreeNode(1); root.left = new TreeNode(2); root.right = new TreeNode(3); root.left.left = new TreeNode(4); root.left.right = new TreeNode(5); root.right.left = new TreeNode(6); root.right.right = new TreeNode(7); List<string> TreePath = root.ListBinaryTreePath1(root); List<string> TreePath2 = root.ListBinaryTreePath2(root); List<int> preResult = root.PreOrderTraversal(root); //1, 2, 4, 5, 3, 6, 7 List<int> preResult_i = root.PreOrderTraversal_Iterative1(root); List<int> preResult_i2 = root.PreOrderTraversal_Iterative2(root); List<int> inResult = root.InOrderTraversal(root); //4, 2, 5, 1, 6, 3, 7 List<int> inResult_i = root.InOrderTraversal_Iterative1(root); List<int> postResult = root.PostOrderTraversal(root); //4, 5, 2, 6, 7, 3, 1 List<int> postResult_i = root.PostOrderTraversal_Iterative1(root); List<int> postResult_i2 = root.PostOrderTraversal_Iterative2(root); List<List<int>> levelResult = root.LevelOrderTraversal(root); }
//DFS: 后序 Post-order Traversal (Left -> Right -> ROOT) using Recursion public List<int> PostOrderTraversal(TreeNode root) { List<int> result = new List<int>(); if (root != null) { result.AddRange(PostOrderTraversal(root.left)); result.AddRange(PostOrderTraversal(root.right)); result.Add(root.val); } return result; }
//--------------------------------------------------------------------- //------------- D F S + I T E R A T I V E ------------------- //--------------------------------------------------------------------- //DFS: 先序 Pre-order Traversal, Stack public List<int> PreOrderTraversal_Iterative1(TreeNode root) { List<int> result = new List<int>(); Stack<TreeNode> stack = new Stack<TreeNode>(); stack.Push(root); while (stack.Count != 0) { root = stack.Pop(); if (root != null) { result.Add(root.val); //Prevent pushing null node to enhance performance. if (root.right != null) stack.Push(root.right); if (root.left != null) stack.Push(root.left); } } return result; }
private static TreeNode AddToTree(int[] array, int start, int end) { if (end < start) { return null; } var mid = (start + end) / 2; var node = new TreeNode(array[mid]); node.SetLeftChild(AddToTree(array, start, mid - 1)); node.SetRightChild(AddToTree(array, mid + 1, end)); return node; }
public void SetRightChild(TreeNode right) { Right = right; if (right != null) { right.Parent = this; } }
public void SetLeftChild(TreeNode left) { Left = left; if (left != null) { left.Parent = this; } }
//DFS: 先序 Pre-order Traversal, Stack public List<int> PreOrderTraversal_Iterative2(TreeNode root) { List<int> result = new List<int>(); Stack<TreeNode> stack = new Stack<TreeNode>(); while (root != null || stack.Count != 0) { if (root != null) { //Store root value first. result.Add(root.val); //Push right child into stack stack.Push(root.right); //Iterate left child first. root = root.left; } else { //if left child does not exist anymore, iterate the nearest right child. root = stack.Pop(); } } return result; }
//------------- D F S + R E C U R S I V E + T O P - D O W N ------------------- //Solution 2: Recursion with helper function. //Key idea: While going deep during recursion, append the current node value into string "path", //But at the same time, each level of recursion kepted its own version of "path" //Once reached leaf node, the "path" is done and add to string list "result" //该方案利用了string类型是绝对引用而List<string>里面装的是对象所以本质上是Reference Variable的特点, //用string类型的path确保每一层的path是独立的,但同时用List<string>类型的result确保所有的path都添加到一个List中并被返回 private void ListBinaryTreePath2_Helper(TreeNode root, string path, List<string> result) { if (root.left == null && root.right == null) result.Add(path + root.val); if (root.left != null) ListBinaryTreePath2_Helper(root.left, path + root.val + "->", result); if (root.right != null) ListBinaryTreePath2_Helper(root.right, path + root.val + "->", result); }
public List<string> ListBinaryTreePath2(TreeNode root) { List<string> treePath = new List<string>(); if (root != null) ListBinaryTreePath2_Helper(root, "", treePath); return treePath; }
//------------- D F S + R E C U R S I V E + B O T T O M - U P ------------------- //Solution 1: Recursion without helper function. //List all root2leaf path in List<string> public List<string> ListBinaryTreePath1(TreeNode root) { //Note that every recursion create its own "result", so what was added in lower level (recursed into) has no affect to the current level. //Processed in Bottom-Up order, the current level will copy each entry (temp[i]) returned from lower level to its own result AFTER recurse bounce back. List<string> temp; List<string> result = new List<string>(); //Null node (List count will remain 0 so NO value copied later.) if (root == null) return result; //Leaf node: Add current level (only one entry) and return if (root.left == null && root.right == null) { result.Add(root.val.ToString()); return result; } //Recurse left subtree: Add current level value to every entry returned from the lower level. temp = ListBinaryTreePath1(root.left); for (int i = 0; i < temp.Count; i++) result.Add(root.val + "->" + temp[i]); //Recurse right subtree: Add current level value to every entry returned from the lower level. temp = ListBinaryTreePath1(root.right); for (int i = 0; i < temp.Count; i++) result.Add(root.val + "->" + temp[i]); return result; }
//--------------------------------------------------------------------- //------------- B F S + I T E R A T I V E ------------------- //--------------------------------------------------------------------- //BFS: Level-order Traversal, Queue public List<List<int>> LevelOrderTraversal(TreeNode root) { List<List<int>> result = new List<List<int>>(); Queue<TreeNode> queue = new Queue<TreeNode>(); queue.Enqueue(root); while (queue.Count != 0) { //Initiate a List<int> container for each level. List<int> level = new List<int>(); //Store the static size as loop condition (this is a must because queue.Count is shrinking in each loop.) int size = queue.Count; for (int i = 0; i < size; i++) { //Dequeue each node root = queue.Dequeue(); //Save the node value level.Add(root.val); //And enqueue its child at the same time if (root.left != null) queue.Enqueue(root.left); if (root.right != null) queue.Enqueue(root.right); } //Save the level after dequeue all the node. result.Add(level); } return result; }
//DFS: 后序 Post-order Traversal, (Reversed Pre-order Traversal) public List<int> PostOrderTraversal_Iterative2(TreeNode root) { List<int> result = new List<int>(); //Iterative: Reverse Pre-Order Traversal. Stack<TreeNode> stack = new Stack<TreeNode>(); while (root != null || stack.Count != 0) { if (root != null) { result.Add(root.val); if (root.left != null) stack.Push(root.left); root = root.right; } else { root = stack.Pop(); } } result.Reverse(); return result; }
//DFS: 后序 Post-order Traversal, Stack public List<int> PostOrderTraversal_Iterative1(TreeNode root) { //Postorder traversal is more complicated to implement comparing to Preorder and Inorder. //At what point shall we visit the root node: //Condition 1: The root node has no child at all. //Condition 2: The root's child has already been visited. List<int> result = new List<int>(); Stack<TreeNode> stack = new Stack<TreeNode>(); if (root != null) stack.Push(root); TreeNode prev = null; while (stack.Count != 0) { root = stack.Peek(); bool noChild = (root.left == null && root.right == null); bool doneChild = false; if (prev != null && (prev == root.left || prev == root.right)) doneChild = true; //直到没有child了或者child已经访问完了才把栈顶元素出栈 if (noChild || doneChild) { root = stack.Pop(); result.Add(root.val); prev = root; } else { if (root.right != null) stack.Push(root.right); if (root.left != null) stack.Push(root.left); } } return result; }
//DFS: 中序 In-order Traversal, Stack public List<int> InOrderTraversal_Iterative1(TreeNode root) { //Step 1: Iterate left subtree, push left node into stack. //Step 2: Stop push until node is null (its parent has no left child). //Step 3: Pop current node, store the value. //Step 4: Switch to the right subtree and iterate right subtree, List<int> result = new List<int>(); Stack<TreeNode> stack = new Stack<TreeNode>(); //Stop loop when both root is null and stack is empty. while (root != null || stack.Count != 0) { if (root != null) { //Store root for later use stack.Push(root); //Iterate left child first. root = root.left; } else { //If left child does not exist anymore, extract its parent root = stack.Pop(); //And store parent value result.Add(root.val); //Then iterate its right child. root = root.right; } } return result; }