Merge branch 'krahets:master' into rust-computational_complexity

This commit is contained in:
xBLACKICEx 2023-01-14 18:32:36 +01:00 committed by GitHub
commit 8317ffb299
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
135 changed files with 4946 additions and 313 deletions

2
.gitignore vendored
View file

@ -4,7 +4,9 @@
# Editor # Editor
.vscode/ .vscode/
.idea/ .idea/
cmake-build-debug/
hello-algo.iml hello-algo.iml
*.dSYM/
# mkdocs files # mkdocs files
site/ site/

View file

@ -1,4 +0,0 @@
{
"tabWidth": 4,
"useTabs": false
}

16
Dockerfile Normal file
View file

@ -0,0 +1,16 @@
FROM python:3.9.0-alpine
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --upgrade pip
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple mkdocs-material==9.0.2
WORKDIR /app
COPY codes /app/codes
COPY docs /app/docs
COPY mkdocs.yml /app/mkdocs.yml
RUN mkdir ./docs/overrides && mkdocs build
EXPOSE 8000
CMD ["mkdocs", "serve", "-a", "0.0.0.0:8000"]

12
codes/c/CMakeLists.txt Normal file
View file

@ -0,0 +1,12 @@
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)
add_subdirectory(chapter_tree)

View file

@ -0,0 +1,2 @@
add_executable(array array.c)
add_executable(linked_list linked_list.c)

View file

@ -0,0 +1,88 @@
/**
* File: linked_list.c
* Created Time: 2022-01-12
* Author: Zero (glj0@outlook.com)
*/
#include "../include/include.h"
/* 在链表的结点 n0 之后插入结点 P */
void insert(ListNode* n0, ListNode* P) {
ListNode *n1 = n0->next;
n0->next = P;
P->next = n1;
}
/* 删除链表的结点 n0 之后的首个结点 */
// 由于引入了 stdio.h ,此处无法使用 remove 关键词
// 详见 https://github.com/krahets/hello-algo/pull/244#discussion_r1067863888
void removeNode(ListNode* n0) {
if (!n0->next)
return;
// n0 -> P -> n1
ListNode *P = n0->next;
ListNode *n1 = P->next;
n0->next = n1;
// 释放内存
free(P);
}
/* 访问链表中索引为 index 的结点 */
ListNode* access(ListNode* head, int index) {
while (head && head->next && index) {
head = head->next;
index--;
}
return head;
}
/* 在链表中查找值为 target 的首个结点 */
int find(ListNode* head, int target) {
int index = 0;
while (head) {
if (head->val == target)
return index;
head = head->next;
index++;
}
return -1;
}
/* Driver Code */
int main() {
/* 初始化链表 */
// 初始化各个结点
ListNode* n0 = newListNode(1);
ListNode* n1 = newListNode(3);
ListNode* n2 = newListNode(2);
ListNode* n3 = newListNode(5);
ListNode* n4 = newListNode(4);
// 构建引用指向
n0->next = n1;
n1->next = n2;
n2->next = n3;
n3->next = n4;
printf("初始化的链表为\r\n");
printLinkedList(n0);
/* 插入结点 */
insert(n0, newListNode(0));
printf("插入结点后的链表为\r\n");
printLinkedList(n0);
/* 删除结点 */
removeNode(n0);
printf("删除结点后的链表为\r\n");
printLinkedList(n0);
/* 访问结点 */
ListNode* node = access(n0, 3);
printf("链表中索引 3 处的结点的值 = %d\r\n", node->val);
/* 查找结点 */
int index = find(n0, 2);
printf("链表中值为 2 的结点的索引 = %d\r\n", index);
return 0;
}

View file

@ -0,0 +1,2 @@
add_executable(time_complexity time_complexity.c )
add_executable(worst_best_time_complexity worst_best_time_complexity.c)

View file

@ -56,11 +56,13 @@ int bubbleSort(int *nums, int n) {
for (int i = n - 1; i > 0; i--) { for (int i = n - 1; i > 0; i--) {
// 内循环:冒泡操作 // 内循环:冒泡操作
for (int j = 0; j < i; j++) { for (int j = 0; j < i; j++) {
// 交换 nums[j] 与 nums[j + 1] if (nums[j] > nums[j + 1]) {
int tmp = nums[j]; // 交换 nums[j] 与 nums[j + 1]
nums[j] = nums[j + 1]; int tmp = nums[j];
nums[j + 1] = tmp; nums[j] = nums[j + 1];
count += 3; // 元素交换包含 3 个单元操作 nums[j + 1] = tmp;
count += 3; // 元素交换包含 3 个单元操作
}
} }
} }
return count; return count;

View file

@ -49,6 +49,5 @@ int main(int argc, char *argv[]) {
nums = NULL; nums = NULL;
} }
} }
getchar();
return 0; return 0;
} }

View file

@ -0,0 +1,2 @@
add_executable(bubble_sort bubble_sort.c)
add_executable(insertion_sort insertion_sort.c)

View file

@ -7,7 +7,7 @@
#include "../include/include.h" #include "../include/include.h"
/* 冒泡排序 */ /* 冒泡排序 */
void bubble_sort(int nums[], int size) { void bubbleSort(int nums[], int size) {
// 外循环:待排序元素数量为 n-1, n-2, ..., 1 // 外循环:待排序元素数量为 n-1, n-2, ..., 1
for (int i = 0; i < size - 1; i++) for (int i = 0; i < size - 1; i++)
{ {
@ -25,7 +25,7 @@ void bubble_sort(int nums[], int size) {
} }
/* 冒泡排序(标志优化)*/ /* 冒泡排序(标志优化)*/
void bubble_sort_with_flag(int nums[], int size) { void bubbleSortWithFlag(int nums[], int size) {
// 外循环:待排序元素数量为 n-1, n-2, ..., 1 // 外循环:待排序元素数量为 n-1, n-2, ..., 1
for (int i = 0; i < size - 1; i++) for (int i = 0; i < size - 1; i++)
{ {
@ -50,15 +50,15 @@ void bubble_sort_with_flag(int nums[], int size) {
/* Driver Code */ /* Driver Code */
int main() { int main() {
int nums[6] = {4, 1, 3, 1, 5, 2}; int nums[6] = {4, 1, 3, 1, 5, 2};
printf("冒泡排序后:\n"); printf("冒泡排序后: ");
bubble_sort(nums, 6); bubbleSort(nums, 6);
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
{ {
printf("%d ", nums[i]); printf("%d ", nums[i]);
} }
printf("优化版冒泡排序后:\n"); printf("\n优化版冒泡排序后: ");
bubble_sort_with_flag(nums, 6); bubbleSortWithFlag(nums, 6);
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
{ {
printf("%d ", nums[i]); printf("%d ", nums[i]);

View file

@ -28,7 +28,7 @@ void insertionSort(int nums[], int size) {
int main() { int main() {
int nums[] = {4, 1, 3, 1, 5, 2}; int nums[] = {4, 1, 3, 1, 5, 2};
insertionSort(nums, 6); insertionSort(nums, 6);
printf("插入排序完成后 nums = \n"); printf("插入排序完成后 nums = ");
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
{ {
printf("%d ", nums[i]); printf("%d ", nums[i]);

View file

@ -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)

View file

@ -0,0 +1,8 @@
/**
* File: binary_search_tree.c
* Created Time: 2023-01-11
* Author: Reanon (793584285@qq.com)
*/
#include "../include/include.h"

View file

@ -0,0 +1,42 @@
/**
* 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;
}

View file

@ -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 = arrToTree(nums, size);
printf("初始化二叉树\n");
printTree(root);
/* 层序遍历 */
// 需要传入数组的长度
int *arr = levelOrder(root, &size);
printf("层序遍历的结点打印序列 = ");
printArray(arr, size);
return 0;
}

View file

@ -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) / sizeof(int);
TreeNode *root = arrToTree(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;
}

View file

@ -0,0 +1,4 @@
add_executable(include
include_test.c
include.h print_util.h
list_node.h tree_node.h)

View file

@ -1,28 +0,0 @@
/**
* File: PrintUtil.h
* Created Time: 2022-12-21
* Author: MolDum (moldum@163.com)
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// #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]);
}

View file

@ -1,13 +1,28 @@
/** /**
* File: include.h * File: include.h
* Created Time: 2022-12-20 * 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 <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include <time.h> #include <time.h>
#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

View file

@ -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 = arrToLinkedList(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 = arrToTree(nums, size);
// print tree
printTree(root);
// tree to arr
int *arr = treeToArr(root);
printArray(arr, size);
}
int main(int argc, char *argv[]) {
printf("==testListNode==\n");
testListNode();
printf("==testTreeNode==\n");
testTreeNode();
return 0;
}

View file

@ -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 *arrToLinkedList(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

View file

@ -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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#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

131
codes/c/include/tree_node.h Normal file
View file

@ -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 *arrToTree(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 *treeToArr(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

View file

@ -23,6 +23,8 @@ int* extend(int* nums, int size, int enlarge) {
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
res[i] = nums[i]; res[i] = nums[i];
} }
// 释放内存
delete[] nums;
// 返回扩展后的新数组 // 返回扩展后的新数组
return res; return res;
} }
@ -82,10 +84,7 @@ int main() {
/* 长度扩展 */ /* 长度扩展 */
int enlarge = 3; int enlarge = 3;
int* res = extend(nums, size, enlarge); nums = extend(nums, size, enlarge);
int* temp = nums;
nums = res;
delete[] temp;
size += enlarge; size += enlarge;
cout << "将数组长度扩展至 8 ,得到 nums = "; cout << "将数组长度扩展至 8 ,得到 nums = ";
PrintUtil::printArray(nums, size); PrintUtil::printArray(nums, size);
@ -107,5 +106,9 @@ int main() {
int index = find(nums, size, 3); int index = find(nums, size, 3);
cout << "在 nums 中查找元素 3 ,得到索引 = " << index << endl; cout << "在 nums 中查找元素 3 ,得到索引 = " << index << endl;
// 释放内存
delete[] arr;
delete[] nums;
return 0; return 0;
} }

View file

@ -83,5 +83,8 @@ int main() {
int index = find(n0, 2); int index = find(n0, 2);
cout << "链表中值为 2 的结点的索引 = " << index << endl; cout << "链表中值为 2 的结点的索引 = " << index << endl;
// 释放内存
freeMemoryLinkedList(n0);
return 0; return 0;
} }

View file

@ -20,6 +20,11 @@ public:
nums = new int[numsCapacity]; nums = new int[numsCapacity];
} }
/* 析构函数 */
~MyList() {
delete[] nums;
}
/* 获取列表长度(即当前元素数量)*/ /* 获取列表长度(即当前元素数量)*/
int size() { int size() {
return numsSize; return numsSize;
@ -90,14 +95,14 @@ public:
void extendCapacity() { void extendCapacity() {
// 新建一个长度为 size * extendRatio 的数组,并将原数组拷贝到新数组 // 新建一个长度为 size * extendRatio 的数组,并将原数组拷贝到新数组
int newCapacity = capacity() * extendRatio; int newCapacity = capacity() * extendRatio;
int* extend = new int[newCapacity]; int* tmp = nums;
nums = new int[newCapacity];
// 将原数组中的所有元素复制到新数组 // 将原数组中的所有元素复制到新数组
for (int i = 0; i < size(); i++) { for (int i = 0; i < size(); i++) {
extend[i] = nums[i]; nums[i] = tmp[i];
} }
int* temp = nums; // 释放内存
nums = extend; delete[] tmp;
delete[] temp;
numsCapacity = newCapacity; numsCapacity = newCapacity;
} }
@ -160,5 +165,8 @@ int main() {
PrintUtil::printVector(vec); PrintUtil::printVector(vec);
cout << "容量 = " << list->capacity() << " ,长度 = " << list->size() << endl; cout << "容量 = " << list->capacity() << " ,长度 = " << list->size() << endl;
// 释放内存
delete list;
return 0; return 0;
} }

View file

@ -56,5 +56,9 @@ int main() {
cout << "方法二 res = "; cout << "方法二 res = ";
PrintUtil::printVector(res); PrintUtil::printVector(res);
// 释放内存
delete slt1;
delete slt2;
return 0; return 0;
} }

View file

@ -18,7 +18,7 @@ void constant(int n) {
const int a = 0; const int a = 0;
int b = 0; int b = 0;
vector<int> nums(10000); vector<int> nums(10000);
ListNode* node = new ListNode(0); ListNode node(0);
// 循环中的变量占用 O(1) 空间 // 循环中的变量占用 O(1) 空间
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
int c = 0; int c = 0;
@ -34,9 +34,9 @@ void linear(int n) {
// 长度为 n 的数组占用 O(n) 空间 // 长度为 n 的数组占用 O(n) 空间
vector<int> nums(n); vector<int> nums(n);
// 长度为 n 的列表占用 O(n) 空间 // 长度为 n 的列表占用 O(n) 空间
vector<ListNode*> nodes; vector<ListNode> nodes;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
nodes.push_back(new ListNode(i)); nodes.push_back(ListNode(i));
} }
// 长度为 n 的哈希表占用 O(n) 空间 // 长度为 n 的哈希表占用 O(n) 空间
unordered_map<int, string> map; unordered_map<int, string> map;
@ -98,5 +98,8 @@ int main() {
TreeNode* root = buildTree(n); TreeNode* root = buildTree(n);
PrintUtil::printTree(root); PrintUtil::printTree(root);
// 释放内存
freeMemoryTree(root);
return 0; return 0;
} }

View file

@ -21,6 +21,10 @@ public:
nums = new int[capacity]; nums = new int[capacity];
} }
~ArrayQueue() {
delete[] nums;
}
/* 获取队列的容量 */ /* 获取队列的容量 */
int capacity() { int capacity() {
return cap; return cap;
@ -117,5 +121,8 @@ int main() {
PrintUtil::printVector(queue->toVector()); PrintUtil::printVector(queue->toVector());
} }
// 释放内存
delete queue;
return 0; return 0;
} }

View file

@ -78,5 +78,8 @@ int main() {
bool empty = stack->empty(); bool empty = stack->empty();
cout << "栈是否为空 = " << empty << endl; cout << "栈是否为空 = " << empty << endl;
// 释放内存
delete stack;
return 0; return 0;
} }

View file

@ -19,6 +19,11 @@ public:
queSize = 0; queSize = 0;
} }
~LinkedListQueue() {
delete front;
delete rear;
}
/* 获取队列的长度 */ /* 获取队列的长度 */
int size() { int size() {
return queSize; return queSize;
@ -108,5 +113,8 @@ int main() {
bool empty = queue->empty(); bool empty = queue->empty();
cout << "队列是否为空 = " << empty << endl; cout << "队列是否为空 = " << empty << endl;
// 释放内存
delete queue;
return 0; return 0;
} }

View file

@ -18,6 +18,10 @@ public:
stkSize = 0; stkSize = 0;
} }
~LinkedListStack() {
freeMemoryLinkedList(stackTop);
}
/* 获取栈的长度 */ /* 获取栈的长度 */
int size() { int size() {
return stkSize; return stkSize;
@ -97,5 +101,8 @@ int main() {
bool empty = stack->empty(); bool empty = stack->empty();
cout << "栈是否为空 = " << empty << endl; cout << "栈是否为空 = " << empty << endl;
// 释放内存
delete stack;
return 0; return 0;
} }

View file

@ -17,6 +17,10 @@ public:
root = buildTree(nums, 0, nums.size() - 1); // 构建二叉搜索树 root = buildTree(nums, 0, nums.size() - 1); // 构建二叉搜索树
} }
~BinarySearchTree() {
freeMemoryTree(root);
}
/* 获取二叉树根结点 */ /* 获取二叉树根结点 */
TreeNode* getRoot() { TreeNode* getRoot() {
return root; return root;
@ -152,5 +156,8 @@ int main() {
cout << endl << "删除结点 4 后,二叉树为\n" << endl; cout << endl << "删除结点 4 后,二叉树为\n" << endl;
PrintUtil::printTree(bst->getRoot()); PrintUtil::printTree(bst->getRoot());
// 释放内存
delete bst;
return 0; return 0;
} }

View file

@ -37,5 +37,8 @@ int main() {
cout << endl << "删除结点 P 后\n" << endl; cout << endl << "删除结点 P 后\n" << endl;
PrintUtil::printTree(n1); PrintUtil::printTree(n1);
// 释放内存
freeMemoryTree(n1);
return 0; return 0;
} }

View file

@ -48,3 +48,18 @@ ListNode* getListNode(ListNode *head, int val) {
} }
return head; return head;
} }
/**
* @brief Free the memory allocated to a linked list
*
* @param cur
*/
void freeMemoryLinkedList(ListNode *cur) {
// 释放内存
ListNode *pre;
while (cur != nullptr) {
pre = cur;
cur = cur->next;
delete pre;
}
}

View file

@ -68,3 +68,16 @@ TreeNode *getTreeNode(TreeNode *root, int val) {
TreeNode *right = getTreeNode(root->right, val); TreeNode *right = getTreeNode(root->right, val);
return left != nullptr ? left : right; return left != nullptr ? left : right;
} }
/**
* @brief Free the memory allocated to a tree
*
* @param root
*/
void freeMemoryTree(TreeNode *root) {
if (root == nullptr) return;
freeMemoryTree(root->left);
freeMemoryTree(root->right);
// 释放内存
delete root;
}

View file

@ -17,6 +17,8 @@
#include <unordered_set> #include <unordered_set>
#include <set> #include <set>
#include <random> #include <random>
#include <chrono>
#include <algorithm>
#include "ListNode.hpp" #include "ListNode.hpp"
#include "TreeNode.hpp" #include "TreeNode.hpp"

View file

@ -0,0 +1,45 @@
// File: intHeap.go
// Created Time: 2023-01-12
// Author: Reanon (793584285@qq.com)
package chapter_heap
// Go 语言中可以通过实现 heap.Interface 来构建整数大顶堆
// 实现 heap.Interface 需要同时实现 sort.Interface
type intHeap []any
// Push heap.Interface 的方法,实现推入元素到堆
func (h *intHeap) Push(x any) {
// Push 和 Pop 使用 pointer receiver 作为参数
// 因为它们不仅会对切片的内容进行调整,还会修改切片的长度。
*h = append(*h, x.(int))
}
// Pop heap.Interface 的方法,实现弹出堆顶元素
func (h *intHeap) Pop() any {
// 待出堆元素存放在最后
last := (*h)[len(*h)-1]
*h = (*h)[:len(*h)-1]
return last
}
// Len sort.Interface 的方法
func (h *intHeap) Len() int {
return len(*h)
}
// Less sort.Interface 的方法
func (h *intHeap) Less(i, j int) bool {
// 如果实现小顶堆,则需要调整为小于号
return (*h)[i].(int) > (*h)[j].(int)
}
// Swap sort.Interface 的方法
func (h *intHeap) Swap(i, j int) {
(*h)[i], (*h)[j] = (*h)[j], (*h)[i]
}
// Top 获取堆顶元素
func (h *intHeap) Top() any {
return (*h)[0]
}

View file

@ -0,0 +1,90 @@
// File: heap_test.go
// Created Time: 2023-01-12
// Author: Reanon (793584285@qq.com)
package chapter_heap
import (
"container/heap"
"fmt"
"testing"
. "github.com/krahets/hello-algo/pkg"
)
func testPush(h *intHeap, val int) {
// 调用 heap.Interface 的方法,来添加元素
heap.Push(h, val)
fmt.Printf("\n元素 %d 入堆后 \n", val)
PrintHeap(*h)
}
func testPop(h *intHeap) {
// 调用 heap.Interface 的方法,来移除元素
val := heap.Pop(h)
fmt.Printf("\n堆顶元素 %d 出堆后 \n", val)
PrintHeap(*h)
}
func TestHeap(t *testing.T) {
/* 初始化堆 */
// 初始化大顶堆
maxHeap := &intHeap{}
heap.Init(maxHeap)
/* 元素入堆 */
testPush(maxHeap, 1)
testPush(maxHeap, 3)
testPush(maxHeap, 2)
testPush(maxHeap, 5)
testPush(maxHeap, 4)
/* 获取堆顶元素 */
top := maxHeap.Top()
fmt.Printf("堆顶元素为 %d\n", top)
/* 堆顶元素出堆 */
testPop(maxHeap)
testPop(maxHeap)
testPop(maxHeap)
testPop(maxHeap)
testPop(maxHeap)
/* 获取堆大小 */
size := len(*maxHeap)
fmt.Printf("堆元素数量为 %d\n", size)
/* 判断堆是否为空 */
isEmpty := len(*maxHeap) == 0
fmt.Printf("堆是否为空 %t\n", isEmpty)
}
func TestMyHeap(t *testing.T) {
/* 初始化堆 */
// 初始化大顶堆
maxHeap := newMaxHeap([]any{9, 8, 6, 6, 7, 5, 2, 1, 4, 3, 6, 2})
fmt.Printf("输入数组并建堆后\n")
maxHeap.print()
/* 获取堆顶元素 */
peek := maxHeap.peek()
fmt.Printf("\n堆顶元素为 %d\n", peek)
/* 元素入堆 */
val := 7
maxHeap.push(val)
fmt.Printf("\n元素 %d 入堆后\n", val)
maxHeap.print()
/* 堆顶元素出堆 */
peek = maxHeap.poll()
fmt.Printf("\n堆顶元素 %d 出堆后\n", peek)
maxHeap.print()
/* 获取堆大小 */
size := maxHeap.size()
fmt.Printf("\n堆元素数量为 %d\n", size)
/* 判断堆是否为空 */
isEmpty := maxHeap.isEmpty()
fmt.Printf("\n堆是否为空 %t\n", isEmpty)
}

View file

@ -0,0 +1,139 @@
// File: my_heap.go
// Created Time: 2023-01-12
// Author: Reanon (793584285@qq.com)
package chapter_heap
import (
"fmt"
. "github.com/krahets/hello-algo/pkg"
)
type maxHeap struct {
// 使用切片而非数组,这样无需考虑扩容问题
data []any
}
/* 构造函数,建立空堆 */
func newHeap() *maxHeap {
return &maxHeap{
data: make([]any, 0),
}
}
/* 构造函数,根据切片建堆 */
func newMaxHeap(nums []any) *maxHeap {
// 所有元素入堆
h := &maxHeap{data: nums}
for i := len(h.data) - 1; i >= 0; i-- {
// 堆化除叶结点以外的其他所有结点
h.siftDown(i)
}
return h
}
/* 获取左子结点索引 */
func (h *maxHeap) left(i int) int {
return 2*i + 1
}
/* 获取右子结点索引 */
func (h *maxHeap) right(i int) int {
return 2*i + 2
}
/* 获取父结点索引 */
func (h *maxHeap) parent(i int) int {
// 向下整除
return (i - 1) / 2
}
/* 交换元素 */
func (h *maxHeap) swap(i, j int) {
h.data[i], h.data[j] = h.data[j], h.data[i]
}
/* 获取堆大小 */
func (h *maxHeap) size() int {
return len(h.data)
}
/* 判断堆是否为空 */
func (h *maxHeap) isEmpty() bool {
return len(h.data) == 0
}
/* 访问堆顶元素 */
func (h *maxHeap) peek() any {
return h.data[0]
}
/* 元素入堆 */
func (h *maxHeap) push(val any) {
// 添加结点
h.data = append(h.data, val)
// 从底至顶堆化
h.siftUp(len(h.data) - 1)
}
/* 从结点 i 开始,从底至顶堆化 */
func (h *maxHeap) siftUp(i int) {
for true {
// 获取结点 i 的父结点
p := h.parent(i)
// 当“越过根结点”或“结点无需修复”时,结束堆化
if p < 0 || h.data[i].(int) <= h.data[p].(int) {
break
}
// 交换两结点
h.swap(i, p)
// 循环向上堆化
i = p
}
}
/* 元素出堆 */
func (h *maxHeap) poll() any {
// 判空处理
if h.isEmpty() {
fmt.Println("error")
}
// 交换根结点与最右叶结点(即交换首元素与尾元素)
h.swap(0, h.size()-1)
// 删除结点
val := h.data[len(h.data)-1]
h.data = h.data[:len(h.data)-1]
// 从顶至底堆化
h.siftDown(0)
// 返回堆顶元素
return val
}
/* 从结点 i 开始,从顶至底堆化 */
func (h *maxHeap) siftDown(i int) {
for true {
// 判断结点 i, l, r 中值最大的结点,记为 max
l, r, max := h.left(i), h.right(i), i
if l < h.size() && h.data[l].(int) > h.data[max].(int) {
max = l
}
if r < h.size() && h.data[r].(int) > h.data[max].(int) {
max = r
}
// 若结点 i 最大或索引 l, r 越界,则无需继续堆化,跳出
if max == i {
break
}
// 交换两结点
h.swap(i, max)
// 循环向下堆化
i = max
}
}
/* 打印堆(二叉树) */
func (h *maxHeap) print() {
PrintHeap(h.data)
}

View file

@ -20,7 +20,7 @@ func TestBinarySearchTree(t *testing.T) {
fmt.Println("\n二叉树的根结点为:", node.Val) fmt.Println("\n二叉树的根结点为:", node.Val)
// 查找结点 // 查找结点
node = bst.Search(7) node = bst.search(7)
fmt.Println("查找到的结点对象为", node, ",结点值 =", node.Val) fmt.Println("查找到的结点对象为", node, ",结点值 =", node.Val)
// 插入结点 // 插入结点

View file

@ -29,6 +29,22 @@ func PrintList(list *list.List) {
fmt.Print(e.Value, "]\n") fmt.Print(e.Value, "]\n")
} }
// PrintMap Print a hash map
func PrintMap[K comparable, V any](m map[K]V) {
for key, value := range m {
fmt.Println(key, "->", value)
}
}
// PrintHeap Print a heap
func PrintHeap(h []any) {
fmt.Printf("堆的数组表示:")
fmt.Printf("%v", h)
fmt.Printf("\n堆的树状表示\n")
root := ArrToTree(h)
PrintTree(root)
}
// PrintLinkedList Print a linked list // PrintLinkedList Print a linked list
func PrintLinkedList(node *ListNode) { func PrintLinkedList(node *ListNode) {
if node == nil { if node == nil {
@ -97,10 +113,3 @@ func showTrunk(t *trunk) {
showTrunk(t.prev) showTrunk(t.prev)
fmt.Print(t.str) fmt.Print(t.str)
} }
// PrintMap Print a hash map
func PrintMap[K comparable, V any](m map[K]V) {
for key, value := range m {
fmt.Println(key, "->", value)
}
}

View file

@ -5,6 +5,7 @@
*/ */
package chapter_hashing; package chapter_hashing;
import java.util.*; import java.util.*;
/* 键值对 int->String */ /* 键值对 int->String */

View file

@ -5,6 +5,7 @@
*/ */
package chapter_hashing; package chapter_hashing;
import java.util.*; import java.util.*;
import include.*; import include.*;

View file

@ -0,0 +1,67 @@
/**
* File: my_heap.java
* Created Time: 2023-01-07
* Author: Krahets (krahets@163.com)
*/
package chapter_heap;
import include.*;
import java.util.*;
public class heap {
public static void testPush(Queue<Integer> heap, int val) {
heap.add(val); // 元素入堆
System.out.format("\n元素 %d 入堆后\n", val);
PrintUtil.printHeap(heap);
}
public static void testPoll(Queue<Integer> heap) {
int val = heap.poll(); // 堆顶元素出堆
System.out.format("\n堆顶元素 %d 出堆后\n", val);
PrintUtil.printHeap(heap);
}
public static void main(String[] args) {
/* 初始化堆 */
// 初始化小顶堆
Queue<Integer> minHeap = new PriorityQueue<>();
// 初始化大顶堆使用 lambda 表达式修改 Comparator 即可
Queue<Integer> maxHeap = new PriorityQueue<>((a, b) -> { return b - a; });
System.out.println("\n以下测试样例为大顶堆");
/* 元素入堆 */
testPush(maxHeap, 1);
testPush(maxHeap, 3);
testPush(maxHeap, 2);
testPush(maxHeap, 5);
testPush(maxHeap, 4);
/* 获取堆顶元素 */
int peek = maxHeap.peek();
System.out.format("\n堆顶元素为 %d\n", peek);
/* 堆顶元素出堆 */
testPoll(maxHeap);
testPoll(maxHeap);
testPoll(maxHeap);
testPoll(maxHeap);
testPoll(maxHeap);
/* 获取堆大小 */
int size = maxHeap.size();
System.out.format("\n堆元素数量为 %d\n", size);
/* 判断堆是否为空 */
boolean isEmpty = maxHeap.isEmpty();
System.out.format("\n堆是否为空 %b\n", isEmpty);
/* 输入列表并建堆 */
// 时间复杂度为 O(n) 而非 O(nlogn)
minHeap = new PriorityQueue<>(Arrays.asList(1, 3, 2, 5, 4));
System.out.println("\n输入列表并建立小顶堆后");
PrintUtil.printHeap(minHeap);
}
}

View file

@ -0,0 +1,177 @@
/**
* File: my_heap.java
* Created Time: 2023-01-07
* Author: Krahets (krahets@163.com)
*/
package chapter_heap;
import include.*;
import java.util.*;
class MaxHeap {
// 使用列表而非数组这样无需考虑扩容问题
private List<Integer> maxHeap;
/* 构造函数,建立空堆 */
public MaxHeap() {
maxHeap = new ArrayList<>();
}
/* 构造函数,根据输入列表建堆 */
public MaxHeap(List<Integer> nums) {
// 所有元素入堆
maxHeap = new ArrayList<>(nums);
// 堆化除叶结点以外的其他所有结点
for (int i = parent(size() - 1); i >= 0; i--) {
siftDown(i);
}
}
/* 获取左子结点索引 */
private int left(int i) {
return 2 * i + 1;
}
/* 获取右子结点索引 */
private int right(int i) {
return 2 * i + 2;
}
/* 获取父结点索引 */
private int parent(int i) {
return (i - 1) / 2; // 向下整除
}
/* 交换元素 */
private void swap(int i, int j) {
int a = maxHeap.get(i),
b = maxHeap.get(j),
tmp = a;
maxHeap.set(i, b);
maxHeap.set(j, tmp);
}
/* 获取堆大小 */
public int size() {
return maxHeap.size();
}
/* 判断堆是否为空 */
public boolean isEmpty() {
return size() == 0;
}
/* 访问堆顶元素 */
public int peek() {
return maxHeap.get(0);
}
/* 元素入堆 */
public void push(int val) {
// 添加结点
maxHeap.add(val);
// 从底至顶堆化
siftUp(size() - 1);
}
/* 从结点 i 开始,从底至顶堆化 */
private void siftUp(int i) {
while (true) {
// 获取结点 i 的父结点
int p = parent(i);
// 越过根结点结点无需修复结束堆化
if (p < 0 || maxHeap.get(i) <= maxHeap.get(p))
break;
// 交换两结点
swap(i, p);
// 循环向上堆化
i = p;
}
}
/* 元素出堆 */
public int poll() {
// 判空处理
if (isEmpty())
throw new EmptyStackException();
// 交换根结点与最右叶结点即交换首元素与尾元素
swap(0, size() - 1);
// 删除结点
int val = maxHeap.remove(size() - 1);
// 从顶至底堆化
siftDown(0);
// 返回堆顶元素
return val;
}
/* 从结点 i 开始,从顶至底堆化 */
private void siftDown(int i) {
while (true) {
// 判断结点 i, l, r 中值最大的结点记为 ma
int l = left(i), r = right(i), ma = i;
if (l < size() && maxHeap.get(l) > maxHeap.get(ma))
ma = l;
if (r < size() && maxHeap.get(r) > maxHeap.get(ma))
ma = r;
// 若结点 i 最大或索引 l, r 越界则无需继续堆化跳出
if (ma == i) break;
// 交换两结点
swap(i, ma);
// 循环向下堆化
i = ma;
}
}
/* 打印堆(二叉树) */
public void print() {
Queue<Integer> queue = new PriorityQueue<>((a, b) -> { return b - a; });
queue.addAll(maxHeap);
PrintUtil.printHeap(queue);
}
}
public class my_heap {
public static void testPush(MaxHeap maxHeap, int val) {
maxHeap.push(val); // 元素入堆
System.out.format("\n添加元素 %d 后\n", val);
maxHeap.print();
}
public static void testPoll(MaxHeap maxHeap) {
int val = maxHeap.poll(); // 堆顶元素出堆
System.out.format("\n出堆元素为 %d\n", val);
maxHeap.print();
}
public static void main(String[] args) {
/* 初始化大顶堆 */
MaxHeap maxHeap = new MaxHeap(Arrays.asList(9, 8, 6, 6, 7, 5, 2, 1, 4, 3, 6, 2));
System.out.println("\n输入列表并建堆后");
maxHeap.print();
/* 获取堆顶元素 */
int peek = maxHeap.peek();
System.out.format("\n堆顶元素为 %d\n", peek);
/* 元素入堆 */
int val = 7;
maxHeap.push(val);
System.out.format("\n元素 %d 入堆后\n", val);
maxHeap.print();
/* 堆顶元素出堆 */
peek = maxHeap.poll();
System.out.format("\n堆顶元素 %d 出堆后\n", peek);
maxHeap.print();
/* 获取堆大小 */
int size = maxHeap.size();
System.out.format("\n堆元素数量为 %d\n", size);
/* 判断堆是否为空 */
boolean isEmpty = maxHeap.isEmpty();
System.out.format("\n堆是否为空 %b\n", isEmpty);
}
}

View file

@ -30,7 +30,7 @@ public class binary_tree_bfs {
public static void main(String[] args) { public static void main(String[] args) {
/* 初始化二叉树 */ /* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数 // 这里借助了一个从数组直接生成二叉树的函数
TreeNode root = TreeNode.arrToTree(new Integer[] { 1, 2, 3, 4, 5, 6, 7 }); TreeNode root = TreeNode.listToTree(Arrays.asList(1, 2, 3, 4, 5, 6, 7));
System.out.println("\n初始化二叉树\n"); System.out.println("\n初始化二叉树\n");
PrintUtil.printTree(root); PrintUtil.printTree(root);

View file

@ -43,7 +43,7 @@ public class binary_tree_dfs {
public static void main(String[] args) { public static void main(String[] args) {
/* 初始化二叉树 */ /* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数 // 这里借助了一个从数组直接生成二叉树的函数
TreeNode root = TreeNode.arrToTree(new Integer[] { 1, 2, 3, 4, 5, 6, 7 }); TreeNode root = TreeNode.listToTree(Arrays.asList(1, 2, 3, 4, 5, 6, 7));
System.out.println("\n初始化二叉树\n"); System.out.println("\n初始化二叉树\n");
PrintUtil.printTree(root); PrintUtil.printTree(root);

View file

@ -105,10 +105,16 @@ public class PrintUtil {
} }
} }
public static void printHeap(PriorityQueue<Integer> queue) { /**
Integer[] nums = (Integer[])queue.toArray(); * Print a heap (PriorityQueue)
TreeNode root = TreeNode.arrToTree(nums); * @param queue
*/
public static void printHeap(Queue<Integer> queue) {
List<Integer> list = new ArrayList<>(queue);
System.out.print("堆的数组表示:");
System.out.println(list);
System.out.println("堆的树状表示:");
TreeNode root = TreeNode.listToTree(list);
printTree(root); printTree(root);
} }
} }

View file

@ -23,26 +23,27 @@ public class TreeNode {
/** /**
* Generate a binary tree given an array * Generate a binary tree given an array
* @param arr * @param list
* @return * @return
*/ */
public static TreeNode arrToTree(Integer[] arr) { public static TreeNode listToTree(List<Integer> list) {
if (arr.length == 0) int size = list.size();
if (size == 0)
return null; return null;
TreeNode root = new TreeNode(arr[0]); TreeNode root = new TreeNode(list.get(0));
Queue<TreeNode> queue = new LinkedList<>() {{ add(root); }}; Queue<TreeNode> queue = new LinkedList<>() {{ add(root); }};
int i = 0; int i = 0;
while(!queue.isEmpty()) { while(!queue.isEmpty()) {
TreeNode node = queue.poll(); TreeNode node = queue.poll();
if (++i >= arr.length) break; if (++i >= size) break;
if(arr[i] != null) { if (list.get(i) != null) {
node.left = new TreeNode(arr[i]); node.left = new TreeNode(list.get(i));
queue.add(node.left); queue.add(node.left);
} }
if (++i >= arr.length) break; if (++i >= size) break;
if(arr[i] != null) { if (list.get(i) != null) {
node.right = new TreeNode(arr[i]); node.right = new TreeNode(list.get(i));
queue.add(node.right); queue.add(node.right);
} }
} }

View file

@ -0,0 +1,51 @@
/**
* File: hashing_search.js
* Created Time: 2022-12-29
* Author: Zhuo Qinyue (1403450829@qq.com)
*/
const PrintUtil = require("../include/PrintUtil");
const ListNode = require("../include/ListNode");
/* 哈希查找(数组) */
function hashingSearch(map, target) {
// 哈希表的 key: 目标元素value: 索引
// 若哈希表中无此 key ,返回 -1
return map.has(target) ? map.get(target) : -1;
}
/* 哈希查找(链表) */
function hashingSearch1(map, target) {
// 哈希表的 key: 目标结点值value: 结点对象
// 若哈希表中无此 key ,返回 null
return map.has(target) ? map.get(target) : null;
}
function main() {
const target = 3;
/* 哈希查找(数组) */
const nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8];
// 初始化哈希表
const map = new Map();
for (let i = 0; i < nums.length; i++) {
map.set(nums[i], i); // key: 元素value: 索引
}
const index = hashingSearch(map, target);
console.log("目标元素 3 的索引 = " + index);
/* 哈希查找(链表) */
let head = new ListNode().arrToLinkedList(nums)
// 初始化哈希表
const map1 = new Map();
while (head != null) {
map1.set(head.val, head); // key: 结点值value: 结点
head = head.next;
}
const node = hashingSearch1(map1, target);
console.log("目标结点值 3 的对应结点对象为" );
PrintUtil.printLinkedList(node);
}
main();

View file

@ -11,10 +11,10 @@ function bubbleSort(nums) {
// 内循环:冒泡操作 // 内循环:冒泡操作
for (let j = 0; j < i; j++) { for (let j = 0; j < i; j++) {
if (nums[j] > nums[j + 1]) { if (nums[j] > nums[j + 1]) {
// 交换 nums[j] 与 nums[j + 1] // 交换 nums[j] 与 nums[j + 1]
let tmp = nums[j]; let tmp = nums[j];
nums[j] = nums[j + 1]; nums[j] = nums[j + 1];
nums[j + 1] = tmp; nums[j + 1] = tmp;
} }
} }
} }
@ -40,10 +40,10 @@ function bubbleSortWithFlag(nums) {
} }
/* Driver Code */ /* Driver Code */
var nums = [4, 1, 3, 1, 5, 2] const nums = [4, 1, 3, 1, 5, 2];
bubbleSort(nums) bubbleSort(nums);
console.log("排序后数组 nums =", nums) console.log("排序后数组 nums =", nums);
var nums1 = [4, 1, 3, 1, 5, 2] const nums1 = [4, 1, 3, 1, 5, 2];
bubbleSortWithFlag(nums1) bubbleSortWithFlag(nums1);
console.log("排序后数组 nums =", nums1) console.log("排序后数组 nums =", nums1);

View file

@ -19,6 +19,6 @@ function insertionSort(nums) {
} }
/* Driver Code */ /* Driver Code */
var nums = [4, 1, 3, 1, 5, 2] const nums = [4, 1, 3, 1, 5, 2];
insertionSort(nums) insertionSort(nums);
console.log("排序后数组 nums =", nums) console.log('排序后数组 nums =', nums);

View file

@ -5,10 +5,10 @@
*/ */
/** /**
* 合并左子数组和右子数组 * 合并左子数组和右子数组
* 左子数组区间 [left, mid] * 左子数组区间 [left, mid]
* 右子数组区间 [mid + 1, right] * 右子数组区间 [mid + 1, right]
*/ */
function merge(nums, left, mid, right) { function merge(nums, left, mid, right) {
// 初始化辅助数组 // 初始化辅助数组
let tmp = nums.slice(left, right + 1); let tmp = nums.slice(left, right + 1);
@ -46,6 +46,6 @@ function mergeSort(nums, left, right) {
} }
/* Driver Code */ /* Driver Code */
var nums = [ 7, 3, 2, 6, 0, 1, 5, 4 ] const nums = [ 7, 3, 2, 6, 0, 1, 5, 4 ]
mergeSort(nums, 0, nums.length - 1) mergeSort(nums, 0, nums.length - 1)
console.log("归并排序完成后 nums =", nums) console.log('归并排序完成后 nums =', nums)

View file

@ -8,38 +8,38 @@
class QuickSort { class QuickSort {
/* 元素交换 */ /* 元素交换 */
swap(nums, i, j) { swap(nums, i, j) {
let tmp = nums[i] let tmp = nums[i];
nums[i] = nums[j] nums[i] = nums[j];
nums[j] = tmp nums[j] = tmp;
} }
/* 哨兵划分 */ /* 哨兵划分 */
partition(nums, left, right){ partition(nums, left, right) {
// 以 nums[left] 作为基准数 // 以 nums[left] 作为基准数
let i = left, j = right let i = left, j = right;
while(i < j){ while (i < j) {
while(i < j && nums[j] >= nums[left]){ while (i < j && nums[j] >= nums[left]) {
j -= 1 // 从右向左找首个小于基准数的元素 j -= 1; // 从右向左找首个小于基准数的元素
} }
while(i < j && nums[i] <= nums[left]){ while (i < j && nums[i] <= nums[left]) {
i += 1 // 从左向右找首个大于基准数的元素 i += 1; // 从左向右找首个大于基准数的元素
} }
// 元素交换 // 元素交换
this.swap(nums, i, j) // 交换这两个元素 this.swap(nums, i, j); // 交换这两个元素
} }
this.swap(nums, i, left) // 将基准数交换至两子数组的分界线 this.swap(nums, i, left); // 将基准数交换至两子数组的分界线
return i // 返回基准数的索引 return i; // 返回基准数的索引
} }
/* 快速排序 */ /* 快速排序 */
quickSort(nums, left, right){ quickSort(nums, left, right) {
// 子数组长度为 1 时终止递归 // 子数组长度为 1 时终止递归
if(left >= right) return if (left >= right) return;
// 哨兵划分 // 哨兵划分
const pivot = this.partition(nums, left, right) const pivot = this.partition(nums, left, right);
// 递归左子数组、右子数组 // 递归左子数组、右子数组
this.quickSort(nums, left, pivot - 1) this.quickSort(nums, left, pivot - 1);
this.quickSort(nums, pivot + 1, right) this.quickSort(nums, pivot + 1, right);
} }
} }
@ -47,21 +47,18 @@ class QuickSort {
class QuickSortMedian { class QuickSortMedian {
/* 元素交换 */ /* 元素交换 */
swap(nums, i, j) { swap(nums, i, j) {
let tmp = nums[i] let tmp = nums[i];
nums[i] = nums[j] nums[i] = nums[j];
nums[j] = tmp nums[j] = tmp;
} }
/* 选取三个元素的中位数 */ /* 选取三个元素的中位数 */
medianThree(nums, left, mid, right) { medianThree(nums, left, mid, right) {
// 使用了异或操作来简化代码 // 使用了异或操作来简化代码
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1 // 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
if ((nums[left] > nums[mid]) ^ (nums[left] > nums[right])) if ((nums[left] > nums[mid]) ^ (nums[left] > nums[right])) return left;
return left; else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right])) return mid;
else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right])) else return right;
return mid;
else
return right;
} }
/* 哨兵划分(三数取中值) */ /* 哨兵划分(三数取中值) */
@ -73,14 +70,12 @@ class QuickSortMedian {
// 以 nums[left] 作为基准数 // 以 nums[left] 作为基准数
let i = left, j = right; let i = left, j = right;
while (i < j) { while (i < j) {
while (i < j && nums[j] >= nums[left]) while (i < j && nums[j] >= nums[left]) j--; // 从右向左找首个小于基准数的元素
j--; // 从右向左找首个小于基准数的元素 while (i < j && nums[i] <= nums[left]) i++; // 从左向右找首个大于基准数的元素
while (i < j && nums[i] <= nums[left])
i++; // 从左向右找首个大于基准数的元素
this.swap(nums, i, j); // 交换这两个元素 this.swap(nums, i, j); // 交换这两个元素
} }
this.swap(nums, i, left); // 将基准数交换至两子数组的分界线 this.swap(nums, i, left); // 将基准数交换至两子数组的分界线
return i; // 返回基准数的索引 return i; // 返回基准数的索引
} }
/* 快速排序 */ /* 快速排序 */
@ -99,9 +94,9 @@ class QuickSortMedian {
class QuickSortTailCall { class QuickSortTailCall {
/* 元素交换 */ /* 元素交换 */
swap(nums, i, j) { swap(nums, i, j) {
let tmp = nums[i] let tmp = nums[i];
nums[i] = nums[j] nums[i] = nums[j];
nums[j] = tmp nums[j] = tmp;
} }
/* 哨兵划分 */ /* 哨兵划分 */
@ -109,13 +104,11 @@ class QuickSortTailCall {
// 以 nums[left] 作为基准数 // 以 nums[left] 作为基准数
let i = left, j = right; let i = left, j = right;
while (i < j) { while (i < j) {
while (i < j && nums[j] >= nums[left]) while (i < j && nums[j] >= nums[left]) j--; // 从右向左找首个小于基准数的元素
j--; // 从右向左找首个小于基准数的元素 while (i < j && nums[i] <= nums[left]) i++; // 从左向右找首个大于基准数的元素
while (i < j && nums[i] <= nums[left])
i++; // 从左向右找首个大于基准数的元素
this.swap(nums, i, j); // 交换这两个元素 this.swap(nums, i, j); // 交换这两个元素
} }
this.swap(nums, i, left); // 将基准数交换至两子数组的分界线 this.swap(nums, i, left); // 将基准数交换至两子数组的分界线
return i; // 返回基准数的索引 return i; // 返回基准数的索引
} }
@ -127,8 +120,8 @@ class QuickSortTailCall {
let pivot = this.partition(nums, left, right); let pivot = this.partition(nums, left, right);
// 对两个子数组中较短的那个执行快排 // 对两个子数组中较短的那个执行快排
if (pivot - left < right - pivot) { if (pivot - left < right - pivot) {
this.quickSort(nums, left, pivot - 1); // 递归排序左子数组 this.quickSort(nums, left, pivot - 1); // 递归排序左子数组
left = pivot + 1; // 剩余待排序区间为 [pivot + 1, right] left = pivot + 1; // 剩余待排序区间为 [pivot + 1, right]
} else { } else {
this.quickSort(nums, pivot + 1, right); // 递归排序右子数组 this.quickSort(nums, pivot + 1, right); // 递归排序右子数组
right = pivot - 1; // 剩余待排序区间为 [left, pivot - 1] right = pivot - 1; // 剩余待排序区间为 [left, pivot - 1]
@ -139,19 +132,19 @@ class QuickSortTailCall {
/* Driver Code */ /* Driver Code */
/* 快速排序 */ /* 快速排序 */
var nums = [4, 1, 3, 1, 5, 2] const nums = [4, 1, 3, 1, 5, 2];
var quickSort = new QuickSort() const quickSort = new QuickSort();
quickSort.quickSort(nums, 0, nums.length - 1) quickSort.quickSort(nums, 0, nums.length - 1);
console.log("快速排序完成后 nums =", nums) console.log('快速排序完成后 nums =', nums);
/* 快速排序(中位基准数优化) */ /* 快速排序(中位基准数优化) */
nums1 = [4, 1, 3, 1, 5,2] const nums1 = [4, 1, 3, 1, 5, 2];
var quickSortMedian = new QuickSort() const quickSortMedian = new QuickSort();
quickSortMedian.quickSort(nums1, 0, nums1.length - 1) quickSortMedian.quickSort(nums1, 0, nums1.length - 1);
console.log("快速排序(中位基准数优化)完成后 nums =", nums1) console.log('快速排序(中位基准数优化)完成后 nums =', nums1);
/* 快速排序(尾递归优化) */ /* 快速排序(尾递归优化) */
nums2 = [4, 1, 3, 1, 5, 2] const nums2 = [4, 1, 3, 1, 5, 2];
var quickSortTailCall = new QuickSort() const quickSortTailCall = new QuickSort();
quickSortTailCall.quickSort(nums2, 0, nums2.length - 1) quickSortTailCall.quickSort(nums2, 0, nums2.length - 1);
console.log("快速排序(尾递归优化)完成后 nums =", nums2) console.log('快速排序(尾递归优化)完成后 nums =', nums2);

View file

@ -13,6 +13,13 @@ let package = Package(
.executable(name: "linked_list", targets: ["linked_list"]), .executable(name: "linked_list", targets: ["linked_list"]),
.executable(name: "list", targets: ["list"]), .executable(name: "list", targets: ["list"]),
.executable(name: "my_list", targets: ["my_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"]),
.executable(name: "queue", targets: ["queue"]),
.executable(name: "linkedlist_queue", targets: ["linkedlist_queue"]),
.executable(name: "array_queue", targets: ["array_queue"]),
.executable(name: "deque", targets: ["deque"]),
], ],
targets: [ targets: [
.target(name: "utils", path: "utils"), .target(name: "utils", path: "utils"),
@ -24,5 +31,12 @@ let package = Package(
.executableTarget(name: "linked_list", dependencies: ["utils"], path: "chapter_array_and_linkedlist", sources: ["linked_list.swift"]), .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: "list", path: "chapter_array_and_linkedlist", sources: ["list.swift"]),
.executableTarget(name: "my_list", path: "chapter_array_and_linkedlist", sources: ["my_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"]),
.executableTarget(name: "queue", path: "chapter_stack_and_queue", sources: ["queue.swift"]),
.executableTarget(name: "linkedlist_queue", dependencies: ["utils"], path: "chapter_stack_and_queue", sources: ["linkedlist_queue.swift"]),
.executableTarget(name: "array_queue", path: "chapter_stack_and_queue", sources: ["array_queue.swift"]),
.executableTarget(name: "deque", path: "chapter_stack_and_queue", sources: ["deque.swift"]),
] ]
) )

View file

@ -0,0 +1,116 @@
/**
* File: array_queue.swift
* Created Time: 2023-01-11
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
class ArrayQueue {
private var nums: [Int] //
private var front = 0 //
private var rear = 0 // + 1
init(capacity: Int) {
//
nums = Array(repeating: 0, count: capacity)
}
/* */
func capacity() -> Int {
nums.count
}
/* */
func size() -> Int {
let capacity = capacity()
// rear < front
return (capacity + rear - front) % capacity
}
/* */
func isEmpty() -> Bool {
rear - front == 0
}
/* */
func offer(num: Int) {
if size() == capacity() {
print("队列已满")
return
}
// num
nums[rear] = num
//
rear = (rear + 1) % capacity()
}
/* */
@discardableResult
func poll() -> Int {
let num = peek()
//
front = (front + 1) % capacity()
return num
}
/* 访 */
func peek() -> Int {
if isEmpty() {
fatalError("队列为空")
}
return nums[front]
}
/* */
func toArray() -> [Int] {
let size = size()
let capacity = capacity()
//
var res = Array(repeating: 0, count: size)
for (i, j) in sequence(first: (0, front), next: { $0 < size - 1 ? ($0 + 1, $1 + 1) : nil }) {
res[i] = nums[j % capacity]
}
return res
}
}
@main
enum _ArrayQueue {
/* Driver Code */
static func main() {
/* */
let capacity = 10
let queue = ArrayQueue(capacity: capacity)
/* */
queue.offer(num: 1)
queue.offer(num: 3)
queue.offer(num: 2)
queue.offer(num: 5)
queue.offer(num: 4)
print("队列 queue = \(queue.toArray())")
/* 访 */
let peek = queue.peek()
print("队首元素 peek = \(peek)")
/* */
let poll = queue.poll()
print("出队元素 poll = \(poll),出队后 queue = \(queue.toArray())")
/* */
let size = queue.size()
print("队列长度 size = \(size)")
/* */
let isEmpty = queue.isEmpty()
print("队列是否为空 = \(isEmpty)")
/* */
for i in 0 ..< 10 {
queue.offer(num: i)
queue.poll()
print("\(i) 轮入队 + 出队后 queue = \(queue.toArray())")
}
}
}

View file

@ -0,0 +1,85 @@
/**
* 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)
}
/* */
@discardableResult
func pop() -> Int {
if isEmpty() {
fatalError("栈为空")
}
return stack.removeLast()
}
/* 访 */
func peek() -> Int {
if 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)")
}
}

View file

@ -0,0 +1,44 @@
/**
* File: deque.swift
* Created Time: 2023-01-14
* Author: nuomi1 (nuomi1@qq.com)
*/
@main
enum Deque {
/* Driver Code */
static func main() {
/* */
// Swift Array 使
var deque: [Int] = []
/* */
deque.append(2)
deque.append(5)
deque.append(4)
deque.insert(3, at: 0)
deque.insert(1, at: 0)
print("双向队列 deque = \(deque)")
/* 访 */
let peekFirst = deque.first!
print("队首元素 peekFirst = \(peekFirst)")
let peekLast = deque.last!
print("队尾元素 peekLast = \(peekLast)")
/* */
// 使 Array pollFirst O(n)
let pollFirst = deque.removeFirst()
print("队首出队元素 pollFirst = \(pollFirst),队首出队后 deque = \(deque)")
let pollLast = deque.removeLast()
print("队尾出队元素 pollLast = \(pollLast),队尾出队后 deque = \(deque)")
/* */
let size = deque.count
print("双向队列长度 size = \(size)")
/* */
let isEmpty = deque.isEmpty
print("双向队列是否为空 = \(isEmpty)")
}
}

View file

@ -0,0 +1,105 @@
/**
* File: linkedlist_queue.swift
* Created Time: 2023-01-11
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* */
class LinkedListQueue {
private var front: ListNode? //
private var rear: ListNode? //
private var _size = 0
init() {}
/* */
func size() -> Int {
_size
}
/* */
func isEmpty() -> Bool {
size() == 0
}
/* */
func offer(num: Int) {
// num
let node = ListNode(x: num)
//
if front == nil {
front = node
rear = node
}
//
else {
rear?.next = node
rear = node
}
_size += 1
}
/* */
@discardableResult
func poll() -> Int {
let num = peek()
//
front = front?.next
_size -= 1
return num
}
/* 访 */
func peek() -> Int {
if isEmpty() {
fatalError("队列为空")
}
return front!.val
}
/* Array */
func toArray() -> [Int] {
var node = front
var res = Array(repeating: 0, count: size())
for i in res.indices {
res[i] = node!.val
node = node?.next
}
return res
}
}
@main
enum _LinkedListQueue {
/* Driver Code */
static func main() {
/* */
let queue = LinkedListQueue()
/* */
queue.offer(num: 1)
queue.offer(num: 3)
queue.offer(num: 2)
queue.offer(num: 5)
queue.offer(num: 4)
print("队列 queue = \(queue.toArray())")
/* 访 */
let peek = queue.peek()
print("队首元素 peek = \(peek)")
/* */
let poll = queue.poll()
print("出队元素 poll = \(poll),出队后 queue = \(queue.toArray())")
/* */
let size = queue.size()
print("队列长度 size = \(size)")
/* */
let isEmpty = queue.isEmpty()
print("队列是否为空 = \(isEmpty)")
}
}

View file

@ -0,0 +1,94 @@
/**
* 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
}
/* */
@discardableResult
func pop() -> Int {
let num = peek()
_peek = _peek?.next
_size -= 1
return num
}
/* 访 */
func peek() -> Int {
if isEmpty() {
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)")
}
}

View file

@ -0,0 +1,40 @@
/**
* File: queue.swift
* Created Time: 2023-01-11
* Author: nuomi1 (nuomi1@qq.com)
*/
@main
enum Queue {
/* Driver Code */
static func main() {
/* */
// Swift Array 使
var queue: [Int] = []
/* */
queue.append(1)
queue.append(3)
queue.append(2)
queue.append(5)
queue.append(4)
print("队列 queue = \(queue)")
/* 访 */
let peek = queue.first!
print("队首元素 peek = \(peek)")
/* */
// 使 Array poll O(n)
let pool = queue.removeFirst()
print("出队元素 poll = \(pool),出队后 queue = \(queue)")
/* */
let size = queue.count
print("队列长度 size = \(size)")
/* */
let isEmpty = queue.isEmpty
print("队列是否为空 = \(isEmpty)")
}
}

View file

@ -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)")
}
}

View file

@ -0,0 +1,51 @@
/**
* File: hashing_search.js
* Created Time: 2022-12-29
* Author: Zhuo Qinyue (1403450829@qq.com)
*/
import { printLinkedList } from "../module/PrintUtil";
import ListNode from "../module/ListNode";
/* 哈希查找(数组) */
function hashingSearch(map: Map<number, number>, target: number): number {
// 哈希表的 key: 目标元素value: 索引
// 若哈希表中无此 key ,返回 -1
return map.has(target) ? map.get(target) as number : -1;
}
/* 哈希查找(链表) */
function hashingSearch1(map: Map<number, ListNode>, target: number): ListNode | null {
// 哈希表的 key: 目标结点值value: 结点对象
// 若哈希表中无此 key ,返回 null
return map.has(target) ? map.get(target) as ListNode : null;
}
function main() {
const target = 3;
/* 哈希查找(数组) */
const nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8];
// 初始化哈希表
const map = new Map();
for (let i = 0; i < nums.length; i++) {
map.set(nums[i], i); // key: 元素value: 索引
}
const index = hashingSearch(map, target);
console.log("目标元素 3 的索引 = " + index);
/* 哈希查找(链表) */
let head = new ListNode().arrToLinkedList(nums)
// 初始化哈希表
const map1 = new Map();
while (head != null) {
map1.set(head.val, head); // key: 结点值value: 结点
head = head.next;
}
const node = hashingSearch1(map1, target);
console.log("目标结点值 3 的对应结点对象为");
printLinkedList(node);
}
main();

View file

@ -0,0 +1,47 @@
/**
* File: linear_search.ts
* Created Time: 2023-01-07
* Author: Daniel (better.sunjian@gmail.com)
*/
import ListNode from '../module/ListNode.ts';
/* 线性查找(数组)*/
function linearSearchArray(nums: number[], target: number): number {
// 遍历数组
for (let i = 0; i < nums.length; i++) {
// 找到目标元素,返回其索引
if (nums[i] === target) {
return i;
}
}
// 未找到目标元素,返回 -1
return -1;
}
/* 线性查找(链表)*/
function linearSearchLinkedList(head: ListNode | null, target: number): ListNode | null {
// 遍历链表
while (head) {
// 找到目标结点,返回之
if (head.val === target) {
return head;
}
head = head.next;
}
// 未找到目标结点,返回 null
return null;
}
/* Driver Code */
const target = 3;
/* 在数组中执行线性查找 */
const nums = [ 1, 5, 3, 2, 4, 7, 5, 9, 10, 8 ];
const index = linearSearchArray(nums, target);
console.log('目标元素 3 的索引 =', index);
/* 在链表中执行线性查找 */
const head = ListNode.arrToLinkedList(nums);
const node = linearSearchLinkedList(head, target);
console.log('目标结点值 3 的对应结点对象为', node);

View file

@ -23,10 +23,10 @@ function merge(nums: number[], left: number, mid: number, right: number): void {
// 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++ // 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++
if (i > leftEnd) { if (i > leftEnd) {
nums[k] = tmp[j++]; nums[k] = tmp[j++];
// 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++ // 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++
} else if (j > rightEnd || tmp[i] <= tmp[j]) { } else if (j > rightEnd || tmp[i] <= tmp[j]) {
nums[k] = tmp[i++]; nums[k] = tmp[i++];
// 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++ // 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++
} else { } else {
nums[k] = tmp[j++]; nums[k] = tmp[j++];
} }

View file

@ -14,4 +14,19 @@ export default class ListNode {
this.val = val === undefined ? 0 : val; this.val = val === undefined ? 0 : val;
this.next = next === undefined ? null : next; this.next = next === undefined ? null : next;
} }
/**
* Generate a linked list with an array
* @param arr
* @return
*/
arrToLinkedList(arr: number[]): ListNode | null {
const dum: ListNode = new ListNode(0);
let head = dum;
for (const val of arr) {
head.next = new ListNode(val);
head = head.next;
}
return dum.next;
}
} }

View file

@ -1,46 +1,232 @@
// File: build.zig
// Created Time: 2023-01-07
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std"); const std = @import("std");
// zig version 0.10.0 // Zig Version: 0.10.0
// Build Command: zig build
pub fn build(b: *std.build.Builder) void { pub fn build(b: *std.build.Builder) void {
const target = b.standardTargetOptions(.{}); const target = b.standardTargetOptions(.{});
const mode = b.standardReleaseOptions(); const mode = b.standardReleaseOptions();
// "chapter_computational_complexity/time_complexity.zig" // Section: "Time Complexity"
// Run Command: zig build run_time_complexity // Source File: "chapter_computational_complexity/time_complexity.zig"
const exe_time_complexity = b.addExecutable("time_complexity", "chapter_computational_complexity/time_complexity.zig"); // Run Command: zig build run_time_complexity
exe_time_complexity.addPackagePath("include", "include/include.zig"); const exe_time_complexity = b.addExecutable("time_complexity", "chapter_computational_complexity/time_complexity.zig");
exe_time_complexity.setTarget(target); exe_time_complexity.addPackagePath("include", "include/include.zig");
exe_time_complexity.setBuildMode(mode); exe_time_complexity.setTarget(target);
exe_time_complexity.install(); exe_time_complexity.setBuildMode(mode);
const run_cmd_time_complexity = exe_time_complexity.run(); exe_time_complexity.install();
run_cmd_time_complexity.step.dependOn(b.getInstallStep()); const run_cmd_time_complexity = exe_time_complexity.run();
if (b.args) |args| run_cmd_time_complexity.addArgs(args); run_cmd_time_complexity.step.dependOn(b.getInstallStep());
const run_step_time_complexity = b.step("run_time_complexity", "Run time_complexity"); if (b.args) |args| run_cmd_time_complexity.addArgs(args);
run_step_time_complexity.dependOn(&run_cmd_time_complexity.step); const run_step_time_complexity = b.step("run_time_complexity", "Run time_complexity");
run_step_time_complexity.dependOn(&run_cmd_time_complexity.step);
// "chapter_computational_complexity/worst_best_time_complexity.zig" // Source File: "chapter_computational_complexity/worst_best_time_complexity.zig"
// Run Command: zig build run_worst_best_time_complexity // Run Command: zig build run_worst_best_time_complexity
const exe_worst_best_time_complexity = b.addExecutable("worst_best_time_complexity", "chapter_computational_complexity/worst_best_time_complexity.zig"); const exe_worst_best_time_complexity = b.addExecutable("worst_best_time_complexity", "chapter_computational_complexity/worst_best_time_complexity.zig");
exe_worst_best_time_complexity.addPackagePath("include", "include/include.zig"); exe_worst_best_time_complexity.addPackagePath("include", "include/include.zig");
exe_worst_best_time_complexity.setTarget(target); exe_worst_best_time_complexity.setTarget(target);
exe_worst_best_time_complexity.setBuildMode(mode); exe_worst_best_time_complexity.setBuildMode(mode);
exe_worst_best_time_complexity.install(); exe_worst_best_time_complexity.install();
const run_cmd_worst_best_time_complexity = exe_worst_best_time_complexity.run(); const run_cmd_worst_best_time_complexity = exe_worst_best_time_complexity.run();
run_cmd_worst_best_time_complexity.step.dependOn(b.getInstallStep()); run_cmd_worst_best_time_complexity.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_worst_best_time_complexity.addArgs(args); if (b.args) |args| run_cmd_worst_best_time_complexity.addArgs(args);
const run_step_worst_best_time_complexity = b.step("run_worst_best_time_complexity", "Run worst_best_time_complexity"); const run_step_worst_best_time_complexity = b.step("run_worst_best_time_complexity", "Run worst_best_time_complexity");
run_step_worst_best_time_complexity.dependOn(&run_cmd_worst_best_time_complexity.step); run_step_worst_best_time_complexity.dependOn(&run_cmd_worst_best_time_complexity.step);
// "chapter_computational_complexity/leetcode_two_sum.zig" // Section: "Space Complexity"
// Run Command: zig build run_leetcode_two_sum // Source File: "chapter_computational_complexity/space_complexity.zig"
const exe_leetcode_two_sum = b.addExecutable("leetcode_two_sum", "chapter_computational_complexity/leetcode_two_sum.zig"); // Run Command: zig build run_space_complexity
exe_leetcode_two_sum.addPackagePath("include", "include/include.zig"); const exe_space_complexity = b.addExecutable("space_complexity", "chapter_computational_complexity/space_complexity.zig");
exe_leetcode_two_sum.setTarget(target); exe_space_complexity.addPackagePath("include", "include/include.zig");
exe_leetcode_two_sum.setBuildMode(mode); exe_space_complexity.setTarget(target);
exe_leetcode_two_sum.install(); exe_space_complexity.setBuildMode(mode);
const run_cmd_leetcode_two_sum = exe_leetcode_two_sum.run(); exe_space_complexity.install();
run_cmd_leetcode_two_sum.step.dependOn(b.getInstallStep()); const run_cmd_space_complexity = exe_space_complexity.run();
if (b.args) |args| run_cmd_leetcode_two_sum.addArgs(args); run_cmd_space_complexity.step.dependOn(b.getInstallStep());
const run_step_leetcode_two_sum = b.step("run_leetcode_two_sum", "Run leetcode_two_sum"); if (b.args) |args| run_cmd_space_complexity.addArgs(args);
run_step_leetcode_two_sum.dependOn(&run_cmd_leetcode_two_sum.step); const run_step_space_complexity = b.step("run_space_complexity", "Run space_complexity");
run_step_space_complexity.dependOn(&run_cmd_space_complexity.step);
// Section: "Space Time Tradeoff"
// Source File: "chapter_computational_complexity/leetcode_two_sum.zig"
// Run Command: zig build run_leetcode_two_sum
const exe_leetcode_two_sum = b.addExecutable("leetcode_two_sum", "chapter_computational_complexity/leetcode_two_sum.zig");
exe_leetcode_two_sum.addPackagePath("include", "include/include.zig");
exe_leetcode_two_sum.setTarget(target);
exe_leetcode_two_sum.setBuildMode(mode);
exe_leetcode_two_sum.install();
const run_cmd_leetcode_two_sum = exe_leetcode_two_sum.run();
run_cmd_leetcode_two_sum.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_leetcode_two_sum.addArgs(args);
const run_step_leetcode_two_sum = b.step("run_leetcode_two_sum", "Run leetcode_two_sum");
run_step_leetcode_two_sum.dependOn(&run_cmd_leetcode_two_sum.step);
// Section: "Array"
// Source File: "chapter_array_and_linkedlist/array.zig"
// Run Command: zig build run_array
const exe_array = b.addExecutable("array", "chapter_array_and_linkedlist/array.zig");
exe_array.addPackagePath("include", "include/include.zig");
exe_array.setTarget(target);
exe_array.setBuildMode(mode);
exe_array.install();
const run_cmd_array = exe_array.run();
run_cmd_array.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_array.addArgs(args);
const run_step_array = b.step("run_array", "Run array");
run_step_array.dependOn(&run_cmd_array.step);
// Section: "LinkedList"
// Source File: "chapter_array_and_linkedlist/linked_list.zig"
// Run Command: zig build run_linked_list
const exe_linked_list = b.addExecutable("linked_list", "chapter_array_and_linkedlist/linked_list.zig");
exe_linked_list.addPackagePath("include", "include/include.zig");
exe_linked_list.setTarget(target);
exe_linked_list.setBuildMode(mode);
exe_linked_list.install();
const run_cmd_linked_list = exe_linked_list.run();
run_cmd_linked_list.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_linked_list.addArgs(args);
const run_step_linked_list = b.step("run_linked_list", "Run linked_list");
run_step_linked_list.dependOn(&run_cmd_linked_list.step);
// Section: "List"
// Source File: "chapter_array_and_linkedlist/list.zig"
// Run Command: zig build run_list
const exe_list = b.addExecutable("list", "chapter_array_and_linkedlist/list.zig");
exe_list.addPackagePath("include", "include/include.zig");
exe_list.setTarget(target);
exe_list.setBuildMode(mode);
exe_list.install();
const run_cmd_list = exe_list.run();
run_cmd_list.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_list.addArgs(args);
const run_step_list = b.step("run_list", "Run list");
run_step_list.dependOn(&run_cmd_list.step);
// Source File: "chapter_array_and_linkedlist/my_list.zig"
// Run Command: zig build run_my_list
const exe_my_list = b.addExecutable("my_list", "chapter_array_and_linkedlist/my_list.zig");
exe_my_list.addPackagePath("include", "include/include.zig");
exe_my_list.setTarget(target);
exe_my_list.setBuildMode(mode);
exe_my_list.install();
const run_cmd_my_list = exe_my_list.run();
run_cmd_my_list.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_my_list.addArgs(args);
const run_step_my_list = b.step("run_my_list", "Run my_list");
run_step_my_list.dependOn(&run_cmd_my_list.step);
// Section: "Stack"
// Source File: "chapter_stack_and_queue/stack.zig"
// Run Command: zig build run_stack
const exe_stack = b.addExecutable("stack", "chapter_stack_and_queue/stack.zig");
exe_stack.addPackagePath("include", "include/include.zig");
exe_stack.setTarget(target);
exe_stack.setBuildMode(mode);
exe_stack.install();
const run_cmd_stack = exe_stack.run();
run_cmd_stack.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_stack.addArgs(args);
const run_step_stack = b.step("run_stack", "Run stack");
run_step_stack.dependOn(&run_cmd_stack.step);
// Source File: "chapter_stack_and_queue/linkedlist_stack.zig"
// Run Command: zig build run_linkedlist_stack
const exe_linkedlist_stack = b.addExecutable("linkedlist_stack", "chapter_stack_and_queue/linkedlist_stack.zig");
exe_linkedlist_stack.addPackagePath("include", "include/include.zig");
exe_linkedlist_stack.setTarget(target);
exe_linkedlist_stack.setBuildMode(mode);
exe_linkedlist_stack.install();
const run_cmd_linkedlist_stack = exe_linkedlist_stack.run();
run_cmd_linkedlist_stack.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_linkedlist_stack.addArgs(args);
const run_step_linkedlist_stack = b.step("run_linkedlist_stack", "Run linkedlist_stack");
run_step_linkedlist_stack.dependOn(&run_cmd_linkedlist_stack.step);
// Source File: "chapter_stack_and_queue/array_stack.zig"
// Run Command: zig build run_array_stack
const exe_array_stack = b.addExecutable("array_stack", "chapter_stack_and_queue/array_stack.zig");
exe_array_stack.addPackagePath("include", "include/include.zig");
exe_array_stack.setTarget(target);
exe_array_stack.setBuildMode(mode);
exe_array_stack.install();
const run_cmd_array_stack = exe_linkedlist_stack.run();
run_cmd_array_stack.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_array_stack.addArgs(args);
const run_step_array_stack = b.step("run_array_stack", "Run array_stack");
run_step_array_stack.dependOn(&run_cmd_array_stack.step);
// Section: "Hash Map"
// Source File: "chapter_hashing/hash_map.zig"
// Run Command: zig build run_hash_map
const exe_hash_map = b.addExecutable("hash_map", "chapter_hashing/hash_map.zig");
exe_hash_map.addPackagePath("include", "include/include.zig");
exe_hash_map.setTarget(target);
exe_hash_map.setBuildMode(mode);
exe_hash_map.install();
const run_cmd_hash_map = exe_hash_map.run();
run_cmd_hash_map.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_hash_map.addArgs(args);
const run_step_hash_map= b.step("run_hash_map", "Run hash_map");
run_step_hash_map.dependOn(&run_cmd_hash_map.step);
// Section: "Binary Tree"
// Source File: "chapter_tree/binary_tree.zig"
// Run Command: zig build run_binary_tree
const exe_binary_tree = b.addExecutable("hash_map", "chapter_tree/binary_tree.zig");
exe_binary_tree.addPackagePath("include", "include/include.zig");
exe_binary_tree.setTarget(target);
exe_binary_tree.setBuildMode(mode);
exe_binary_tree.install();
const run_cmd_binary_tree = exe_binary_tree.run();
run_cmd_binary_tree.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_binary_tree.addArgs(args);
const run_step_binary_tree= b.step("run_binary_tree", "Run binary_tree");
run_step_binary_tree.dependOn(&run_cmd_binary_tree.step);
// Section: "Linear Search"
// Source File: "chapter_searching/linear_search.zig"
// Run Command: zig build run_linear_search
const exe_linear_search = b.addExecutable("linear_search", "chapter_searching/linear_search.zig");
exe_linear_search.addPackagePath("include", "include/include.zig");
exe_linear_search.setTarget(target);
exe_linear_search.setBuildMode(mode);
exe_linear_search.install();
const run_cmd_linear_search = exe_linear_search.run();
run_cmd_linear_search.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_linear_search.addArgs(args);
const run_step_linear_search= b.step("run_linear_search", "Run linear_search");
run_step_linear_search.dependOn(&run_cmd_linear_search.step);
// Section: "Bubble Sort"
// Source File: "chapter_sorting/bubble_sort.zig"
// Run Command: zig build run_bubble_sort
const exe_bubble_sort = b.addExecutable("bubble_sort", "chapter_sorting/bubble_sort.zig");
exe_bubble_sort.addPackagePath("include", "include/include.zig");
exe_bubble_sort.setTarget(target);
exe_bubble_sort.setBuildMode(mode);
exe_bubble_sort.install();
const run_cmd_bubble_sort = exe_bubble_sort.run();
run_cmd_bubble_sort.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_bubble_sort.addArgs(args);
const run_step_bubble_sort = b.step("run_bubble_sort", "Run bubble_sort");
run_step_bubble_sort.dependOn(&run_cmd_bubble_sort.step);
// Section: "Insertion Sort"
// Source File: "chapter_sorting/insertion_sort.zig"
// Run Command: zig build run_insertion_sort
const exe_insertion_sort = b.addExecutable("insertion_sort", "chapter_sorting/insertion_sort.zig");
exe_insertion_sort.addPackagePath("include", "include/include.zig");
exe_insertion_sort.setTarget(target);
exe_insertion_sort.setBuildMode(mode);
exe_insertion_sort.install();
const run_cmd_insertion_sort = exe_insertion_sort.run();
run_cmd_insertion_sort.step.dependOn(b.getInstallStep());
if (b.args) |args| run_cmd_insertion_sort.addArgs(args);
const run_step_insertion_sort = b.step("run_insertion_sort", "Run insertion_sort");
run_step_insertion_sort.dependOn(&run_cmd_insertion_sort.step);
} }

View file

@ -0,0 +1,117 @@
// File: array.zig
// Created Time: 2023-01-07
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const inc = @import("include");
//
pub fn randomAccess(nums: []i32) i32 {
// [0, nums.len)
var randomIndex = std.crypto.random.intRangeLessThan(usize, 0, nums.len);
//
var randomNum = nums[randomIndex];
return randomNum;
}
//
pub fn extend(mem_allocator: std.mem.Allocator, nums: []i32, enlarge: usize) ![]i32 {
//
var res = try mem_allocator.alloc(i32, nums.len + enlarge);
std.mem.set(i32, res, 0);
//
std.mem.copy(i32, res, nums);
//
return res;
}
// index num
pub fn insert(nums: []i32, num: i32, index: usize) void {
// index
var i = nums.len - 1;
while (i > index) : (i -= 1) {
nums[i] = nums[i - 1];
}
// num index
nums[index] = num;
}
// index
pub fn remove(nums: []i32, index: usize) void {
// index
var i = index;
while (i < nums.len - 1) : (i += 1) {
nums[i] = nums[i + 1];
}
}
//
pub fn traverse(nums: []i32) void {
var count: i32 = 0;
//
var i: i32 = 0;
while (i < nums.len) : (i += 1) {
count += 1;
}
count = 0;
//
for (nums) |_| {
count += 1;
}
}
//
pub fn find(nums: []i32, target: i32) i32 {
for (nums) |num, i| {
if (num == target) return @intCast(i32, i);
}
return -1;
}
// Driver Code
pub fn main() !void {
//
const size: i32 = 5;
var arr = [_]i32{0} ** size;
std.debug.print("数组 arr = ", .{});
inc.PrintUtil.printArray(i32, &arr);
var array = [_]i32{ 1, 3, 2, 5, 4 };
std.debug.print("\n数组 nums = ", .{});
inc.PrintUtil.printArray(i32, &array);
// 访
var randomNum = randomAccess(&array);
std.debug.print("\n在 nums 中获取随机元素 {}", .{randomNum});
//
var known_at_runtime_zero: usize = 0;
var nums: []i32 = array[known_at_runtime_zero..array.len];
var mem_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer mem_arena.deinit();
const mem_allocator = mem_arena.allocator();
nums = try extend(mem_allocator, nums, 3);
std.debug.print("\n将数组长度扩展至 8 ,得到 nums = ", .{});
inc.PrintUtil.printArray(i32, nums);
//
insert(nums, 6, 3);
std.debug.print("\n在索引 3 处插入数字 6 ,得到 nums = ", .{});
inc.PrintUtil.printArray(i32, nums);
//
remove(nums, 2);
std.debug.print("\n删除索引 2 处的元素,得到 nums = ", .{});
inc.PrintUtil.printArray(i32, nums);
//
traverse(nums);
//
var index = find(nums, 3);
std.debug.print("\n在 nums 中查找元素 3 ,得到索引 = {}\n", .{index});
const getchar = try std.io.getStdIn().reader().readByte();
_ = getchar;
}

View file

@ -0,0 +1,85 @@
// File: linked_list.zig
// Created Time: 2023-01-07
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const inc = @import("include");
// n0 P
pub fn insert(n0: ?*inc.ListNode(i32), P: ?*inc.ListNode(i32)) void {
var n1 = n0.?.next;
n0.?.next = P;
P.?.next = n1;
}
// n0
pub fn remove(n0: ?*inc.ListNode(i32)) void {
if (n0.?.next == null) return;
// n0 -> P -> n1
var P = n0.?.next;
var n1 = P.?.next;
n0.?.next = n1;
}
// 访 index
pub fn access(node: ?*inc.ListNode(i32), index: i32) ?*inc.ListNode(i32) {
var head = node;
var i: i32 = 0;
while (i < index) : (i += 1) {
head = head.?.next;
if (head == null) return null;
}
return head;
}
// target
pub fn find(node: ?*inc.ListNode(i32), target: i32) i32 {
var head = node;
var index: i32 = 0;
while (head != null) {
if (head.?.val == target) return index;
head = head.?.next;
index += 1;
}
return -1;
}
// Driver Code
pub fn main() !void {
//
//
var n0 = inc.ListNode(i32){.val = 1};
var n1 = inc.ListNode(i32){.val = 3};
var n2 = inc.ListNode(i32){.val = 2};
var n3 = inc.ListNode(i32){.val = 5};
var n4 = inc.ListNode(i32){.val = 4};
//
n0.next = &n1;
n1.next = &n2;
n2.next = &n3;
n3.next = &n4;
std.debug.print("初始化的链表为", .{});
try inc.PrintUtil.printLinkedList(i32, &n0);
//
var tmp = inc.ListNode(i32){.val = 0};
insert(&n0, &tmp);
std.debug.print("插入结点后的链表为", .{});
try inc.PrintUtil.printLinkedList(i32, &n0);
//
remove(&n0);
std.debug.print("删除结点后的链表为", .{});
try inc.PrintUtil.printLinkedList(i32, &n0);
// 访
var node = access(&n0, 3);
std.debug.print("链表中索引 3 处的结点的值 = {}\n", .{node.?.val});
//
var index = find(&n0, 2);
std.debug.print("链表中值为 2 的结点的索引 = {}\n", .{index});
const getchar = try std.io.getStdIn().reader().readByte();
_ = getchar;
}

View file

@ -0,0 +1,81 @@
// File: list.zig
// Created Time: 2023-01-07
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const inc = @import("include");
// Driver Code
pub fn main() !void {
//
var list = std.ArrayList(i32).init(std.heap.page_allocator);
//
defer list.deinit();
try list.appendSlice(&[_]i32{ 1, 3, 2, 5, 4 });
std.debug.print("列表 list = ", .{});
inc.PrintUtil.printList(i32, list);
// 访
var num = list.items[1];
std.debug.print("\n访问索引 1 处的元素,得到 num = {}", .{num});
//
list.items[1] = 0;
std.debug.print("\n将索引 1 处的元素更新为 0 ,得到 list = ", .{});
inc.PrintUtil.printList(i32, list);
//
list.clearRetainingCapacity();
std.debug.print("\n清空列表后 list = ", .{});
inc.PrintUtil.printList(i32, list);
//
try list.append(1);
try list.append(3);
try list.append(2);
try list.append(5);
try list.append(4);
std.debug.print("\n添加元素后 list = ", .{});
inc.PrintUtil.printList(i32, list);
//
try list.insert(3, 6);
std.debug.print("\n在索引 3 处插入数字 6 ,得到 list = ", .{});
inc.PrintUtil.printList(i32, list);
//
var value = list.orderedRemove(3);
_ = value;
std.debug.print("\n删除索引 3 处的元素,得到 list = ", .{});
inc.PrintUtil.printList(i32, list);
//
var count: i32 = 0;
var i: i32 = 0;
while (i < list.items.len) : (i += 1) {
count += 1;
}
//
count = 0;
for (list.items) |_| {
count += 1;
}
//
var list1 = std.ArrayList(i32).init(std.heap.page_allocator);
defer list1.deinit();
try list1.appendSlice(&[_]i32{ 6, 8, 7, 10, 9 });
try list.insertSlice(list.items.len, list1.items);
std.debug.print("\n将列表 list1 拼接到 list 之后,得到 list = ", .{});
inc.PrintUtil.printList(i32, list);
//
std.sort.sort(i32, list.items, {}, comptime std.sort.asc(i32));
std.debug.print("\n排序列表后 list = ", .{});
inc.PrintUtil.printList(i32, list);
const getchar = try std.io.getStdIn().reader().readByte();
_ = getchar;
}

View file

@ -0,0 +1,177 @@
// File: my_list.zig
// Created Time: 2023-01-08
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const inc = @import("include");
//
//
pub fn MyList(comptime T: type) type {
return struct {
const Self = @This();
nums: []T = undefined, //
numsCapacity: usize = 10, //
numSize: usize = 0, //
extendRatio: usize = 2, //
mem_arena: ?std.heap.ArenaAllocator = null,
mem_allocator: std.mem.Allocator = undefined, //
// +
pub fn init(self: *Self, allocator: std.mem.Allocator) !void {
if (self.mem_arena == null) {
self.mem_arena = std.heap.ArenaAllocator.init(allocator);
self.mem_allocator = self.mem_arena.?.allocator();
}
self.nums = try self.mem_allocator.alloc(T, self.numsCapacity);
std.mem.set(T, self.nums, @as(T, 0));
}
//
pub fn deinit(self: *Self) void {
if (self.mem_arena == null) return;
self.mem_arena.?.deinit();
}
//
pub fn size(self: *Self) usize {
return self.numSize;
}
//
pub fn capacity(self: *Self) usize {
return self.numsCapacity;
}
// 访
pub fn get(self: *Self, index: usize) T {
//
if (index >= self.size()) @panic("索引越界");
return self.nums[index];
}
//
pub fn set(self: *Self, index: usize, num: T) void {
//
if (index >= self.size()) @panic("索引越界");
self.nums[index] = num;
}
//
pub fn add(self: *Self, num: T) !void {
//
if (self.size() == self.capacity()) try self.extendCapacity();
self.nums[self.size()] = num;
//
self.numSize += 1;
}
//
pub fn insert(self: *Self, index: usize, num: T) !void {
if (index >= self.size()) @panic("索引越界");
//
if (self.size() == self.capacity()) try self.extendCapacity();
// i
var j = self.size() - 1;
while (j >= index) : (j -= 1) {
self.nums[j + 1] = self.nums[j];
}
self.nums[index] = num;
//
self.numSize += 1;
}
//
pub fn remove(self: *Self, index: usize) T {
if (index >= self.size()) @panic("索引越界");
var num = self.nums[index];
// i
var j = index;
while (j < self.size() - 1) : (j += 1) {
self.nums[j] = self.nums[j + 1];
}
//
self.numSize -= 1;
//
return num;
}
//
pub fn extendCapacity(self: *Self) !void {
// size * extendRatio
var newCapacity = self.capacity() * self.extendRatio;
var extend = try self.mem_allocator.alloc(T, newCapacity);
std.mem.set(T, extend, @as(T, 0));
//
std.mem.copy(T, extend, self.nums);
self.nums = extend;
//
self.numsCapacity = newCapacity;
}
//
pub fn toArray(self: *Self) ![]T {
//
var nums = try self.mem_allocator.alloc(T, self.size());
std.mem.set(T, nums, @as(T, 0));
for (nums) |*num, i| {
num.* = self.get(i);
}
return nums;
}
};
}
// Driver Code
pub fn main() !void {
//
var list = MyList(i32){};
try list.init(std.heap.page_allocator);
//
defer list.deinit();
//
try list.add(1);
try list.add(3);
try list.add(2);
try list.add(5);
try list.add(4);
std.debug.print("列表 list = ", .{});
inc.PrintUtil.printArray(i32, try list.toArray());
std.debug.print(" ,容量 = {} ,长度 = {}", .{list.capacity(), list.size()});
//
try list.insert(3, 6);
std.debug.print("\n在索引 3 处插入数字 6 ,得到 list = ", .{});
inc.PrintUtil.printArray(i32, try list.toArray());
//
_ = list.remove(3);
std.debug.print("\n删除索引 3 处的元素,得到 list = ", .{});
inc.PrintUtil.printArray(i32, try list.toArray());
// 访
var num = list.get(1);
std.debug.print("\n访问索引 1 处的元素,得到 num = {}", .{num});
//
list.set(1, 0);
std.debug.print("\n将索引 1 处的元素更新为 0 ,得到 list = ", .{});
inc.PrintUtil.printArray(i32, try list.toArray());
//
list.set(1, 0);
var i: i32 = 0;
while (i < 10) : (i += 1) {
// i = 5
try list.add(i);
}
std.debug.print("\n扩容后的列表 list = ", .{});
inc.PrintUtil.printArray(i32, try list.toArray());
std.debug.print(" ,容量 = {} ,长度 = {}\n", .{list.capacity(), list.size()});
const getchar = try std.io.getStdIn().reader().readByte();
_ = getchar;
}

View file

@ -0,0 +1,125 @@
// File: space_complexity.zig
// Created Time: 2023-01-07
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const inc = @import("include");
//
fn function() i32 {
// do something
return 0;
}
//
fn constant(n: i32) void {
// O(1)
const a: i32 = 0;
var b: i32 = 0;
var nums = [_]i32{0}**10000;
var node = inc.ListNode(i32){.val = 0};
var i: i32 = 0;
// O(1)
while (i < n) : (i += 1) {
var c: i32 = 0;
_ = c;
}
// O(1)
i = 0;
while (i < n) : (i += 1) {
_ = function();
}
_ = a;
_ = b;
_ = nums;
_ = node;
}
// 线
fn linear(comptime n: i32) !void {
// n O(n)
var nums = [_]i32{0}**n;
// n O(n)
var nodes = std.ArrayList(i32).init(std.heap.page_allocator);
defer nodes.deinit();
var i: i32 = 0;
while (i < n) : (i += 1) {
try nodes.append(i);
}
// n O(n)
var map = std.AutoArrayHashMap(i32, []const u8).init(std.heap.page_allocator);
defer map.deinit();
var j: i32 = 0;
while (j < n) : (j += 1) {
const string = try std.fmt.allocPrint(std.heap.page_allocator, "{d}", .{j});
defer std.heap.page_allocator.free(string);
try map.put(i, string);
}
_ = nums;
}
// 线
fn linearRecur(comptime n: i32) void {
std.debug.print("递归 n = {}\n", .{n});
if (n == 1) return;
linearRecur(n - 1);
}
//
fn quadratic(n: i32) !void {
// O(n^2)
var nodes = std.ArrayList(std.ArrayList(i32)).init(std.heap.page_allocator);
defer nodes.deinit();
var i: i32 = 0;
while (i < n) : (i += 1) {
var tmp = std.ArrayList(i32).init(std.heap.page_allocator);
defer tmp.deinit();
var j: i32 = 0;
while (j < n) : (j += 1) {
try tmp.append(0);
}
try nodes.append(tmp);
}
}
//
fn quadraticRecur(comptime n: i32) i32 {
if (n <= 0) return 0;
var nums = [_]i32{0}**n;
std.debug.print("递归 n = {} 中的 nums 长度 = {}\n", .{n, nums.len});
return quadraticRecur(n - 1);
}
//
fn buildTree(mem_allocator: std.mem.Allocator, n: i32) !?*inc.TreeNode(i32) {
if (n == 0) return null;
const root = try mem_allocator.create(inc.TreeNode(i32));
root.init(0);
root.left = try buildTree(mem_allocator, n - 1);
root.right = try buildTree(mem_allocator, n - 1);
return root;
}
// Driver Code
pub fn main() !void {
const n: i32 = 5;
//
constant(n);
// 线
try linear(n);
linearRecur(n);
//
try quadratic(n);
_ = quadraticRecur(n);
//
var mem_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer mem_arena.deinit();
var root = blk_root: {
const mem_allocator = mem_arena.allocator();
break :blk_root try buildTree(mem_allocator, n);
};
try inc.PrintUtil.printTree(root, null, false);
const getchar = try std.io.getStdIn().reader().readByte();
_ = getchar;
}

View file

@ -59,11 +59,13 @@ fn bubbleSort(nums: []i32) i32 {
var j: usize = 0; var j: usize = 0;
// //
while (j < i) : (j += 1) { while (j < i) : (j += 1) {
// nums[j] nums[j + 1] if (nums[j] > nums[j + 1]) {
var tmp = nums[j]; // nums[j] nums[j + 1]
nums[j] = nums[j + 1]; var tmp = nums[j];
nums[j + 1] = tmp; nums[j] = nums[j + 1];
count += 3; // 3 nums[j + 1] = tmp;
count += 3; // 3
}
} }
} }
return count; return count;
@ -138,7 +140,7 @@ fn factorialRecur(n: i32) i32 {
} }
// Driver Code // Driver Code
pub fn main() void { pub fn main() !void {
// n // n
const n: i32 = 8; const n: i32 = 8;
std.debug.print("输入数据大小 n = {}\n", .{n}); std.debug.print("输入数据大小 n = {}\n", .{n});

View file

@ -27,7 +27,7 @@ pub fn findOne(nums: []i32) i32 {
} }
// Driver Code // Driver Code
pub fn main() void { pub fn main() !void {
var i: i32 = 0; var i: i32 = 0;
while (i < 10) : (i += 1) { while (i < 10) : (i += 1) {
const n: usize = 100; const n: usize = 100;

View file

@ -0,0 +1,55 @@
// File: hash_map.zig
// Created Time: 2023-01-13
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const inc = @import("include");
// Driver Code
pub fn main() !void {
//
var map = std.AutoHashMap(i32, []const u8).init(std.heap.page_allocator);
//
defer map.deinit();
//
// (key, value)
try map.put(12836, "小哈");
try map.put(15937, "小啰");
try map.put(16750, "小算");
try map.put(13276, "小法");
try map.put(10583, "小鸭");
std.debug.print("\n添加完成后,哈希表为\nKey -> Value\n", .{});
inc.PrintUtil.printHashMap(i32, []const u8, map);
//
// key value
var name = map.get(15937).?;
std.debug.print("\n输入学号 15937 ,查询到姓名 {s}\n", .{name});
//
// (key, value)
_ = map.remove(10583);
std.debug.print("\n删除 10583 后,哈希表为\nKey -> Value\n", .{});
inc.PrintUtil.printHashMap(i32, []const u8, map);
//
std.debug.print("\n遍历键值对 Key->Value\n", .{});
inc.PrintUtil.printHashMap(i32, []const u8, map);
std.debug.print("\n单独遍历键 Key\n", .{});
var it = map.iterator();
while (it.next()) |kv| {
std.debug.print("{}\n", .{kv.key_ptr.*});
}
std.debug.print("\n单独遍历值 value\n", .{});
it = map.iterator();
while (it.next()) |kv| {
std.debug.print("{s}\n", .{kv.value_ptr.*});
}
const getchar = try std.io.getStdIn().reader().readByte();
_ = getchar;
}

View file

@ -0,0 +1,56 @@
// File: linear_search.zig
// Created Time: 2023-01-13
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const inc = @import("include");
// 线
fn linearSearchList(comptime T: type, nums: std.ArrayList(T), target: T) T {
//
for (nums.items) |num, i| {
//
if (num == target) {
return @intCast(T, i);
}
}
// -1
return -1;
}
// 线
pub fn linearSearchLinkedList(comptime T: type, node: ?*inc.ListNode(T), target: T) ?*inc.ListNode(T) {
var head = node;
//
while (head != null) {
//
if (head.?.val == target) return head;
head = head.?.next;
}
return null;
}
// Driver Code
pub fn main() !void {
var target: i32 = 3;
// 线
var nums = std.ArrayList(i32).init(std.heap.page_allocator);
defer nums.deinit();
try nums.appendSlice(&[_]i32{ 1, 5, 3, 2, 4, 7, 5, 9, 10, 8 });
var index = linearSearchList(i32, nums, target);
std.debug.print("目标元素 3 的索引 = {}\n", .{index});
// 线
var mem_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer mem_arena.deinit();
const mem_allocator = mem_arena.allocator();
var head = try inc.ListUtil.listToLinkedList(i32, mem_allocator, nums);
var node = linearSearchLinkedList(i32, head, target);
std.debug.print("目标结点值 3 的对应结点对象为 ", .{});
try inc.PrintUtil.printLinkedList(i32, node);
const getchar = try std.io.getStdIn().reader().readByte();
_ = getchar;
}

View file

@ -0,0 +1,62 @@
// File: bubble_sort.zig
// Created Time: 2023-01-08
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const inc = @import("include");
//
fn bubbleSort(nums: []i32) void {
// n-1, n-2, ..., 1
var i: usize = nums.len - 1;
while (i > 0) : (i -= 1) {
var j: usize = 0;
//
while (j < i) : (j += 1) {
if (nums[j] > nums[j + 1]) {
// nums[j] nums[j + 1]
var tmp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = tmp;
}
}
}
}
//
fn bubbleSortWithFlag(nums: []i32) void {
// n-1, n-2, ..., 1
var i: usize = nums.len - 1;
while (i > 0) : (i -= 1) {
var flag = false; //
var j: usize = 0;
//
while (j < i) : (j += 1) {
if (nums[j] > nums[j + 1]) {
// nums[j] nums[j + 1]
var tmp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = tmp;
flag = true;
}
}
if (!flag) break; //
}
}
// Driver Code
pub fn main() !void {
var nums = [_]i32{ 4, 1, 3, 1, 5, 2 };
bubbleSort(&nums);
std.debug.print("冒泡排序完成后 nums = ", .{});
inc.PrintUtil.printArray(i32, &nums);
var nums1 = [_]i32{ 4, 1, 3, 1, 5, 2 };
bubbleSortWithFlag(&nums1);
std.debug.print("\n冒泡排序完成后 nums1 = ", .{});
inc.PrintUtil.printArray(i32, &nums1);
const getchar = try std.io.getStdIn().reader().readByte();
_ = getchar;
}

View file

@ -0,0 +1,33 @@
// File: insertion_sort.zig
// Created Time: 2023-01-08
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const inc = @import("include");
//
fn insertionSort(nums: []i32) void {
// base = nums[1], nums[2], ..., nums[n-1]
var i: usize = 1;
while (i < nums.len) : (i += 1) {
var base = nums[i];
var j: usize = i;
// base
while (j >= 1 and nums[j - 1] > base) : (j -= 1) {
nums[j] = nums[j - 1]; // 1. nums[j]
}
nums[j] = base; // 2. base
}
}
// Driver Code
pub fn main() !void {
var nums = [_]i32{ 4, 1, 3, 1, 5, 2 };
insertionSort(&nums);
std.debug.print("插入排序完成后 nums = ", .{});
inc.PrintUtil.printArray(i32, &nums);
const getchar = try std.io.getStdIn().reader().readByte();
_ = getchar;
}

View file

@ -0,0 +1,99 @@
// File: array_stack.zig
// Created Time: 2023-01-08
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const inc = @import("include");
//
//
pub fn ArrayStack(comptime T: type) type {
return struct {
const Self = @This();
stack: ?std.ArrayList(T) = null,
// +
pub fn init(self: *Self, allocator: std.mem.Allocator) void {
if (self.stack == null) {
self.stack = std.ArrayList(T).init(allocator);
}
}
//
pub fn deinit(self: *Self) void {
if (self.stack == null) return;
self.stack.?.deinit();
}
//
pub fn size(self: *Self) usize {
return self.stack.?.items.len;
}
//
pub fn empty(self: *Self) bool {
return self.size() == 0;
}
// 访
pub fn top(self: *Self) T {
if (self.size() == 0) @panic("栈为空");
return self.stack.?.items[self.size() - 1];
}
//
pub fn push(self: *Self, num: T) !void {
try self.stack.?.append(num);
}
//
pub fn pop(self: *Self) T {
var num = self.stack.?.pop();
return num;
}
// ArrayList
pub fn toList(self: *Self) std.ArrayList(T) {
return self.stack.?;
}
};
}
// Driver Code
pub fn main() !void {
//
var stack = ArrayStack(i32){};
stack.init(std.heap.page_allocator);
//
defer stack.deinit();
//
try stack.push(1);
try stack.push(3);
try stack.push(2);
try stack.push(5);
try stack.push(4);
std.debug.print("栈 stack = ", .{});
inc.PrintUtil.printList(i32, stack.toList());
// 访
var top = stack.top();
std.debug.print("\n栈顶元素 top = {}", .{top});
//
top = stack.pop();
std.debug.print("\n出栈元素 pop = {},出栈后 stack = ", .{top});
inc.PrintUtil.printList(i32, stack.toList());
//
var size = stack.size();
std.debug.print("\n栈的长度 size = {}", .{size});
//
var empty = stack.empty();
std.debug.print("\n栈是否为空 = {}", .{empty});
const getchar = try std.io.getStdIn().reader().readByte();
_ = getchar;
}

View file

@ -0,0 +1,120 @@
// File: linkedlist_stack.zig
// Created Time: 2023-01-08
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const inc = @import("include");
//
//
pub fn LinkedListStack(comptime T: type) type {
return struct {
const Self = @This();
stackTop: ?*inc.ListNode(T) = null, //
stkSize: usize = 0, //
mem_arena: ?std.heap.ArenaAllocator = null,
mem_allocator: std.mem.Allocator = undefined, //
// +
pub fn init(self: *Self, allocator: std.mem.Allocator) !void {
if (self.mem_arena == null) {
self.mem_arena = std.heap.ArenaAllocator.init(allocator);
self.mem_allocator = self.mem_arena.?.allocator();
}
self.stackTop = null;
self.stkSize = 0;
}
//
pub fn deinit(self: *Self) void {
if (self.mem_arena == null) return;
self.mem_arena.?.deinit();
}
//
pub fn size(self: *Self) usize {
return self.stkSize;
}
//
pub fn empty(self: *Self) bool {
return self.size() == 0;
}
// 访
pub fn top(self: *Self) T {
if (self.size() == 0) @panic("栈为空");
return self.stackTop.?.val;
}
//
pub fn push(self: *Self, num: T) !void {
var node = try self.mem_allocator.create(inc.ListNode(T));
node.init(num);
node.next = self.stackTop;
self.stackTop = node;
self.stkSize += 1;
}
//
pub fn pop(self: *Self) T {
var num = self.top();
self.stackTop = self.stackTop.?.next;
self.stkSize -= 1;
return num;
}
//
pub fn toArray(self: *Self) ![]T {
var node = self.stackTop;
var res = try self.mem_allocator.alloc(T, self.size());
std.mem.set(T, res, @as(T, 0));
var i: usize = 0;
while (i < res.len) : (i += 1) {
res[res.len - i - 1] = node.?.val;
node = node.?.next;
}
return res;
}
};
}
// Driver Code
pub fn main() !void {
//
var stack = LinkedListStack(i32){};
try stack.init(std.heap.page_allocator);
//
defer stack.deinit();
//
try stack.push(1);
try stack.push(3);
try stack.push(2);
try stack.push(5);
try stack.push(4);
std.debug.print("栈 stack = ", .{});
inc.PrintUtil.printArray(i32, try stack.toArray());
// 访
var top = stack.top();
std.debug.print("\n栈顶元素 top = {}", .{top});
//
top = stack.pop();
std.debug.print("\n出栈元素 pop = {},出栈后 stack = ", .{top});
inc.PrintUtil.printArray(i32, try stack.toArray());
//
var size = stack.size();
std.debug.print("\n栈的长度 size = {}", .{size});
//
var empty = stack.empty();
std.debug.print("\n栈是否为空 = {}", .{empty});
const getchar = try std.io.getStdIn().reader().readByte();
_ = getchar;
}

View file

@ -0,0 +1,44 @@
// File: stack.zig
// Created Time: 2023-01-08
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const inc = @import("include");
// Driver Code
pub fn main() !void {
//
// zig ArrayList 使
var stack = std.ArrayList(i32).init(std.heap.page_allocator);
//
defer stack.deinit();
//
try stack.append(1);
try stack.append(3);
try stack.append(2);
try stack.append(5);
try stack.append(4);
std.debug.print("栈 stack = ", .{});
inc.PrintUtil.printList(i32, stack);
// 访
var top = stack.items[stack.items.len - 1];
std.debug.print("\n栈顶元素 top = {}", .{top});
//
top = stack.pop();
std.debug.print("\n出栈元素 pop = {},出栈后 stack = ", .{top});
inc.PrintUtil.printList(i32, stack);
//
var size = stack.items.len;
std.debug.print("\n栈的长度 size = {}", .{size});
//
var empty = if (stack.items.len == 0) true else false;
std.debug.print("\n栈是否为空 = {}", .{empty});
const getchar = try std.io.getStdIn().reader().readByte();
_ = getchar;
}

View file

@ -0,0 +1,40 @@
// File: binary_tree.zig
// Created Time: 2023-01-14
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
const inc = @import("include");
// Driver Code
pub fn main() !void {
//
//
var n1 = inc.TreeNode(i32){ .val = 1 };
var n2 = inc.TreeNode(i32){ .val = 2 };
var n3 = inc.TreeNode(i32){ .val = 3 };
var n4 = inc.TreeNode(i32){ .val = 4 };
var n5 = inc.TreeNode(i32){ .val = 5 };
//
n1.left = &n2;
n1.right = &n3;
n2.left = &n4;
n2.right = &n5;
std.debug.print("初始化二叉树\n", .{});
try inc.PrintUtil.printTree(&n1, null, false);
//
var p = inc.TreeNode(i32){ .val = 0 };
// n1 -> n2 P
n1.left = &p;
p.left = &n2;
std.debug.print("插入结点 P 后\n", .{});
try inc.PrintUtil.printTree(&n1, null, false);
//
n1.left = &n2;
std.debug.print("删除结点 P 后\n", .{});
try inc.PrintUtil.printTree(&n1, null, false);
const getchar = try std.io.getStdIn().reader().readByte();
_ = getchar;
}

View file

@ -0,0 +1,36 @@
// File: ListNode.zig
// Created Time: 2023-01-07
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
// Definition for a singly-linked list node
//
pub fn ListNode(comptime T: type) type {
return struct {
const Self = @This();
val: T = 0,
next: ?*Self = null,
// Initialize a list node with specific value
pub fn init(self: *Self, x: i32) void {
self.val = x;
self.next = null;
}
};
}
// Generate a linked list with a list
pub fn listToLinkedList(comptime T: type, mem_allocator: std.mem.Allocator, list: std.ArrayList(T)) !?*ListNode(T) {
var dum = try mem_allocator.create(ListNode(T));
dum.init(0);
var head = dum;
for (list.items) |val| {
var tmp = try mem_allocator.create(ListNode(T));
tmp.init(val);
head.next = tmp;
head = head.next.?;
}
return dum.next;
}

View file

@ -1,13 +1,122 @@
// File: TreeNode.zig // File: PrintUtil.zig
// Created Time: 2023-01-07 // Created Time: 2023-01-07
// Author: sjinzh (sjinzh@gmail.com) // Author: sjinzh (sjinzh@gmail.com)
const std = @import("std"); const std = @import("std");
pub const ListUtil = @import("ListNode.zig");
pub const ListNode = ListUtil.ListNode;
pub const TreeUtil = @import("TreeNode.zig");
pub const TreeNode = TreeUtil.TreeNode;
// Print an Array // Print an array
pub fn printArray(comptime T: type, nums: []T) void { pub fn printArray(comptime T: type, nums: []T) void {
std.debug.print("[", .{}); std.debug.print("[", .{});
for (nums) |num, j| { if (nums.len > 0) {
std.debug.print("{}{s}", .{num, if (j == nums.len-1) "]\n" else ", " }); for (nums) |num, j| {
} std.debug.print("{}{s}", .{num, if (j == nums.len-1) "]" else ", " });
}
} else {
std.debug.print("]", .{});
}
}
// Print a list
pub fn printList(comptime T: type, list: std.ArrayList(T)) void {
std.debug.print("[", .{});
if (list.items.len > 0) {
for (list.items) |value, i| {
std.debug.print("{}{s}", .{value, if (i == list.items.len-1) "]" else ", " });
}
} else {
std.debug.print("]", .{});
}
}
// Print a linked list
pub fn printLinkedList(comptime T: type, node: ?*ListNode(T)) !void {
if (node == null) return;
var list = std.ArrayList(i32).init(std.heap.page_allocator);
defer list.deinit();
var head = node;
while (head != null) {
try list.append(head.?.val);
head = head.?.next;
}
for (list.items) |value, i| {
std.debug.print("{}{s}", .{value, if (i == list.items.len-1) "\n" else "->" });
}
}
// Print a HashMap
pub fn printHashMap(comptime TKey: type, comptime TValue: type, map: std.AutoHashMap(TKey, TValue)) void {
var it = map.iterator();
while (it.next()) |kv| {
var key = kv.key_ptr.*;
var value = kv.value_ptr.*;
std.debug.print("{} -> {s}\n", .{key, value});
}
}
// print a heap (PriorityQueue)
pub fn printHeap(comptime T: type, mem_allocator: std.mem.Allocator, queue: anytype) !void {
var arr = queue.items;
var len = queue.len;
std.debug.print("堆的数组表示:", .{});
printArray(T, arr[0..len]);
std.debug.print("\n堆的树状表示:\n", .{});
var root = try TreeUtil.arrToTree(T, mem_allocator, arr[0..len]);
try printTree(root, null, false);
}
// This tree printer is borrowed from TECHIE DELIGHT
// https://www.techiedelight.com/c-program-print-binary-tree/
const Trunk = struct {
prev: ?*Trunk = null,
str: []const u8 = undefined,
pub fn init(self: *Trunk, prev: ?*Trunk, str: []const u8) void {
self.prev = prev;
self.str = str;
}
};
// Helper function to print branches of the binary tree
pub fn showTrunks(p: ?*Trunk) void {
if (p == null) return;
showTrunks(p.?.prev);
std.debug.print("{s}", .{p.?.str});
}
// The interface of the tree printer
// Print a binary tree
pub fn printTree(root: ?*TreeNode(i32), prev: ?*Trunk, isLeft: bool) !void {
if (root == null) {
return;
}
var prev_str = " ";
var trunk = Trunk{.prev = prev, .str = prev_str};
try printTree(root.?.right, &trunk, true);
if (prev == null) {
trunk.str = "———";
} else if (isLeft) {
trunk.str = "/———";
prev_str = " |";
} else {
trunk.str = "\\———";
prev.?.str = prev_str;
}
showTrunks(&trunk);
std.debug.print(" {}\n", .{root.?.val});
if (prev) |_| {
prev.?.str = prev_str;
}
trunk.str = " |";
try printTree(root.?.left, &trunk, false);
} }

View file

@ -0,0 +1,60 @@
// File: TreeNode.zig
// Created Time: 2023-01-07
// Author: sjinzh (sjinzh@gmail.com)
const std = @import("std");
// Definition for a binary tree node
//
pub fn TreeNode(comptime T: type) type {
return struct {
const Self = @This();
val: T = undefined,
left: ?*Self = null,
right: ?*Self = null,
// Initialize a tree node with specific value
pub fn init(self: *Self, x: i32) void {
self.val = x;
self.left = null;
self.right = null;
}
};
}
// Generate a binary tree with an array
pub fn arrToTree(comptime T: type, mem_allocator: std.mem.Allocator, list: []T) !?*TreeNode(T) {
if (list.len == 0) return null;
var root = try mem_allocator.create(TreeNode(T));
root.init(list[0]);
const TailQueue = std.TailQueue(?*TreeNode(T));
const TailQueueNode = std.TailQueue(?*TreeNode(T)).Node;
var que = TailQueue{};
var node_root = TailQueueNode{ .data = root };
que.append(&node_root);
var index: usize = 0;
while (que.len > 0) {
var node = que.popFirst();
index += 1;
if (index >= list.len) break;
if (index < list.len) {
var tmp = try mem_allocator.create(TreeNode(T));
tmp.init(list[index]);
node.?.data.?.left = tmp;
var a = TailQueueNode{ .data = node.?.data.?.left };
que.append(&a);
}
index += 1;
if (index >= list.len) break;
if (index < list.len) {
var tmp = try mem_allocator.create(TreeNode(T));
tmp.init(list[index]);
node.?.data.?.right = tmp;
var a = TailQueueNode{ .data = node.?.data.?.right };
que.append(&a);
}
}
return root;
}

View file

@ -1,5 +1,9 @@
// File: include.zig // File: include.zig
// Created Time: 2023-01-04 // Created Time: 2023-01-07
// Author: sjinzh (sjinzh@gmail.com) // Author: sjinzh (sjinzh@gmail.com)
pub const PrintUtil = @import("PrintUtil.zig"); pub const PrintUtil = @import("PrintUtil.zig");
pub const ListUtil = @import("ListNode.zig");
pub const ListNode = ListUtil.ListNode;
pub const TreeUtil = @import("TreeNode.zig");
pub const TreeNode = TreeUtil.TreeNode;

View file

@ -3,6 +3,6 @@ mkdocs build --clean
cd site cd site
git init git init
git add -A git add -A
git commit -m 'deploy' git commit -m "deploy"
git push -f git@github.com:krahets/hello-algo.git master:gh-pages git push -f git@github.com:krahets/hello-algo.git master:gh-pages
cd - cd -

7
docker-compose.yml Normal file
View file

@ -0,0 +1,7 @@
version: '3'
services:
hello-algo:
build: .
ports:
- "8000:8000"

View file

@ -245,6 +245,8 @@ elementAddr = firtstElementAddr + elementLength * elementIndex
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
res[i] = nums[i]; res[i] = nums[i];
} }
// 释放内存
delete[] nums;
// 返回扩展后的新数组 // 返回扩展后的新数组
return res; return res;
} }

View file

@ -748,6 +748,11 @@ comments: true
nums = new int[numsCapacity]; nums = new int[numsCapacity];
} }
/* 析构函数 */
~MyList() {
delete[] nums;
}
/* 获取列表长度(即当前元素数量)*/ /* 获取列表长度(即当前元素数量)*/
int size() { int size() {
return numsSize; return numsSize;
@ -818,14 +823,14 @@ comments: true
void extendCapacity() { void extendCapacity() {
// 新建一个长度为 size * extendRatio 的数组,并将原数组拷贝到新数组 // 新建一个长度为 size * extendRatio 的数组,并将原数组拷贝到新数组
int newCapacity = capacity() * extendRatio; int newCapacity = capacity() * extendRatio;
int* extend = new int[newCapacity]; int* tmp = nums;
nums = new int[newCapacity];
// 将原数组中的所有元素复制到新数组 // 将原数组中的所有元素复制到新数组
for (int i = 0; i < size(); i++) { for (int i = 0; i < size(); i++) {
extend[i] = nums[i]; nums[i] = tmp[i];
} }
int* temp = nums; // 释放内存
nums = extend; delete[] tmp;
delete[] temp;
numsCapacity = newCapacity; numsCapacity = newCapacity;
} }
}; };

View file

@ -507,7 +507,7 @@ $$
const int a = 0; const int a = 0;
int b = 0; int b = 0;
vector<int> nums(10000); vector<int> nums(10000);
ListNode* node = new ListNode(0); ListNode node(0);
// 循环中的变量占用 O(1) 空间 // 循环中的变量占用 O(1) 空间
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
int c = 0; int c = 0;
@ -654,9 +654,9 @@ $$
// 长度为 n 的数组占用 O(n) 空间 // 长度为 n 的数组占用 O(n) 空间
vector<int> nums(n); vector<int> nums(n);
// 长度为 n 的列表占用 O(n) 空间 // 长度为 n 的列表占用 O(n) 空间
vector<ListNode*> nodes; vector<ListNode> nodes;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
nodes.push_back(new ListNode(i)); nodes.push_back(ListNode(i));
} }
// 长度为 n 的哈希表占用 O(n) 空间 // 长度为 n 的哈希表占用 O(n) 空间
unordered_map<int, string> map; unordered_map<int, string> map;

View file

@ -355,8 +355,8 @@ $$
print(0) print(0)
} }
} }
``` ```
![time_complexity_first_example](time_complexity.assets/time_complexity_first_example.png) ![time_complexity_first_example](time_complexity.assets/time_complexity_first_example.png)
<p align="center"> Fig. 算法 A, B, C 的时间增长趋势 </p> <p align="center"> Fig. 算法 A, B, C 的时间增长趋势 </p>
@ -725,7 +725,6 @@ $$
} }
``` ```
### 2. 判断渐近上界 ### 2. 判断渐近上界
**时间复杂度由多项式 $T(n)$ 中最高阶的项来决定**。这是因为在 $n$ 趋于无穷大时,最高阶的项将处于主导作用,其它项的影响都可以被忽略。 **时间复杂度由多项式 $T(n)$ 中最高阶的项来决定**。这是因为在 $n$ 趋于无穷大时,最高阶的项将处于主导作用,其它项的影响都可以被忽略。
@ -1435,11 +1434,14 @@ $$
for (int i = n - 1; i > 0; i--) { for (int i = n - 1; i > 0; i--) {
// 内循环:冒泡操作 // 内循环:冒泡操作
for (int j = 0; j < i; j++) { for (int j = 0; j < i; j++) {
// 交换 nums[j] 与 nums[j + 1] if (nums[j] > nums [j + 1])
int tmp = nums[j]; {
nums[j] = nums[j + 1]; // 交换 nums[j] 与 nums[j + 1]
nums[j + 1] = tmp; int tmp = nums[j];
count += 3; // 元素交换包含 3 个单元操作 nums[j] = nums[j + 1];
nums[j + 1] = tmp;
count += 3; // 元素交换包含 3 个单元操作
}
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Some files were not shown because too many files have changed in this diff Show more