diff --git a/codes/csharp/chapter_tree/array_binary_tree.cs b/codes/csharp/chapter_tree/array_binary_tree.cs new file mode 100644 index 000000000..51f565811 --- /dev/null +++ b/codes/csharp/chapter_tree/array_binary_tree.cs @@ -0,0 +1,134 @@ +/** +* File: array_binary_tree.cs +* Created Time: 2023-07-20 +* Author: hpstory (hpstory1024@163.com) +*/ + +namespace hello_algo.chapter_tree; + +/* 数组表示下的二叉树类 */ +public class ArrayBinaryTree { + private List tree; + + /* 构造方法 */ + public ArrayBinaryTree(List arr) { + tree = new List(arr); + } + + /* 节点数量 */ + public int size() { + return tree.Count; + } + + /* 获取索引为 i 节点的值 */ + public int? val(int i) { + // 若索引越界,则返回 null ,代表空位 + if (i < 0 || i >= size()) + return null; + return tree[i]; + } + + /* 获取索引为 i 节点的左子节点的索引 */ + public int left(int i) { + return 2 * i + 1; + } + + /* 获取索引为 i 节点的右子节点的索引 */ + public int right(int i) { + return 2 * i + 2; + } + + /* 获取索引为 i 节点的父节点的索引 */ + public int parent(int i) { + return (i - 1) / 2; + } + + /* 层序遍历 */ + public List levelOrder() { + List res = new List(); + // 直接遍历数组 + for (int i = 0; i < size(); i++) { + if (val(i).HasValue) + res.Add(val(i).Value); + } + return res; + } + + /* 深度优先遍历 */ + private void dfs(int i, string order, List res) { + // 若为空位,则返回 + if (!val(i).HasValue) + return; + // 前序遍历 + if (order == "pre") + res.Add(val(i).Value); + dfs(left(i), order, res); + // 中序遍历 + if (order == "in") + res.Add(val(i).Value); + dfs(right(i), order, res); + // 后序遍历 + if (order == "post") + res.Add(val(i).Value); + } + + /* 前序遍历 */ + public List preOrder() { + List res = new List(); + dfs(0, "pre", res); + return res; + } + + /* 中序遍历 */ + public List inOrder() { + List res = new List(); + dfs(0, "in", res); + return res; + } + + /* 后序遍历 */ + public List postOrder() { + List res = new List(); + dfs(0, "post", res); + return res; + } +} + +public class array_binary_tree { + [Test] + public void Test() { + // 初始化二叉树 + // 这里借助了一个从数组直接生成二叉树的函数 + List arr = new List { 1, 2, 3, 4, null, 6, 7, 8, 9, null, null, 12, null, null, 15 }; + + TreeNode root = TreeNode.ListToTree(arr); + Console.WriteLine("\n初始化二叉树\n"); + Console.WriteLine("二叉树的数组表示:"); + Console.WriteLine(arr.PrintList()); + Console.WriteLine("二叉树的链表表示:"); + PrintUtil.PrintTree(root); + + // 数组表示下的二叉树类 + ArrayBinaryTree abt = new ArrayBinaryTree(arr); + + // 访问节点 + int i = 1; + int l = abt.left(i); + int r = abt.right(i); + int p = abt.parent(i); + Console.WriteLine("\n当前节点的索引为 " + i + " ,值为 " + abt.val(i)); + Console.WriteLine("其左子节点的索引为 " + l + " ,值为 " + (abt.val(l).HasValue ? abt.val(l) : "null")); + Console.WriteLine("其右子节点的索引为 " + r + " ,值为 " + (abt.val(r).HasValue ? abt.val(r) : "null")); + Console.WriteLine("其父节点的索引为 " + p + " ,值为 " + (abt.val(p).HasValue ? abt.val(p) : "null")); + + // 遍历树 + List res = abt.levelOrder(); + Console.WriteLine("\n层序遍历为:" + res.PrintList()); + res = abt.preOrder(); + Console.WriteLine("前序遍历为:" + res.PrintList()); + res = abt.inOrder(); + Console.WriteLine("中序遍历为:" + res.PrintList()); + res = abt.postOrder(); + Console.WriteLine("后序遍历为:" + res.PrintList()); + } +} \ No newline at end of file diff --git a/codes/csharp/utils/PrintUtil.cs b/codes/csharp/utils/PrintUtil.cs index dd9b67a20..cad29f521 100644 --- a/codes/csharp/utils/PrintUtil.cs +++ b/codes/csharp/utils/PrintUtil.cs @@ -16,12 +16,16 @@ public class Trunk { } }; -public class PrintUtil { +public static class PrintUtil { /* Print a list */ public static void PrintList(IList list) { Console.WriteLine("[" + string.Join(", ", list) + "]"); } + public static string PrintList(this IEnumerable list) { + return $"[ {string.Join(", ", list.Select(x => x?.ToString() ?? "null"))} ]"; + } + /* Print a matrix (Array) */ public static void PrintMatrix(T[][] matrix) { Console.WriteLine("["); @@ -131,4 +135,4 @@ public class PrintUtil { TreeNode tree = TreeNode.ListToTree(list.Cast().ToList()); PrintTree(tree); } -} +} \ No newline at end of file diff --git a/codes/csharp/utils/TreeNode.cs b/codes/csharp/utils/TreeNode.cs index efebc32a7..d9752e22e 100644 --- a/codes/csharp/utils/TreeNode.cs +++ b/codes/csharp/utils/TreeNode.cs @@ -13,50 +13,59 @@ public class TreeNode { public TreeNode? left; // 左子节点引用 public TreeNode? right; // 右子节点引用 + /* 构造方法 */ public TreeNode(int x) { val = x; } - /* Generate a binary tree given an array */ - public static TreeNode? ListToTree(List arr) { - if (arr.Count == 0 || arr[0] == null) - return null; + // 序列化编码规则请参考: + // https://www.hello-algo.com/chapter_tree/array_representation_of_tree/ + // 二叉树的数组表示: + // [1, 2, 3, 4, None, 6, 7, 8, 9, None, None, 12, None, None, 15] + // 二叉树的链表表示: + // /——— 15 + // /——— 7 + // /——— 3 + // | \——— 6 + // | \——— 12 + // ——— 1 + // \——— 2 + // | /——— 9 + // \——— 4 + // \——— 8 - TreeNode root = new TreeNode(arr[0]!.Value); - Queue queue = new Queue(); - queue.Enqueue(root); - int i = 0; - while (queue.Count != 0) { - TreeNode node = queue.Dequeue(); - if (++i >= arr.Count) break; - if (arr[i] != null) { - node.left = new TreeNode((int)arr[i]); - queue.Enqueue(node.left); - } - if (++i >= arr.Count) break; - if (arr[i] != null) { - node.right = new TreeNode((int)arr[i]); - queue.Enqueue(node.right); - } + /* 将列表反序列化为二叉树:递归 */ + private static TreeNode? ListToTreeDFS(List arr, int i) { + if (i < 0|| i >= arr.Count || !arr[i].HasValue) { + return null; } + TreeNode root = new TreeNode(arr[i].Value); + root.left = ListToTreeDFS(arr, 2 * i + 1); + root.right = ListToTreeDFS(arr, 2 * i + 2); return root; } - /* Serialize a binary tree to a list */ - public static List TreeToList(TreeNode root) { - List list = new(); - if (root == null) return list; - Queue queue = new(); - while (queue.Count != 0) { - TreeNode? node = queue.Dequeue(); - if (node != null) { - list.Add(node.val); - queue.Enqueue(node.left); - queue.Enqueue(node.right); - } else { - list.Add(null); - } + /* 将列表反序列化为二叉树 */ + public static TreeNode? ListToTree(List arr) { + return ListToTreeDFS(arr, 0); + } + + /* 将二叉树序列化为列表:递归 */ + private static void TreeToListDFS(TreeNode? root, int i, List res) { + if (root == null) + return; + while (i >= res.Count) { + res.Add(null); } - return list; + res[i] = root.val; + TreeToListDFS(root.left, 2 * i + 1, res); + TreeToListDFS(root.right, 2 * i + 2, res); + } + + /* 将二叉树序列化为列表 */ + public static List treeToList(TreeNode root) { + List res = new List(); + TreeToListDFS(root, 0, res); + return res; } }