Fine tune

This commit is contained in:
Yudong Jin 2022-12-24 16:15:41 +08:00
parent 3339a648d0
commit b1645c7d7e
24 changed files with 235 additions and 233 deletions

View file

@ -1,4 +1,4 @@
// File: Array.cs // File: array.cs
// Created Time: 2022-12-14 // Created Time: 2022-12-14
// Author: mingXta (1195669834@qq.com) // Author: mingXta (1195669834@qq.com)

View file

@ -1,4 +1,4 @@
// File: LinkedList.cs // File: linked_list.cs
// Created Time: 2022-12-16 // Created Time: 2022-12-16
// Author: mingXta (1195669834@qq.com) // Author: mingXta (1195669834@qq.com)
@ -7,14 +7,14 @@ using NUnit.Framework;
namespace hello_algo.chapter_array_and_linkedlist namespace hello_algo.chapter_array_and_linkedlist
{ {
public class LinkedList public class linked_list
{ {
/// <summary> /// <summary>
/// 在链表的结点 n0 之后插入结点 P /// 在链表的结点 n0 之后插入结点 P
/// </summary> /// </summary>
public static void Insert(ListNode n0, ListNode P) public static void Insert(ListNode n0, ListNode P)
{ {
ListNode n1 = n0.next; ListNode? n1 = n0.next;
n0.next = P; n0.next = P;
P.next = n1; P.next = n1;
} }
@ -28,7 +28,7 @@ namespace hello_algo.chapter_array_and_linkedlist
return; return;
// n0 -> P -> n1 // n0 -> P -> n1
ListNode P = n0.next; ListNode P = n0.next;
ListNode n1 = P.next; ListNode? n1 = P.next;
n0.next = n1; n0.next = n1;
} }

View file

@ -34,7 +34,7 @@ namespace hello_algo.chapter_array_and_linkedlist
} }
/* 访问元素 */ /* 访问元素 */
public int get(int index) public int Get(int index)
{ {
// 索引如果越界则抛出异常,下同 // 索引如果越界则抛出异常,下同
if (index >= size) if (index >= size)
@ -43,7 +43,7 @@ namespace hello_algo.chapter_array_and_linkedlist
} }
/* 更新元素 */ /* 更新元素 */
public void set(int index, int num) public void Set(int index, int num)
{ {
if (index >= size) if (index >= size)
throw new IndexOutOfRangeException("索引越界"); throw new IndexOutOfRangeException("索引越界");
@ -51,24 +51,24 @@ namespace hello_algo.chapter_array_and_linkedlist
} }
/* 尾部添加元素 */ /* 尾部添加元素 */
public void add(int num) public void Add(int num)
{ {
// 元素数量超出容量时,触发扩容机制 // 元素数量超出容量时,触发扩容机制
if (size == Capacity()) if (size == Capacity())
extendCapacity(); ExtendCapacity();
nums[size] = num; nums[size] = num;
// 更新元素数量 // 更新元素数量
size++; size++;
} }
/* 中间插入元素 */ /* 中间插入元素 */
public void insert(int index, int num) public void Insert(int index, int num)
{ {
if (index >= size) if (index >= size)
throw new IndexOutOfRangeException("索引越界"); throw new IndexOutOfRangeException("索引越界");
// 元素数量超出容量时,触发扩容机制 // 元素数量超出容量时,触发扩容机制
if (size == Capacity()) if (size == Capacity())
extendCapacity(); ExtendCapacity();
// 将索引 index 以及之后的元素都向后移动一位 // 将索引 index 以及之后的元素都向后移动一位
for (int j = size - 1; j >= index; j--) for (int j = size - 1; j >= index; j--)
{ {
@ -80,7 +80,7 @@ namespace hello_algo.chapter_array_and_linkedlist
} }
/* 删除元素 */ /* 删除元素 */
public int remove(int index) public int Remove(int index)
{ {
if (index >= size) if (index >= size)
throw new IndexOutOfRangeException("索引越界"); throw new IndexOutOfRangeException("索引越界");
@ -97,7 +97,7 @@ namespace hello_algo.chapter_array_and_linkedlist
} }
/* 列表扩容 */ /* 列表扩容 */
public void extendCapacity() public void ExtendCapacity()
{ {
// 新建一个长度为 size 的数组,并将原数组拷贝到新数组 // 新建一个长度为 size 的数组,并将原数组拷贝到新数组
System.Array.Resize(ref nums, Capacity() * extendRatio); System.Array.Resize(ref nums, Capacity() * extendRatio);
@ -106,14 +106,14 @@ namespace hello_algo.chapter_array_and_linkedlist
} }
/* 将列表转换为数组 */ /* 将列表转换为数组 */
public int[] toArray() public int[] ToArray()
{ {
int size = Size(); int size = Size();
// 仅转换有效长度范围内的列表元素 // 仅转换有效长度范围内的列表元素
int[] nums = new int[size]; int[] nums = new int[size];
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)
{ {
nums[i] = get(i); nums[i] = Get(i);
} }
return nums; return nums;
} }
@ -127,37 +127,37 @@ namespace hello_algo.chapter_array_and_linkedlist
/* 初始化列表 */ /* 初始化列表 */
MyList list = new MyList(); MyList list = new MyList();
/* 尾部添加元素 */ /* 尾部添加元素 */
list.add(1); list.Add(1);
list.add(3); list.Add(3);
list.add(2); list.Add(2);
list.add(5); list.Add(5);
list.add(4); list.Add(4);
Console.WriteLine("列表 list = " + string.Join(",", list.toArray()) + Console.WriteLine("列表 list = " + string.Join(",", list.ToArray()) +
" ,容量 = " + list.Capacity() + " ,长度 = " + list.Size()); " ,容量 = " + list.Capacity() + " ,长度 = " + list.Size());
/* 中间插入元素 */ /* 中间插入元素 */
list.insert(3, 6); list.Insert(3, 6);
Console.WriteLine("在索引 3 处插入数字 6 ,得到 list = " + string.Join(",", list.toArray())); Console.WriteLine("在索引 3 处插入数字 6 ,得到 list = " + string.Join(",", list.ToArray()));
/* 删除元素 */ /* 删除元素 */
list.remove(3); list.Remove(3);
Console.WriteLine("删除索引 3 处的元素,得到 list = " + string.Join(",", list.toArray())); Console.WriteLine("删除索引 3 处的元素,得到 list = " + string.Join(",", list.ToArray()));
/* 访问元素 */ /* 访问元素 */
int num = list.get(1); int num = list.Get(1);
Console.WriteLine("访问索引 1 处的元素,得到 num = " + num); Console.WriteLine("访问索引 1 处的元素,得到 num = " + num);
/* 更新元素 */ /* 更新元素 */
list.set(1, 0); list.Set(1, 0);
Console.WriteLine("将索引 1 处的元素更新为 0 ,得到 list = " + string.Join(",", list.toArray())); Console.WriteLine("将索引 1 处的元素更新为 0 ,得到 list = " + string.Join(",", list.ToArray()));
/* 测试扩容机制 */ /* 测试扩容机制 */
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
// 在 i = 5 时,列表长度将超出列表容量,此时触发扩容机制 // 在 i = 5 时,列表长度将超出列表容量,此时触发扩容机制
list.add(i); list.Add(i);
} }
Console.WriteLine("扩容后的列表 list = " + string.Join(",", list.toArray()) + Console.WriteLine("扩容后的列表 list = " + string.Join(",", list.ToArray()) +
" ,容量 = " + list.Capacity() + " ,长度 = " + list.Size()); " ,容量 = " + list.Capacity() + " ,长度 = " + list.Size());
} }
} }

View file

@ -116,7 +116,7 @@ namespace hello_algo.chapter_computational_complexity
quadraticRecur(n); quadraticRecur(n);
// 指数阶 // 指数阶
TreeNode? root = buildTree(n); TreeNode? root = buildTree(n);
PrintUtil.printTree(root); PrintUtil.PrintTree(root);
} }
} }
} }

View file

@ -4,6 +4,8 @@
* Author: haptear (haptear@hotmail.com) * Author: haptear (haptear@hotmail.com)
*/ */
using NUnit.Framework;
namespace hello_algo.chapter_computational_complexity namespace hello_algo.chapter_computational_complexity
{ {
public class worst_best_time_complexity public class worst_best_time_complexity
@ -43,7 +45,8 @@ namespace hello_algo.chapter_computational_complexity
/* Driver Code */ /* Driver Code */
public static void main(String[] args) [Test]
public void Test()
{ {
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {

View file

@ -45,7 +45,7 @@ namespace hello_algo.chapter_searching
Console.WriteLine("目标元素 3 的索引 = " + index); Console.WriteLine("目标元素 3 的索引 = " + index);
/* 哈希查找(链表) */ /* 哈希查找(链表) */
ListNode head = ListNode.ArrToLinkedList(nums); ListNode? head = ListNode.ArrToLinkedList(nums);
// 初始化哈希表 // 初始化哈希表
Dictionary<int, ListNode> map1 = new(); Dictionary<int, ListNode> map1 = new();
while (head != null) while (head != null)

View file

@ -37,7 +37,7 @@ namespace hello_algo.chapter_sorting
for (int i = nums.Length - 1; i > 0; i--) for (int i = nums.Length - 1; i > 0; i--)
{ {
bool flag = false; // 初始化标志位 bool flag = false; // 初始化标志位
// 内循环:冒泡操作 // 内循环:冒泡操作
for (int j = 0; j < i; j++) for (int j = 0; j < i; j++)
{ {
if (nums[j] > nums[j + 1]) if (nums[j] > nums[j + 1])

View file

@ -20,7 +20,7 @@ namespace hello_algo.chapter_sorting
// 内循环:将 base 插入到左边的正确位置 // 内循环:将 base 插入到左边的正确位置
while (j >= 0 && nums[j] > bas) while (j >= 0 && nums[j] > bas)
{ {
nums[j + 1] = nums[j]; // 1. 将 nums[j] 向右移动一位 nums[j + 1] = nums[j]; // 1. 将 nums[j] 向右移动一位
j--; j--;
} }
nums[j + 1] = bas; // 2. 将 base 赋值到正确位置 nums[j + 1] = bas; // 2. 将 base 赋值到正确位置

View file

@ -18,7 +18,7 @@ namespace hello_algo.chapter_sorting
static void merge(int[] nums, int left, int mid, int right) static void merge(int[] nums, int left, int mid, int right)
{ {
// 初始化辅助数组 // 初始化辅助数组
int[] tmp = nums[left..(right + 1)];//Array.CopyOfRange(nums, left, right + 1); int[] tmp = nums[left..(right + 1)];
// 左子数组的起始索引和结束索引 // 左子数组的起始索引和结束索引
int leftStart = left - left, leftEnd = mid - left; int leftStart = left - left, leftEnd = mid - left;
// 右子数组的起始索引和结束索引 // 右子数组的起始索引和结束索引

View file

@ -22,6 +22,7 @@ namespace hello_algo.chapter_stack_and_queue
stack.Push(2); stack.Push(2);
stack.Push(5); stack.Push(5);
stack.Push(4); stack.Push(4);
// 请注意stack.ToArray() 得到的是倒序序列,即索引 0 为栈顶
Console.WriteLine("栈 stack = " + string.Join(",", stack.ToArray())); Console.WriteLine("栈 stack = " + string.Join(",", stack.ToArray()));
/* 访问栈顶元素 */ /* 访问栈顶元素 */

View file

@ -148,7 +148,7 @@ namespace hello_algo.chapter_tree
} }
/* 递归删除结点(辅助函数) */ /* 递归删除结点(辅助函数) */
private TreeNode? removeHelper(TreeNode? node, int? val) private TreeNode? removeHelper(TreeNode? node, int val)
{ {
if (node == null) return null; if (node == null) return null;
/* 1. 查找结点,并删除之 */ /* 1. 查找结点,并删除之 */
@ -172,8 +172,8 @@ namespace hello_algo.chapter_tree
{ {
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 // 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点
TreeNode? temp = minNode(node.right); TreeNode? temp = minNode(node.right);
node.right = removeHelper(node.right, temp?.val); node.right = removeHelper(node.right, temp.val);
node.val = temp?.val; node.val = temp.val;
} }
} }
updateHeight(node); // 更新结点高度 updateHeight(node); // 更新结点高度
@ -223,14 +223,14 @@ namespace hello_algo.chapter_tree
{ {
tree.insert(val); tree.insert(val);
Console.WriteLine("\n插入结点 " + val + " 后AVL 树为"); Console.WriteLine("\n插入结点 " + val + " 后AVL 树为");
PrintUtil.printTree(tree.root); PrintUtil.PrintTree(tree.root);
} }
static void testRemove(AVLTree tree, int val) static void testRemove(AVLTree tree, int val)
{ {
tree.remove(val); tree.remove(val);
Console.WriteLine("\n删除结点 " + val + " 后AVL 树为"); Console.WriteLine("\n删除结点 " + val + " 后AVL 树为");
PrintUtil.printTree(tree.root); PrintUtil.PrintTree(tree.root);
} }
[Test] [Test]

View file

@ -9,16 +9,38 @@ using NUnit.Framework;
namespace hello_algo.chapter_tree namespace hello_algo.chapter_tree
{ {
internal class binary_search_tree class BinarySearchTree
{ {
TreeNode? root; TreeNode? root;
public BinarySearchTree(int[] nums) {
Array.Sort(nums); // 排序数组
root = buildTree(nums, 0, nums.Length - 1); // 构建二叉搜索树
}
/* 获取二叉树根结点 */
public TreeNode? getRoot() {
return root;
}
/* 构建二叉搜索树 */
public TreeNode? buildTree(int[] nums, int i, int j) {
if (i > j) return null;
// 将数组中间结点作为根结点
int mid = (i + j) / 2;
TreeNode root = new TreeNode(nums[mid]);
// 递归建立左子树和右子树
root.left = buildTree(nums, i, mid - 1);
root.right = buildTree(nums, mid + 1, j);
return root;
}
/// <summary> /// <summary>
/// 查找结点 /// 查找结点
/// </summary> /// </summary>
/// <param name="num"></param> /// <param name="num"></param>
/// <returns></returns> /// <returns></returns>
TreeNode? search(int num) public TreeNode? search(int num)
{ {
TreeNode? cur = root; TreeNode? cur = root;
// 循环查找,越过叶结点后跳出 // 循环查找,越过叶结点后跳出
@ -36,7 +58,7 @@ namespace hello_algo.chapter_tree
} }
/* 插入结点 */ /* 插入结点 */
TreeNode? insert(int num) public TreeNode? insert(int num)
{ {
// 若树为空,直接提前返回 // 若树为空,直接提前返回
if (root == null) return null; if (root == null) return null;
@ -65,7 +87,7 @@ namespace hello_algo.chapter_tree
/* 删除结点 */ /* 删除结点 */
TreeNode? remove(int? num) public TreeNode? remove(int num)
{ {
// 若树为空,直接提前返回 // 若树为空,直接提前返回
if (root == null) return null; if (root == null) return null;
@ -106,7 +128,7 @@ namespace hello_algo.chapter_tree
TreeNode? nex = min(cur.right); TreeNode? nex = min(cur.right);
if (nex != null) if (nex != null)
{ {
int? tmp = nex.val; int tmp = nex.val;
// 递归删除结点 nex // 递归删除结点 nex
remove(nex.val); remove(nex.val);
// 将 nex 的值复制给 cur // 将 nex 的值复制给 cur
@ -117,7 +139,7 @@ namespace hello_algo.chapter_tree
} }
/* 获取最小结点 */ /* 获取最小结点 */
TreeNode? min(TreeNode? root) private TreeNode? min(TreeNode? root)
{ {
if (root == null) return root; if (root == null) return root;
// 循环访问左子结点,直到叶结点时为最小结点,跳出 // 循环访问左子结点,直到叶结点时为最小结点,跳出
@ -127,55 +149,38 @@ namespace hello_algo.chapter_tree
} }
return root; return root;
} }
}
public class binary_search_tree
{
[Test] [Test]
public void Test() public void Test()
{ {
// 初始化结点 /* 初始化二叉搜索树 */
TreeNode n1 = new TreeNode(1); int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
TreeNode n2 = new TreeNode(2); BinarySearchTree bst = new BinarySearchTree(nums);
TreeNode n3 = new TreeNode(3); Console.WriteLine("\n初始化的二叉树为\n");
TreeNode n4 = new TreeNode(4); PrintUtil.PrintTree(bst.getRoot());
TreeNode n5 = new TreeNode(5);
TreeNode n6 = new TreeNode(6);
TreeNode n7 = new TreeNode(7);
TreeNode n8 = new TreeNode(8);
TreeNode n9 = new TreeNode(9);
TreeNode n10 = new TreeNode(10);
TreeNode n11 = new TreeNode(11);
TreeNode n12 = new TreeNode(12);
TreeNode n13 = new TreeNode(13);
TreeNode n14 = new TreeNode(14);
TreeNode n15 = new TreeNode(15);
root = n8;
root.left = n4;
root.right = n12;
n4.left = n2;
n4.right = n6;
n12.left = n10;
n12.right = n14;
n2.left = n1;
n2.right = n3;
n6.left = n5;
n6.right = n7;
n10.left = n9;
n10.right = n11;
n14.left = n13;
n14.right = n15;
var cur = search(7); /* 查找结点 */
Console.WriteLine("查找结点 结果 = " + cur?.val); TreeNode? node = bst.search(5);
Console.WriteLine("\n查找到的结点对象为 " + node + ",结点值 = " + node.val);
var node = insert(16); /* 插入结点 */
Console.WriteLine("插入结点 结果 = " + node?.val); node = bst.insert(16);
Console.WriteLine("\n插入结点 16 后,二叉树为\n");
node = remove(1); PrintUtil.PrintTree(bst.getRoot());
Console.WriteLine("删除结点 结果 = " + node?.val);
node = remove(2);
Console.WriteLine("删除结点 结果 = " + node?.val);
node = remove(4);
Console.WriteLine("删除结点 结果 = " + node?.val);
/* 删除结点 */
bst.remove(1);
Console.WriteLine("\n删除结点 1 后,二叉树为\n");
PrintUtil.PrintTree(bst.getRoot());
bst.remove(2);
Console.WriteLine("\n删除结点 2 后,二叉树为\n");
PrintUtil.PrintTree(bst.getRoot());
bst.remove(4);
Console.WriteLine("\n删除结点 4 后,二叉树为\n");
PrintUtil.PrintTree(bst.getRoot());
} }
} }
} }

View file

@ -28,7 +28,7 @@ namespace hello_algo.chapter_tree
n2.left = n4; n2.left = n4;
n2.right = n5; n2.right = n5;
Console.WriteLine("\n初始化二叉树\n"); Console.WriteLine("\n初始化二叉树\n");
PrintUtil.printTree(n1); PrintUtil.PrintTree(n1);
/* 插入与删除结点 */ /* 插入与删除结点 */
TreeNode P = new TreeNode(0); TreeNode P = new TreeNode(0);
@ -36,11 +36,11 @@ namespace hello_algo.chapter_tree
n1.left = P; n1.left = P;
P.left = n2; P.left = n2;
Console.WriteLine("\n插入结点 P 后\n"); Console.WriteLine("\n插入结点 P 后\n");
PrintUtil.printTree(n1); PrintUtil.PrintTree(n1);
// 删除结点 P // 删除结点 P
n1.left = n2; n1.left = n2;
Console.WriteLine("\n删除结点 P 后\n"); Console.WriteLine("\n删除结点 P 后\n");
PrintUtil.printTree(n1); PrintUtil.PrintTree(n1);
} }
} }
} }

View file

@ -17,17 +17,17 @@ namespace hello_algo.chapter_tree
/// </summary> /// </summary>
/// <param name="root"></param> /// <param name="root"></param>
/// <returns></returns> /// <returns></returns>
public List<int?> hierOrder(TreeNode root) public List<int> hierOrder(TreeNode root)
{ {
// 初始化队列,加入根结点 // 初始化队列,加入根结点
Queue<TreeNode> queue = new(); Queue<TreeNode> queue = new();
queue.Enqueue(root); queue.Enqueue(root);
// 初始化一个列表,用于保存遍历序列 // 初始化一个列表,用于保存遍历序列
List<int?> list = new(); List<int> list = new();
while (queue.Count != 0) while (queue.Count != 0)
{ {
TreeNode node = queue.Dequeue(); // 队列出队 TreeNode node = queue.Dequeue(); // 队列出队
list.Add(node.val); // 保存结点值 list.Add(node.val); // 保存结点值
if (node.left != null) if (node.left != null)
queue.Enqueue(node.left); // 左子结点入队 queue.Enqueue(node.left); // 左子结点入队
if (node.right != null) if (node.right != null)
@ -36,88 +36,18 @@ namespace hello_algo.chapter_tree
return list; return list;
} }
List<int?> list = new();
/// <summary>
/// 前序遍历
/// </summary>
/// <param name="root"></param>
void preOrder(TreeNode? root)
{
if (root == null) return;
// 访问优先级:根结点 -> 左子树 -> 右子树
list.Add(root.val);
preOrder(root.left);
preOrder(root.right);
}
/// <summary>
/// 中序遍历
/// </summary>
/// <param name="root"></param>
void inOrder(TreeNode? root)
{
if (root == null) return;
// 访问优先级:左子树 -> 根结点 -> 右子树
inOrder(root.left);
list.Add(root.val);
inOrder(root.right);
}
/// <summary>
/// 后序遍历
/// </summary>
/// <param name="root"></param>
void postOrder(TreeNode? root)
{
if (root == null) return;
// 访问优先级:左子树 -> 右子树 -> 根结点
postOrder(root.left);
postOrder(root.right);
list.Add(root.val);
}
/// <summary>
/// 辅助函数,数组转字符串
/// </summary>
public static string ToString(int?[] nums)
{
return string.Join(",", nums);
}
[Test] [Test]
public void Test() public void Test()
{ {
// 初始化结点 /* 初始化二叉树 */
TreeNode root = new TreeNode(1); // 这里借助了一个从数组直接生成二叉树的函数
TreeNode n2 = new TreeNode(2); TreeNode? root = TreeNode.ArrToTree(new int?[] {
TreeNode n3 = new TreeNode(3); 1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null});
TreeNode n4 = new TreeNode(4); Console.WriteLine("\n初始化二叉树\n");
TreeNode n5 = new TreeNode(5); PrintUtil.PrintTree(root);
TreeNode n6 = new TreeNode(6);
TreeNode n7 = new TreeNode(7);
// 构建引用指向(即指针)
root.left = n2;
root.right = n3;
n2.left = n4;
n2.right = n5;
n3.left = n6;
n3.right = n7;
list = hierOrder(root); List<int> list = hierOrder(root);
Console.WriteLine("层序遍历 结果 = " + ToString(list.ToArray())); Console.WriteLine("\n层序遍历的结点打印序列 = " + string.Join(",", list.ToArray()));
list = new List<int?>();
preOrder(root);
Console.WriteLine("前序遍历 结果 = " + ToString(list.ToArray()));
list = new List<int?>();
inOrder(root);
Console.WriteLine("中序遍历 结果 = " + ToString(list.ToArray()));
list = new List<int?>();
postOrder(root);
Console.WriteLine("后序遍历 结果 = " + ToString(list.ToArray()));
} }
} }
} }

View file

@ -0,0 +1,78 @@
/**
* File: binary_tree_bfs.cs
* Created Time: 2022-12-23
* Author: haptear (haptear@hotmail.com)
*/
using hello_algo.include;
using NUnit.Framework;
namespace hello_algo.chapter_tree
{
public class binary_tree_dfs
{
List<int> list = new();
/// <summary>
/// 前序遍历
/// </summary>
/// <param name="root"></param>
void preOrder(TreeNode? root)
{
if (root == null) return;
// 访问优先级:根结点 -> 左子树 -> 右子树
list.Add(root.val);
preOrder(root.left);
preOrder(root.right);
}
/// <summary>
/// 中序遍历
/// </summary>
/// <param name="root"></param>
void inOrder(TreeNode? root)
{
if (root == null) return;
// 访问优先级:左子树 -> 根结点 -> 右子树
inOrder(root.left);
list.Add(root.val);
inOrder(root.right);
}
/// <summary>
/// 后序遍历
/// </summary>
/// <param name="root"></param>
void postOrder(TreeNode? root)
{
if (root == null) return;
// 访问优先级:左子树 -> 右子树 -> 根结点
postOrder(root.left);
postOrder(root.right);
list.Add(root.val);
}
[Test]
public void Test()
{
/* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数
TreeNode? root = TreeNode.ArrToTree(new int?[] {
1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null});
Console.WriteLine("\n初始化二叉树\n");
PrintUtil.PrintTree(root);
list.Clear();
preOrder(root);
Console.WriteLine("\n前序遍历的结点打印序列 = " + string.Join(",", list.ToArray()));
list.Clear();
inOrder(root);
Console.WriteLine("\n中序遍历的结点打印序列 = " + string.Join(",", list.ToArray()));
list.Clear();
postOrder(root);
Console.WriteLine("\n后序遍历的结点打印序列 = " + string.Join(",", list.ToArray()));
}
}
}

View file

@ -24,7 +24,7 @@ namespace hello_algo.include
* Print a linked list * Print a linked list
* @param head * @param head
*/ */
public static void printLinkedList(ListNode head) public static void PrintLinkedList(ListNode head)
{ {
List<String> list = new(); List<String> list = new();
while (head != null) while (head != null)
@ -41,9 +41,9 @@ namespace hello_algo.include
* https://www.techiedelight.com/c-program-print-binary-tree/ * https://www.techiedelight.com/c-program-print-binary-tree/
* @param root * @param root
*/ */
public static void printTree(TreeNode? root) public static void PrintTree(TreeNode? root)
{ {
printTree(root, null, false); PrintTree(root, null, false);
} }
/** /**
@ -52,7 +52,7 @@ namespace hello_algo.include
* @param prev * @param prev
* @param isLeft * @param isLeft
*/ */
public static void printTree(TreeNode? root, Trunk? prev, bool isLeft) public static void PrintTree(TreeNode? root, Trunk? prev, bool isLeft)
{ {
if (root == null) if (root == null)
{ {
@ -62,7 +62,7 @@ namespace hello_algo.include
String prev_str = " "; String prev_str = " ";
Trunk trunk = new Trunk(prev, prev_str); Trunk trunk = new Trunk(prev, prev_str);
printTree(root.right, trunk, true); PrintTree(root.right, trunk, true);
if (prev == null) if (prev == null)
{ {
@ -80,7 +80,7 @@ namespace hello_algo.include
} }
showTrunks(trunk); showTrunks(trunk);
Console.Write(" " + root.val); Console.WriteLine(" " + root.val);
if (prev != null) if (prev != null)
{ {
@ -88,7 +88,7 @@ namespace hello_algo.include
} }
trunk.str = " |"; trunk.str = " |";
printTree(root.left, trunk, false); PrintTree(root.left, trunk, false);
} }
/** /**

View file

@ -8,12 +8,12 @@ namespace hello_algo.include
{ {
public class TreeNode public class TreeNode
{ {
public int? val; // 结点值 public int val; // 结点值
public int height; // 结点高度 public int height; // 结点高度
public TreeNode? left; // 左子结点引用 public TreeNode? left; // 左子结点引用
public TreeNode? right; // 右子结点引用 public TreeNode? right; // 右子结点引用
public TreeNode(int? x) public TreeNode(int x)
{ {
val = x; val = x;
} }
@ -23,12 +23,12 @@ namespace hello_algo.include
* @param arr * @param arr
* @return * @return
*/ */
public static TreeNode? arrToTree(int?[] arr) public static TreeNode? ArrToTree(int?[] arr)
{ {
if (arr.Length == 0) if (arr.Length == 0 || arr[0] == null)
return null; return null;
TreeNode root = new TreeNode(arr[0]); TreeNode root = new TreeNode((int) arr[0]);
Queue<TreeNode> queue = new Queue<TreeNode>(); Queue<TreeNode> queue = new Queue<TreeNode>();
queue.Enqueue(root); queue.Enqueue(root);
int i = 1; int i = 1;
@ -37,13 +37,13 @@ namespace hello_algo.include
TreeNode node = queue.Dequeue(); TreeNode node = queue.Dequeue();
if (arr[i] != null) if (arr[i] != null)
{ {
node.left = new TreeNode(arr[i]); node.left = new TreeNode((int) arr[i]);
queue.Enqueue(node.left); queue.Enqueue(node.left);
} }
i++; i++;
if (arr[i] != null) if (arr[i] != null)
{ {
node.right = new TreeNode(arr[i]); node.right = new TreeNode((int) arr[i]);
queue.Enqueue(node.right); queue.Enqueue(node.right);
} }
i++; i++;
@ -56,7 +56,7 @@ namespace hello_algo.include
* @param root * @param root
* @return * @return
*/ */
public static List<int?> treeToList(TreeNode root) public static List<int?> TreeToList(TreeNode root)
{ {
List<int?> list = new(); List<int?> list = new();
if (root == null) return list; if (root == null) return list;
@ -84,14 +84,14 @@ namespace hello_algo.include
* @param val * @param val
* @return * @return
*/ */
public static TreeNode? getTreeNode(TreeNode? root, int val) public static TreeNode? GetTreeNode(TreeNode? root, int val)
{ {
if (root == null) if (root == null)
return null; return null;
if (root.val == val) if (root.val == val)
return root; return root;
TreeNode? left = getTreeNode(root.left, val); TreeNode? left = GetTreeNode(root.left, val);
TreeNode? right = getTreeNode(root.right, val); TreeNode? right = GetTreeNode(root.right, val);
return left != null ? left : right; return left != null ? left : right;
} }
} }

View file

@ -314,7 +314,7 @@ comments: true
list.Insert(3, 6); list.Insert(3, 6);
/* 删除元素 */ /* 删除元素 */
list.Remove(3); list.RemoveAt(3);
``` ```
**遍历列表。** 与数组一样,列表可以使用索引遍历,也可以使用 `for-each` 直接遍历。 **遍历列表。** 与数组一样,列表可以使用索引遍历,也可以使用 `for-each` 直接遍历。
@ -376,9 +376,9 @@ comments: true
/* 直接遍历列表元素 */ /* 直接遍历列表元素 */
count = 0 count = 0
for range list { for range list {
count++ count++
} }
``` ```
=== "JavaScript" === "JavaScript"
@ -1148,7 +1148,7 @@ comments: true
} }
/* 访问元素 */ /* 访问元素 */
public int get(int index) public int Get(int index)
{ {
// 索引如果越界则抛出异常,下同 // 索引如果越界则抛出异常,下同
if (index >= size) if (index >= size)
@ -1157,7 +1157,7 @@ comments: true
} }
/* 更新元素 */ /* 更新元素 */
public void set(int index, int num) public void Set(int index, int num)
{ {
if (index >= size) if (index >= size)
throw new IndexOutOfRangeException("索引越界"); throw new IndexOutOfRangeException("索引越界");
@ -1165,24 +1165,24 @@ comments: true
} }
/* 尾部添加元素 */ /* 尾部添加元素 */
public void add(int num) public void Add(int num)
{ {
// 元素数量超出容量时,触发扩容机制 // 元素数量超出容量时,触发扩容机制
if (size == Capacity()) if (size == Capacity())
extendCapacity(); ExtendCapacity();
nums[size] = num; nums[size] = num;
// 更新元素数量 // 更新元素数量
size++; size++;
} }
/* 中间插入元素 */ /* 中间插入元素 */
public void insert(int index, int num) public void Insert(int index, int num)
{ {
if (index >= size) if (index >= size)
throw new IndexOutOfRangeException("索引越界"); throw new IndexOutOfRangeException("索引越界");
// 元素数量超出容量时,触发扩容机制 // 元素数量超出容量时,触发扩容机制
if (size == Capacity()) if (size == Capacity())
extendCapacity(); ExtendCapacity();
// 将索引 index 以及之后的元素都向后移动一位 // 将索引 index 以及之后的元素都向后移动一位
for (int j = size - 1; j >= index; j--) for (int j = size - 1; j >= index; j--)
{ {
@ -1194,7 +1194,7 @@ comments: true
} }
/* 删除元素 */ /* 删除元素 */
public int remove(int index) public int Remove(int index)
{ {
if (index >= size) if (index >= size)
throw new IndexOutOfRangeException("索引越界"); throw new IndexOutOfRangeException("索引越界");
@ -1211,25 +1211,12 @@ comments: true
} }
/* 列表扩容 */ /* 列表扩容 */
public void extendCapacity() public void ExtendCapacity()
{ {
// 新建一个长度为 size 的数组,并将原数组拷贝到新数组 // 新建一个长度为 size 的数组,并将原数组拷贝到新数组
System.Array.Resize(ref nums, Capacity() * extendRatio); System.Array.Resize(ref nums, Capacity() * extendRatio);
// 更新列表容量 // 更新列表容量
capacity = nums.Length; capacity = nums.Length;
} }
/* 将列表转换为数组 */
public int[] toArray()
{
int size = Size();
// 仅转换有效长度范围内的列表元素
int[] nums = new int[size];
for (int i = 0; i < size; i++)
{
nums[i] = get(i);
}
return nums;
}
} }
``` ```

View file

@ -365,7 +365,7 @@ comments: true
for (int i = nums.Length - 1; i > 0; i--) for (int i = nums.Length - 1; i > 0; i--)
{ {
bool flag = false; // 初始化标志位 bool flag = false; // 初始化标志位
// 内循环:冒泡操作 // 内循环:冒泡操作
for (int j = 0; j < i; j++) for (int j = 0; j < i; j++)
{ {
if (nums[j] > nums[j + 1]) if (nums[j] > nums[j + 1])

View file

@ -151,7 +151,7 @@ comments: true
// 内循环:将 base 插入到左边的正确位置 // 内循环:将 base 插入到左边的正确位置
while (j >= 0 && nums[j] > bas) while (j >= 0 && nums[j] > bas)
{ {
nums[j + 1] = nums[j]; // 1. 将 nums[j] 向右移动一位 nums[j + 1] = nums[j]; // 1. 将 nums[j] 向右移动一位
j--; j--;
} }
nums[j + 1] = bas; // 2. 将 base 赋值到正确位置 nums[j + 1] = bas; // 2. 将 base 赋值到正确位置

View file

@ -352,7 +352,7 @@ comments: true
void merge(int[] nums, int left, int mid, int right) void merge(int[] nums, int left, int mid, int right)
{ {
// 初始化辅助数组 // 初始化辅助数组
int[] tmp = nums[left..(right + 1)];//Array.CopyOfRange(nums, left, right + 1); int[] tmp = nums[left..(right + 1)];
// 左子数组的起始索引和结束索引 // 左子数组的起始索引和结束索引
int leftStart = left - left, leftEnd = mid - left; int leftStart = left - left, leftEnd = mid - left;
// 右子数组的起始索引和结束索引 // 右子数组的起始索引和结束索引

View file

@ -660,7 +660,6 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
// 返回子树的根节点 // 返回子树的根节点
return node; return node;
} }
``` ```
### 删除结点 ### 删除结点
@ -765,7 +764,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
} }
/* 递归删除结点(辅助函数) */ /* 递归删除结点(辅助函数) */
private TreeNode? removeHelper(TreeNode? node, int? val) private TreeNode? removeHelper(TreeNode? node, int val)
{ {
if (node == null) return null; if (node == null) return null;
/* 1. 查找结点,并删除之 */ /* 1. 查找结点,并删除之 */
@ -789,8 +788,8 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
{ {
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 // 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点
TreeNode? temp = minNode(node.right); TreeNode? temp = minNode(node.right);
node.right = removeHelper(node.right, temp?.val); node.right = removeHelper(node.right, temp.val);
node.val = temp?.val; node.val = temp.val;
} }
} }
updateHeight(node); // 更新结点高度 updateHeight(node); // 更新结点高度

View file

@ -692,7 +692,7 @@ comments: true
```csharp title="binary_search_tree.cs" ```csharp title="binary_search_tree.cs"
/* 删除结点 */ /* 删除结点 */
TreeNode? remove(int? num) TreeNode? remove(int num)
{ {
// 若树为空,直接提前返回 // 若树为空,直接提前返回
if (root == null) return null; if (root == null) return null;
@ -724,7 +724,6 @@ comments: true
{ {
pre.right = child; pre.right = child;
} }
} }
// 子结点数量 = 2 // 子结点数量 = 2
else else
@ -733,7 +732,7 @@ comments: true
TreeNode? nex = min(cur.right); TreeNode? nex = min(cur.right);
if (nex != null) if (nex != null)
{ {
int? tmp = nex.val; int tmp = nex.val;
// 递归删除结点 nex // 递归删除结点 nex
remove(nex.val); remove(nex.val);
// 将 nex 的值复制给 cur // 将 nex 的值复制给 cur

View file

@ -156,11 +156,11 @@ comments: true
Queue<TreeNode> queue = new(); Queue<TreeNode> queue = new();
queue.Enqueue(root); queue.Enqueue(root);
// 初始化一个列表,用于保存遍历序列 // 初始化一个列表,用于保存遍历序列
List<int?> list = new(); List<int> list = new();
while (queue.Count != 0) while (queue.Count != 0)
{ {
TreeNode node = queue.Dequeue(); // 队列出队 TreeNode node = queue.Dequeue(); // 队列出队
list.Add(node.val); // 保存结点值 list.Add(node.val); // 保存结点值
if (node.left != null) if (node.left != null)
queue.Enqueue(node.left); // 左子结点入队 queue.Enqueue(node.left); // 左子结点入队
if (node.right != null) if (node.right != null)