From 47f017177bad4faa8582c635772f9b64a2861584 Mon Sep 17 00:00:00 2001 From: nuomi1 Date: Mon, 9 Jan 2023 23:02:22 +0800 Subject: [PATCH 1/7] feat: add Swift codes for stack article --- codes/swift/Package.swift | 6 + .../chapter_stack_and_queue/array_stack.swift | 84 +++++++++++++ .../linkedlist_stack.swift | 93 ++++++++++++++ .../swift/chapter_stack_and_queue/stack.swift | 39 ++++++ docs/chapter_stack_and_queue/stack.md | 116 ++++++++++++++++++ 5 files changed, 338 insertions(+) create mode 100644 codes/swift/chapter_stack_and_queue/array_stack.swift create mode 100644 codes/swift/chapter_stack_and_queue/linkedlist_stack.swift create mode 100644 codes/swift/chapter_stack_and_queue/stack.swift diff --git a/codes/swift/Package.swift b/codes/swift/Package.swift index 3a5a18ed3..6d6eaa8a5 100644 --- a/codes/swift/Package.swift +++ b/codes/swift/Package.swift @@ -13,6 +13,9 @@ let package = Package( .executable(name: "linked_list", targets: ["linked_list"]), .executable(name: "list", targets: ["list"]), .executable(name: "my_list", targets: ["my_list"]), + .executable(name: "stack", targets: ["stack"]), + .executable(name: "linkedlist_stack", targets: ["linkedlist_stack"]), + .executable(name: "array_stack", targets: ["array_stack"]), ], targets: [ .target(name: "utils", path: "utils"), @@ -24,5 +27,8 @@ let package = Package( .executableTarget(name: "linked_list", dependencies: ["utils"], path: "chapter_array_and_linkedlist", sources: ["linked_list.swift"]), .executableTarget(name: "list", path: "chapter_array_and_linkedlist", sources: ["list.swift"]), .executableTarget(name: "my_list", path: "chapter_array_and_linkedlist", sources: ["my_list.swift"]), + .executableTarget(name: "stack", path: "chapter_stack_and_queue", sources: ["stack.swift"]), + .executableTarget(name: "linkedlist_stack", dependencies: ["utils"], path: "chapter_stack_and_queue", sources: ["linkedlist_stack.swift"]), + .executableTarget(name: "array_stack", path: "chapter_stack_and_queue", sources: ["array_stack.swift"]), ] ) diff --git a/codes/swift/chapter_stack_and_queue/array_stack.swift b/codes/swift/chapter_stack_and_queue/array_stack.swift new file mode 100644 index 000000000..faeeaa173 --- /dev/null +++ b/codes/swift/chapter_stack_and_queue/array_stack.swift @@ -0,0 +1,84 @@ +/** + * File: array_stack.swift + * Created Time: 2023-01-09 + * Author: nuomi1 (nuomi1@qq.com) + */ + +/* 基于数组实现的栈 */ +class ArrayStack { + private var stack: [Int] + + init() { + // 初始化列表(动态数组) + stack = [] + } + + /* 获取栈的长度 */ + func size() -> Int { + stack.count + } + + /* 判断栈是否为空 */ + func isEmpty() -> Bool { + stack.isEmpty + } + + /* 入栈 */ + func push(num: Int) { + stack.append(num) + } + + /* 出栈 */ + func pop() -> Int { + if stack.isEmpty { + fatalError("栈为空") + } + return stack.removeLast() + } + + /* 访问栈顶元素 */ + func peek() -> Int { + if stack.isEmpty { + fatalError("栈为空") + } + return stack.last! + } + + /* 将 List 转化为 Array 并返回 */ + func toArray() -> [Int] { + stack + } +} + +@main +enum _ArrayStack { + /* Driver Code */ + static func main() { + /* 初始化栈 */ + let stack = ArrayStack() + + /* 元素入栈 */ + stack.push(num: 1) + stack.push(num: 3) + stack.push(num: 2) + stack.push(num: 5) + stack.push(num: 4) + print("栈 stack = \(stack.toArray())") + + /* 访问栈顶元素 */ + let peek = stack.peek() + print("栈顶元素 peek = \(peek)") + + /* 元素出栈 */ + let pop = stack.pop() + print("出栈元素 pop = \(pop),出栈后 stack = \(stack.toArray())") + + /* 获取栈的长度 */ + let size = stack.size() + print("栈的长度 size = \(size)") + + /* 判断是否为空 */ + let isEmpty = stack.isEmpty() + print("栈是否为空 = \(isEmpty)") + } +} diff --git a/codes/swift/chapter_stack_and_queue/linkedlist_stack.swift b/codes/swift/chapter_stack_and_queue/linkedlist_stack.swift new file mode 100644 index 000000000..9d3c98b01 --- /dev/null +++ b/codes/swift/chapter_stack_and_queue/linkedlist_stack.swift @@ -0,0 +1,93 @@ +/** + * File: linkedlist_stack.swift + * Created Time: 2023-01-09 + * Author: nuomi1 (nuomi1@qq.com) + */ + +import utils + +/* 基于链表实现的栈 */ +class LinkedListStack { + private var _peek: ListNode? // 将头结点作为栈顶 + private var _size = 0 // 栈的长度 + + init() {} + + /* 获取栈的长度 */ + func size() -> Int { + _size + } + + /* 判断栈是否为空 */ + func isEmpty() -> Bool { + _size == 0 + } + + /* 入栈 */ + func push(num: Int) { + let node = ListNode(x: num) + node.next = _peek + _peek = node + _size += 1 + } + + /* 出栈 */ + func pop() -> Int { + let num = peek() + _peek = _peek?.next + _size -= 1 + return num + } + + /* 访问栈顶元素 */ + func peek() -> Int { + if _size == 0 { + fatalError("栈为空") + } + return _peek!.val + } + + /* 将 List 转化为 Array 并返回 */ + func toArray() -> [Int] { + var node = _peek + var res = Array(repeating: 0, count: _size) + for i in sequence(first: res.count - 1, next: { $0 >= 0 + 1 ? $0 - 1 : nil }) { + res[i] = node!.val + node = node?.next + } + return res + } +} + +@main +enum _LinkedListStack { + /* Driver Code */ + static func main() { + /* 初始化栈 */ + let stack = LinkedListStack() + + /* 元素入栈 */ + stack.push(num: 1) + stack.push(num: 3) + stack.push(num: 2) + stack.push(num: 5) + stack.push(num: 4) + print("栈 stack = \(stack.toArray())") + + /* 访问栈顶元素 */ + let peek = stack.peek() + print("栈顶元素 peek = \(peek)") + + /* 元素出栈 */ + let pop = stack.pop() + print("出栈元素 pop = \(pop),出栈后 stack = \(stack.toArray())") + + /* 获取栈的长度 */ + let size = stack.size() + print("栈的长度 size = \(size)") + + /* 判断是否为空 */ + let isEmpty = stack.isEmpty() + print("栈是否为空 = \(isEmpty)") + } +} diff --git a/codes/swift/chapter_stack_and_queue/stack.swift b/codes/swift/chapter_stack_and_queue/stack.swift new file mode 100644 index 000000000..c6b8bc184 --- /dev/null +++ b/codes/swift/chapter_stack_and_queue/stack.swift @@ -0,0 +1,39 @@ +/** + * File: stack.swift + * Created Time: 2023-01-09 + * Author: nuomi1 (nuomi1@qq.com) + */ + +@main +enum Stack { + /* Driver Code */ + static func main() { + /* 初始化栈 */ + // Swift 没有内置的栈类,可以把 Array 当作栈来使用 + var stack: [Int] = [] + + /* 元素入栈 */ + stack.append(1) + stack.append(3) + stack.append(2) + stack.append(5) + stack.append(4) + print("栈 stack = \(stack)") + + /* 访问栈顶元素 */ + let peek = stack.last! + print("栈顶元素 peek = \(peek)") + + /* 元素出栈 */ + let pop = stack.removeLast() + print("出栈元素 pop = \(pop),出栈后 stack = \(stack)") + + /* 获取栈的长度 */ + let size = stack.count + print("栈的长度 size = \(size)") + + /* 判断是否为空 */ + let isEmpty = stack.isEmpty + print("栈是否为空 = \(isEmpty)") + } +} diff --git a/docs/chapter_stack_and_queue/stack.md b/docs/chapter_stack_and_queue/stack.md index d5a3f9164..04825695c 100644 --- a/docs/chapter_stack_and_queue/stack.md +++ b/docs/chapter_stack_and_queue/stack.md @@ -231,7 +231,28 @@ comments: true === "Swift" ```swift title="stack.swift" + /* 初始化栈 */ + // Swift 没有内置的栈类,可以把 Array 当作栈来使用 + var stack: [Int] = [] + /* 元素入栈 */ + stack.append(1) + stack.append(3) + stack.append(2) + stack.append(5) + stack.append(4) + + /* 访问栈顶元素 */ + let peek = stack.last! + + /* 元素出栈 */ + let pop = stack.removeLast() + + /* 获取栈的长度 */ + let size = stack.count + + /* 判断是否为空 */ + let isEmpty = stack.isEmpty ``` ## 栈的实现 @@ -606,7 +627,58 @@ comments: true === "Swift" ```swift title="linkedlist_stack.swift" + /* 基于链表实现的栈 */ + class LinkedListStack { + private var _peek: ListNode? // 将头结点作为栈顶 + private var _size = 0 // 栈的长度 + init() {} + + /* 获取栈的长度 */ + func size() -> Int { + _size + } + + /* 判断栈是否为空 */ + func isEmpty() -> Bool { + _size == 0 + } + + /* 入栈 */ + func push(num: Int) { + let node = ListNode(x: num) + node.next = _peek + _peek = node + _size += 1 + } + + /* 出栈 */ + func pop() -> Int { + let num = peek() + _peek = _peek?.next + _size -= 1 + return num + } + + /* 访问栈顶元素 */ + func peek() -> Int { + if _size == 0 { + fatalError("栈为空") + } + return _peek!.val + } + + /* 将 List 转化为 Array 并返回 */ + func toArray() -> [Int] { + var node = _peek + var res = Array(repeating: 0, count: _size) + for i in sequence(first: res.count - 1, next: { $0 >= 0 + 1 ? $0 - 1 : nil }) { + res[i] = node!.val + node = node?.next + } + return res + } + } ``` ### 基于数组的实现 @@ -897,7 +969,51 @@ comments: true === "Swift" ```swift title="array_stack.swift" + /* 基于数组实现的栈 */ + class ArrayStack { + private var stack: [Int] + init() { + // 初始化列表(动态数组) + stack = [] + } + + /* 获取栈的长度 */ + func size() -> Int { + stack.count + } + + /* 判断栈是否为空 */ + func isEmpty() -> Bool { + stack.isEmpty + } + + /* 入栈 */ + func push(num: Int) { + stack.append(num) + } + + /* 出栈 */ + func pop() -> Int { + if stack.isEmpty { + fatalError("栈为空") + } + return stack.removeLast() + } + + /* 访问栈顶元素 */ + func peek() -> Int { + if stack.isEmpty { + fatalError("栈为空") + } + return stack.last! + } + + /* 将 List 转化为 Array 并返回 */ + func toArray() -> [Int] { + stack + } + } ``` !!! tip From 9c5eedeb8ce7332ddf93ae2c6a8bb381127d93ca Mon Sep 17 00:00:00 2001 From: Cavin Date: Tue, 10 Jan 2023 16:02:46 +0800 Subject: [PATCH 2/7] Update binary_tree.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 优化第三段中对“左子树”和“右子树”的描述 --- docs/chapter_tree/binary_tree.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/chapter_tree/binary_tree.md b/docs/chapter_tree/binary_tree.md index 077c03e0d..1061e019d 100644 --- a/docs/chapter_tree/binary_tree.md +++ b/docs/chapter_tree/binary_tree.md @@ -114,7 +114,7 @@ comments: true 结点的两个指针分别指向「左子结点 Left Child Node」和「右子结点 Right Child Node」,并且称该结点为两个子结点的「父结点 Parent Node」。给定二叉树某结点,将左子结点以下的树称为该结点的「左子树 Left Subtree」,右子树同理。 -除了叶结点外,每个结点都有子结点和子树。例如,若将上图的「结点 2」看作父结点,那么其左子结点和右子结点分别为「结点 4」和「结点 5」,左子树和右子树分别为「结点 4 以下的树」和「结点 5 以下的树」。 +除了叶结点外,每个结点都有子结点和子树。例如,若将上图的「结点 2」看作父结点,那么其左子结点和右子结点分别为「结点 4」和「结点 5」,左子树和右子树分别为「结点 4 及其以下结点形成的树」和「结点 5 及其以下结点形成的树」。 ![binary_tree_definition](binary_tree.assets/binary_tree_definition.png) From 51e52121dce697c1a9a883e63590472354d1c4c5 Mon Sep 17 00:00:00 2001 From: mellowrsa <87369532+mellowrsa@users.noreply.github.com> Date: Tue, 10 Jan 2023 18:05:52 +0800 Subject: [PATCH 3/7] Update time_complexity.md --- .../time_complexity.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/chapter_computational_complexity/time_complexity.md b/docs/chapter_computational_complexity/time_complexity.md index 09aee7b79..ea523b46d 100644 --- a/docs/chapter_computational_complexity/time_complexity.md +++ b/docs/chapter_computational_complexity/time_complexity.md @@ -1434,11 +1434,14 @@ $$ for (int i = n - 1; i > 0; i--) { // 内循环:冒泡操作 for (int j = 0; j < i; j++) { - // 交换 nums[j] 与 nums[j + 1] - int tmp = nums[j]; - nums[j] = nums[j + 1]; - nums[j + 1] = tmp; - count += 3; // 元素交换包含 3 个单元操作 + if (nums[j] > nums [j+1]) + { + // 交换 nums[j] 与 nums[j + 1] + int tmp = nums[j]; + nums[j] = nums[j + 1]; + nums[j + 1] = tmp; + count += 3; // 元素交换包含 3 个单元操作 + } } } From 17de5fd5d17637d15ac837beec74983401927b4b Mon Sep 17 00:00:00 2001 From: reanon <793584285@qq.com> Date: Mon, 9 Jan 2023 17:25:27 +0800 Subject: [PATCH 4/7] feat(include): add c code --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index c960a1bb3..ccb5e1b1e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ # Editor .vscode/ .idea/ +cmake-build-debug/ +CMakeLists.txt hello-algo.iml # mkdocs files From 24cdcd54df0b2f0c01a4cbf5ece35496a0b0cf08 Mon Sep 17 00:00:00 2001 From: reanon <793584285@qq.com> Date: Wed, 11 Jan 2023 00:48:48 +0800 Subject: [PATCH 5/7] feat(codes/c): add C include/ codes and modify exist C codes --- .gitignore | 2 +- codes/c/CMakeLists.txt | 11 ++ .../CMakeLists.txt | 1 + codes/c/chapter_array_and_linkedlist/array.c | 10 +- .../CMakeLists.txt | 2 + .../worst_best_time_complexity.c | 3 +- codes/c/chapter_sorting/CMakeLists.txt | 2 + codes/c/chapter_sorting/bubble_sort.c | 4 +- codes/c/chapter_sorting/insertion_sort.c | 2 +- codes/c/include/CMakeLists.txt | 4 + codes/c/include/PrintUtil.h | 28 ---- codes/c/include/include.h | 19 ++- codes/c/include/include_test.c | 38 +++++ codes/c/include/list_node.h | 72 ++++++++++ codes/c/include/print_util.h | 135 ++++++++++++++++++ codes/c/include/tree_node.h | 131 +++++++++++++++++ 16 files changed, 423 insertions(+), 41 deletions(-) create mode 100644 codes/c/CMakeLists.txt create mode 100644 codes/c/chapter_array_and_linkedlist/CMakeLists.txt create mode 100644 codes/c/chapter_computational_complexity/CMakeLists.txt create mode 100644 codes/c/chapter_sorting/CMakeLists.txt create mode 100644 codes/c/include/CMakeLists.txt delete mode 100644 codes/c/include/PrintUtil.h create mode 100644 codes/c/include/include_test.c create mode 100644 codes/c/include/list_node.h create mode 100644 codes/c/include/print_util.h create mode 100644 codes/c/include/tree_node.h diff --git a/.gitignore b/.gitignore index ccb5e1b1e..52026b066 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,8 @@ .vscode/ .idea/ cmake-build-debug/ -CMakeLists.txt hello-algo.iml +*.dSYM/ # mkdocs files site/ diff --git a/codes/c/CMakeLists.txt b/codes/c/CMakeLists.txt new file mode 100644 index 000000000..dc9e56af3 --- /dev/null +++ b/codes/c/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.10) +project(hello_algo C) + +set(CMAKE_C_STANDARD 11) + +include_directories(./include) + +add_subdirectory(include) +add_subdirectory(chapter_computational_complexity) +add_subdirectory(chapter_array_and_linkedlist) +add_subdirectory(chapter_sorting) diff --git a/codes/c/chapter_array_and_linkedlist/CMakeLists.txt b/codes/c/chapter_array_and_linkedlist/CMakeLists.txt new file mode 100644 index 000000000..24658b301 --- /dev/null +++ b/codes/c/chapter_array_and_linkedlist/CMakeLists.txt @@ -0,0 +1 @@ +add_executable(array array.c) \ No newline at end of file diff --git a/codes/c/chapter_array_and_linkedlist/array.c b/codes/c/chapter_array_and_linkedlist/array.c index 33dc99903..11fcb67f9 100644 --- a/codes/c/chapter_array_and_linkedlist/array.c +++ b/codes/c/chapter_array_and_linkedlist/array.c @@ -74,11 +74,11 @@ int main() { int size = 5; int arr[5]; printf("数组 arr = "); - printArray(arr, size); + PrintArray(arr, size); int nums[5] = { 1, 3, 2, 5, 4 }; printf("数组 nums = "); - printArray(nums, size); + PrintArray(nums, size); /* 随机访问 */ int randomNum = randomAccess(nums, size); @@ -89,17 +89,17 @@ int main() { int* res = extend(nums, size, enlarge); size += enlarge; printf("将数组长度扩展至 8 ,得到 nums = "); - printArray(res, size); + PrintArray(res, size); /* 插入元素 */ insert(res, size, 6, 3); printf("在索引 3 处插入数字 6 ,得到 nums = "); - printArray(res, size); + PrintArray(res, size); /* 删除元素 */ removeItem(res, size, 2); printf("删除索引 2 处的元素,得到 nums = "); - printArray(res, size); + PrintArray(res, size); /* 遍历数组 */ traverse(res, size); diff --git a/codes/c/chapter_computational_complexity/CMakeLists.txt b/codes/c/chapter_computational_complexity/CMakeLists.txt new file mode 100644 index 000000000..d9e55dcf1 --- /dev/null +++ b/codes/c/chapter_computational_complexity/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(time_complexity time_complexity.c ) +add_executable(worst_best_time_complexity worst_best_time_complexity.c) \ No newline at end of file diff --git a/codes/c/chapter_computational_complexity/worst_best_time_complexity.c b/codes/c/chapter_computational_complexity/worst_best_time_complexity.c index 2570ff3c3..531a76e51 100644 --- a/codes/c/chapter_computational_complexity/worst_best_time_complexity.c +++ b/codes/c/chapter_computational_complexity/worst_best_time_complexity.c @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) { int *nums = randomNumbers(n); int index = findOne(nums, n); printf("\n数组 [ 1, 2, ..., n ] 被打乱后 = "); - printArray(nums, n); + PrintArray(nums, n); printf("数字 1 的索引为 %d\n", index); // 释放堆区内存 if (nums != NULL) { @@ -49,6 +49,5 @@ int main(int argc, char *argv[]) { nums = NULL; } } - getchar(); return 0; } diff --git a/codes/c/chapter_sorting/CMakeLists.txt b/codes/c/chapter_sorting/CMakeLists.txt new file mode 100644 index 000000000..192e1cb97 --- /dev/null +++ b/codes/c/chapter_sorting/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(bubble_sort bubble_sort.c) +add_executable(insertion_sort insertion_sort.c) \ No newline at end of file diff --git a/codes/c/chapter_sorting/bubble_sort.c b/codes/c/chapter_sorting/bubble_sort.c index 5c74d9e4e..4a2a24b44 100644 --- a/codes/c/chapter_sorting/bubble_sort.c +++ b/codes/c/chapter_sorting/bubble_sort.c @@ -50,14 +50,14 @@ void bubble_sort_with_flag(int nums[], int size) { /* Driver Code */ int main() { int nums[6] = {4, 1, 3, 1, 5, 2}; - printf("冒泡排序后:\n"); + printf("冒泡排序后: "); bubble_sort(nums, 6); for (int i = 0; i < 6; i++) { printf("%d ", nums[i]); } - printf("优化版冒泡排序后:\n"); + printf("\n优化版冒泡排序后: "); bubble_sort_with_flag(nums, 6); for (int i = 0; i < 6; i++) { diff --git a/codes/c/chapter_sorting/insertion_sort.c b/codes/c/chapter_sorting/insertion_sort.c index 80e8b127b..f81b8d43e 100644 --- a/codes/c/chapter_sorting/insertion_sort.c +++ b/codes/c/chapter_sorting/insertion_sort.c @@ -28,7 +28,7 @@ void insertionSort(int nums[], int size) { int main() { int nums[] = {4, 1, 3, 1, 5, 2}; insertionSort(nums, 6); - printf("插入排序完成后 nums = \n"); + printf("插入排序完成后 nums = "); for (int i = 0; i < 6; i++) { printf("%d ", nums[i]); diff --git a/codes/c/include/CMakeLists.txt b/codes/c/include/CMakeLists.txt new file mode 100644 index 000000000..4189ae334 --- /dev/null +++ b/codes/c/include/CMakeLists.txt @@ -0,0 +1,4 @@ +add_executable(include + include_test.c + include.h print_util.h + list_node.h tree_node.h) \ No newline at end of file diff --git a/codes/c/include/PrintUtil.h b/codes/c/include/PrintUtil.h deleted file mode 100644 index 59a8eac1b..000000000 --- a/codes/c/include/PrintUtil.h +++ /dev/null @@ -1,28 +0,0 @@ -/** - * File: PrintUtil.h - * Created Time: 2022-12-21 - * Author: MolDum (moldum@163.com) - */ - -#include -#include -#include - -// #include "ListNode.h" -// #include "TreeNode.h" - -/** - * @brief Print an Array - * - * @param arr - * @param n - */ - -static void printArray(int* arr, int n) -{ - printf("["); - for (int i = 0; i < n - 1; i++) { - printf("%d, ", arr[i]); - } - printf("%d]\n", arr[n-1]); -} diff --git a/codes/c/include/include.h b/codes/c/include/include.h index 2c4fd9252..9f30b0529 100644 --- a/codes/c/include/include.h +++ b/codes/c/include/include.h @@ -1,13 +1,28 @@ /** * File: include.h * Created Time: 2022-12-20 - * Author: MolDuM (moldum@163.com) + * Author: MolDuM (moldum@163.com)、Reanon (793584285@qq.com) */ +#ifndef C_INCLUDE_H +#define C_INCLUDE_H + #include #include #include #include #include -#include "PrintUtil.h" +#include "list_node.h" +#include "tree_node.h" +#include "print_util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif // C_INCLUDE_H diff --git a/codes/c/include/include_test.c b/codes/c/include/include_test.c new file mode 100644 index 000000000..baa8e649d --- /dev/null +++ b/codes/c/include/include_test.c @@ -0,0 +1,38 @@ +/** + * File: include_test.c + * Created Time: 2023-01-10 + * Author: Reanon (793584285@qq.com) + */ + +#include "include.h" + +void testListNode() { + int nums[] = {2, 3, 5, 6, 7}; + int size = sizeof(nums) / sizeof(int); + ListNode *head = ArrayToLinkedList(nums, size); + PrintLinkedList(head); + + ListNode *node = GetListNode(head, 5); + printf("find node: %d\n", node->val); +} + +void testTreeNode() { + int nums[] = {1, 2, 3, NIL, 5, 6, NIL}; + int size = sizeof(nums) / sizeof(int); + TreeNode *root = ArrayToTree(nums, size); + + // print tree + PrintTree(root); + + // tree to arr + int *arr = TreeToArray(root); + PrintArray(arr, size); +} + +int main(int argc, char *argv[]) { + printf("==testListNode==\n"); + testListNode(); + printf("==testTreeNode==\n"); + testTreeNode(); + return 0; +} diff --git a/codes/c/include/list_node.h b/codes/c/include/list_node.h new file mode 100644 index 000000000..5597d2102 --- /dev/null +++ b/codes/c/include/list_node.h @@ -0,0 +1,72 @@ +/** + * File: list_node.h + * Created Time: 2023-01-09 + * Author: Reanon (793584285@qq.com) + */ +#ifndef LIST_NODE_H +#define LIST_NODE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Definition for a singly-linked list node + * + */ +struct ListNode { + int val; // 结点值 + struct ListNode *next; // 指向下一结点的指针(引用) +}; + +// typedef 为 C 语言的关键字,作用是为一种数据类型定义一个新名字 +typedef struct ListNode ListNode; + +ListNode *NewListNode(int val) { + ListNode *node, *next; + node = (ListNode *) malloc(sizeof(ListNode)); + node->val = val; + node->next = NULL; + return node; +} + +/** + * @brief Generate a linked list with a vector + * + * @param list + * @return ListNode* + */ + +ListNode *ArrayToLinkedList(const int *arr, size_t size) { + if (size <= 0) { + return NULL; + } + + ListNode *dummy = NewListNode(0); + ListNode *node = dummy; + for (int i = 0; i < size; i++) { + node->next = NewListNode(arr[i]); + node = node->next; + } + return dummy->next; +} + +/** + * @brief Get a list node with specific value from a linked list + * + * @param head + * @param val + * @return ListNode* + */ +ListNode *GetListNode(ListNode *head, int val) { + while (head != NULL && head->val != val) { + head = head->next; + } + return head; +} + +#ifdef __cplusplus +} +#endif + +#endif // LIST_NODE_H \ No newline at end of file diff --git a/codes/c/include/print_util.h b/codes/c/include/print_util.h new file mode 100644 index 000000000..fcb0a4ca6 --- /dev/null +++ b/codes/c/include/print_util.h @@ -0,0 +1,135 @@ +/** + * File: print_util.h + * Created Time: 2022-12-21 + * Author: MolDum (moldum@163.com)、Reanon (793584285@qq.com) + */ + +#ifndef PRINT_UTIL_H +#define PRINT_UTIL_H + +#include +#include +#include + +#include "list_node.h" +#include "tree_node.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Print an Array + * + * @param arr + * @param size + */ +static void PrintArray(int *arr, int size) { + printf("["); + for (int i = 0; i < size - 1; i++) { + if (arr[i] != NIL) { + printf("%d, ", arr[i]); + } else { + printf("NULL, "); + } + } + if (arr[size - 1] != NIL) { + printf("%d]\n", arr[size - 1]); + }else{ + printf("NULL]\n"); + } +} + +/** + * @brief Print a linked list + * + * @param head + */ +static void PrintLinkedList(ListNode *node) { + if (node == NULL) { + return; + } + while (node->next != NULL) { + printf("%d -> ", node->val); + node = node->next; + } + printf("%d\n", node->val); +} + +struct Trunk { + struct Trunk *prev; + char *str; +}; + +typedef struct Trunk Trunk; + +Trunk *newTrunk(Trunk *prev, char *str) { + Trunk *trunk = (Trunk *) malloc(sizeof(Trunk)); + trunk->prev = prev; + trunk->str = (char *) malloc(sizeof(char) * 10); + strcpy(trunk->str, str); + return trunk; +} + +/** + * @brief Helper function to print branches of the binary tree + * + * @param trunk + */ +void showTrunks(Trunk *trunk) { + if (trunk == NULL) { + return; + } + showTrunks(trunk->prev); + printf("%s", trunk->str); +} + +/** + * Help to print a binary tree, hide more details + * @param node + * @param prev + * @param isLeft + */ +static void printTreeHelper(TreeNode *node, Trunk *prev, bool isLeft) { + if (node == NULL) { + return; + } + char *prev_str = " "; + Trunk *trunk = newTrunk(prev, prev_str); + printTreeHelper(node->right, trunk, true); + if (prev == NULL) { + trunk->str = "———"; + } else if (isLeft) { + trunk->str = "/———"; + prev_str = " |"; + } else { + trunk->str = "\\———"; + prev->str = prev_str; + } + showTrunks(trunk); + printf("%d\n", node->val); + + if (prev != NULL) { + prev->str = prev_str; + } + trunk->str = " |"; + + printTreeHelper(node->left, trunk, false); +} + +/** + * @brief Print a binary tree + * + * @param head + */ +static void PrintTree(TreeNode *root) { + printTreeHelper(root, NULL, false); +} + + +#ifdef __cplusplus +} +#endif + +#endif // PRINT_UTIL_H diff --git a/codes/c/include/tree_node.h b/codes/c/include/tree_node.h new file mode 100644 index 000000000..4b0e70187 --- /dev/null +++ b/codes/c/include/tree_node.h @@ -0,0 +1,131 @@ +/** + * File: tree_node.h + * Created Time: 2023-01-09 + * Author: Reanon (793584285@qq.com) + */ + + +#ifndef TREE_NODE_H +#define TREE_NODE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define NIL ('#') +#define MAX_NODE_SIZE 5000 + +struct TreeNode { + int val; + int height; + struct TreeNode *left; + struct TreeNode *right; +}; + +typedef struct TreeNode TreeNode; + + +TreeNode *NewTreeNode(int val) { + TreeNode *node; + + node = (TreeNode *) malloc(sizeof(TreeNode)); + node->val = val; + node->height = 0; + node->left = NULL; + node->right = NULL; + return node; +} + +/** + * @brief Generate a binary tree with an array + * + * @param arr + * @param size + * @return TreeNode * + */ +TreeNode *ArrayToTree(const int *arr, size_t size) { + if (size <= 0) { + return NULL; + } + + int front, rear, index; + TreeNode *root, *node; + TreeNode **queue; + + /* 根结点 */ + root = NewTreeNode(arr[0]); + /* 辅助队列 */ + queue = (TreeNode **) malloc(sizeof(TreeNode) * MAX_NODE_SIZE); + // 队列指针 + front = 0, rear = 0; + // 将根结点放入队尾 + queue[rear++] = root; + // 记录遍历数组的索引 + index = 0; + while (front < rear) { + // 取队列中的头结点,并让头结点出队 + node = queue[front++]; + index++; + if (index < size) { + if (arr[index] != NIL) { + node->left = NewTreeNode(arr[index]); + queue[rear++] = node->left; + } + } + index++; + if (index < size) { + if (arr[index] != NIL) { + node->right = NewTreeNode(arr[index]); + queue[rear++] = node->right; + } + } + } + return root; +} + + +/** + * @brief Generate a binary tree with an array + * + * @param arr + * @param size + * @return TreeNode * + */ +int *TreeToArray(TreeNode *root) { + if (root == NULL) { + return NULL; + } + int front, rear; + int index, *arr; + TreeNode *node; + TreeNode **queue; + /* 辅助队列 */ + queue = (TreeNode **) malloc(sizeof(TreeNode) * MAX_NODE_SIZE); + // 队列指针 + front = 0, rear = 0; + // 将根结点放入队尾 + queue[rear++] = root; + /* 辅助数组 */ + arr = (int *) malloc(sizeof(int) * MAX_NODE_SIZE); + // 数组指针 + index = 0; + while (front < rear) { + // 取队列中的头结点,并让头结点出队 + node = queue[front++]; + if (node != NULL) { + arr[index] = node->val; + queue[rear++] = node->left; + queue[rear++] = node->right; + } else { + arr[index] = NIL; + } + index++; + } + return arr; +} + +#ifdef __cplusplus +} +#endif + +#endif // TREE_NODE_H From 8723ca14694b36e00e729739aa1f594eef534814 Mon Sep 17 00:00:00 2001 From: reanon <793584285@qq.com> Date: Wed, 11 Jan 2023 01:56:08 +0800 Subject: [PATCH 6/7] feat(tree): add C codes --- codes/c/CMakeLists.txt | 1 + codes/c/chapter_tree/CMakeLists.txt | 4 ++ codes/c/chapter_tree/binary_search_tree.c | 8 +++ codes/c/chapter_tree/binary_tree.c | 43 +++++++++++ codes/c/chapter_tree/binary_tree_bfs.c | 66 +++++++++++++++++ codes/c/chapter_tree/binary_tree_dfs.c | 72 +++++++++++++++++++ .../chapter_tree/binary_search_tree_test.go | 2 +- 7 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 codes/c/chapter_tree/CMakeLists.txt create mode 100644 codes/c/chapter_tree/binary_search_tree.c create mode 100644 codes/c/chapter_tree/binary_tree.c create mode 100644 codes/c/chapter_tree/binary_tree_bfs.c create mode 100644 codes/c/chapter_tree/binary_tree_dfs.c diff --git a/codes/c/CMakeLists.txt b/codes/c/CMakeLists.txt index dc9e56af3..1a208dd9d 100644 --- a/codes/c/CMakeLists.txt +++ b/codes/c/CMakeLists.txt @@ -9,3 +9,4 @@ add_subdirectory(include) add_subdirectory(chapter_computational_complexity) add_subdirectory(chapter_array_and_linkedlist) add_subdirectory(chapter_sorting) +add_subdirectory(chapter_tree) diff --git a/codes/c/chapter_tree/CMakeLists.txt b/codes/c/chapter_tree/CMakeLists.txt new file mode 100644 index 000000000..779315b7b --- /dev/null +++ b/codes/c/chapter_tree/CMakeLists.txt @@ -0,0 +1,4 @@ +add_executable(binary_search binary_tree.c) +add_executable(binary_tree_bfs binary_tree_bfs.c) +add_executable(binary_tree_dfs binary_tree_dfs.c) +add_executable(binary_search_tree binary_search_tree.c) diff --git a/codes/c/chapter_tree/binary_search_tree.c b/codes/c/chapter_tree/binary_search_tree.c new file mode 100644 index 000000000..f993faec3 --- /dev/null +++ b/codes/c/chapter_tree/binary_search_tree.c @@ -0,0 +1,8 @@ +/** + * File: binary_search_tree.c + * Created Time: 2023-01-11 + * Author: Reanon (793584285@qq.com) + */ + +#include "../include/include.h" + diff --git a/codes/c/chapter_tree/binary_tree.c b/codes/c/chapter_tree/binary_tree.c new file mode 100644 index 000000000..0a2f946a7 --- /dev/null +++ b/codes/c/chapter_tree/binary_tree.c @@ -0,0 +1,43 @@ +/** + * File: binary_tree.c + * Created Time: 2023-01-11 + * Author: Reanon (793584285@qq.com) + */ + +#include "../include/include.h" + +/* Driver Code */ +int main() { + /* 初始化二叉树 */ + // 初始化结点 + TreeNode* n1 = NewTreeNode(1); + TreeNode* n2 = NewTreeNode(2); + TreeNode* n3 = NewTreeNode(3); + TreeNode* n4 = NewTreeNode(4); + TreeNode* n5 = NewTreeNode(5); + // 构建引用指向(即指针) + n1->left = n2; + n1->right = n3; + n2->left = n4; + n2->right = n5; + printf("初始化二叉树\n"); + PrintTree(n1); + + /* 插入与删除结点 */ + TreeNode* P = NewTreeNode(0); + // 在 n1 -> n2 中间插入结点 P + n1->left = P; + P->left = n2; + printf("插入结点 P 后\n"); + PrintTree(n1); + + // 删除结点 P + n1->left = n2; + // 释放内存 + free(P); + printf("删除结点 P 后\n"); + PrintTree(n1); + + return 0; +} + diff --git a/codes/c/chapter_tree/binary_tree_bfs.c b/codes/c/chapter_tree/binary_tree_bfs.c new file mode 100644 index 000000000..abad3735f --- /dev/null +++ b/codes/c/chapter_tree/binary_tree_bfs.c @@ -0,0 +1,66 @@ +/** + * File: binary_tree_bfs.c + * Created Time: 2023-01-11 + * Author: Reanon (793584285@qq.com) + */ + +#include "../include/include.h" + +/* 层序遍历 */ +int *levelOrder(TreeNode *root, int *size) { + /* 辅助队列 */ + int front, rear; + int index, *arr; + TreeNode *node; + TreeNode **queue; + + /* 辅助队列 */ + queue = (TreeNode **) malloc(sizeof(TreeNode) * MAX_NODE_SIZE); + // 队列指针 + front = 0, rear = 0; + // 加入根结点 + queue[rear++] = root; + // 初始化一个列表,用于保存遍历序列 + /* 辅助数组 */ + arr = (int *) malloc(sizeof(int) * MAX_NODE_SIZE); + // 数组指针 + index = 0; + while (front < rear) { + // 队列出队 + node = queue[front++]; + // 保存结点 + arr[index++] = node->val; + if (node->left != NULL) { + // 左子结点入队 + queue[rear++] = node->left; + } + if (node->right != NULL) { + // 右子结点入队 + queue[rear++] = node->right; + } + } + // 更新数组长度的值 + *size = index; + arr = realloc(arr, sizeof(int) * (*size)); + return arr; +} + + +/* Driver Code */ +int main() { + /* 初始化二叉树 */ + // 这里借助了一个从数组直接生成二叉树的函数 + int nums[] = {1, 2, 3, NIL, 5, 6, NIL}; + int size = sizeof(nums) / sizeof(int); + TreeNode *root = ArrayToTree(nums, size); + printf("初始化二叉树\n"); + PrintTree(root); + + /* 层序遍历 */ + // 需要传入数组的长度 + int *arr = levelOrder(root, &size); + printf("层序遍历的结点打印序列 = "); + PrintArray(arr, size); + + return 0; +} \ No newline at end of file diff --git a/codes/c/chapter_tree/binary_tree_dfs.c b/codes/c/chapter_tree/binary_tree_dfs.c new file mode 100644 index 000000000..f72e6687b --- /dev/null +++ b/codes/c/chapter_tree/binary_tree_dfs.c @@ -0,0 +1,72 @@ +/** + * File: binary_tree_dfs.c + * Created Time: 2023-01-11 + * Author: Reanon (793584285@qq.com) + */ + +#include "../include/include.h" + +/* 辅助数组,用于存储遍历序列 */ +int *arr; + +/* 前序遍历 */ +void preOrder(TreeNode *root, int *size) { + + if (root == NULL) return; + // 访问优先级:根结点 -> 左子树 -> 右子树 + arr[(*size)++] = root->val; + preOrder(root->left, size); + preOrder(root->right, size); +} + +/* 中序遍历 */ +void inOrder(TreeNode *root, int *size) { + if (root == NULL) return; + // 访问优先级:左子树 -> 根结点 -> 右子树 + inOrder(root->left, size); + arr[(*size)++] = root->val; + inOrder(root->right, size); +} + +/* 后序遍历 */ +void postOrder(TreeNode *root, int *size) { + if (root == NULL) return; + // 访问优先级:左子树 -> 右子树 -> 根结点 + postOrder(root->left, size); + postOrder(root->right, size); + arr[(*size)++] = root->val; +} + + +/* Driver Code */ +int main() { + /* 初始化二叉树 */ + // 这里借助了一个从数组直接生成二叉树的函数 + int nums[] = {1, 2, 3, 4, 5, 6, 7}; + int size = sizeof(nums) / sizt ceof(int); + TreeNode *root = ArrayToTree(nums, size); + printf("初始化二叉树\n"); + PrintTree(root); + + /* 前序遍历 */ + // 初始化辅助数组 + arr = (int *) malloc(sizeof(int) * MAX_NODE_SIZE); + size = 0; + preOrder(root, &size); + printf("前序遍历的结点打印序列 = "); + PrintArray(arr, size); + + /* 中序遍历 */ + size = 0; + inOrder(root, &size); + printf("中序遍历的结点打印序列 = "); + PrintArray(arr, size); + + /* 后序遍历 */ + size = 0; + postOrder(root, &size); + printf("后序遍历的结点打印序列 = "); + PrintArray(arr, size); + + return 0; +} diff --git a/codes/go/chapter_tree/binary_search_tree_test.go b/codes/go/chapter_tree/binary_search_tree_test.go index 2109d5a44..2a864d138 100644 --- a/codes/go/chapter_tree/binary_search_tree_test.go +++ b/codes/go/chapter_tree/binary_search_tree_test.go @@ -20,7 +20,7 @@ func TestBinarySearchTree(t *testing.T) { fmt.Println("\n二叉树的根结点为:", node.Val) // 查找结点 - node = bst.Search(7) + node = bst.search(7) fmt.Println("查找到的结点对象为", node, ",结点值 =", node.Val) // 插入结点 From 483925686f7ac8103e88ec02c2f841d82e0b5153 Mon Sep 17 00:00:00 2001 From: Yudong Jin Date: Wed, 11 Jan 2023 02:45:28 +0800 Subject: [PATCH 7/7] Update time_complexity.md --- docs/chapter_computational_complexity/time_complexity.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/chapter_computational_complexity/time_complexity.md b/docs/chapter_computational_complexity/time_complexity.md index ea523b46d..def052c92 100644 --- a/docs/chapter_computational_complexity/time_complexity.md +++ b/docs/chapter_computational_complexity/time_complexity.md @@ -1434,7 +1434,7 @@ $$ for (int i = n - 1; i > 0; i--) { // 内循环:冒泡操作 for (int j = 0; j < i; j++) { - if (nums[j] > nums [j+1]) + if (nums[j] > nums [j + 1]) { // 交换 nums[j] 与 nums[j + 1] int tmp = nums[j];