This commit is contained in:
krahets 2023-10-18 02:16:55 +08:00
parent 64c5d13051
commit d2ba55fcd6
22 changed files with 374 additions and 436 deletions

View file

@ -153,12 +153,10 @@ comments: true
```c title="" ```c title=""
/* 链表节点结构体 */ /* 链表节点结构体 */
struct ListNode { typedef struct ListNode {
int val; // 节点值 int val; // 节点值
struct ListNode *next; // 指向下一节点的指针 struct ListNode *next; // 指向下一节点的指针
}; } ListNode;
typedef struct ListNode ListNode;
/* 构造函数 */ /* 构造函数 */
ListNode *newListNode(int val) { ListNode *newListNode(int val) {
@ -1284,13 +1282,11 @@ comments: true
```c title="" ```c title=""
/* 双向链表节点结构体 */ /* 双向链表节点结构体 */
struct ListNode { typedef struct ListNode {
int val; // 节点值 int val; // 节点值
struct ListNode *next; // 指向后继节点的指针 struct ListNode *next; // 指向后继节点的指针
struct ListNode *prev; // 指向前驱节点的指针 struct ListNode *prev; // 指向前驱节点的指针
}; } ListNode;
typedef struct ListNode ListNode;
/* 构造函数 */ /* 构造函数 */
ListNode *newListNode(int val) { ListNode *newListNode(int val) {

View file

@ -1895,18 +1895,16 @@ comments: true
```c title="my_list.c" ```c title="my_list.c"
/* 列表类简易实现 */ /* 列表类简易实现 */
struct myList { typedef struct {
int *arr; // 数组(存储列表元素) int *arr; // 数组(存储列表元素)
int capacity; // 列表容量 int capacity; // 列表容量
int size; // 列表大小 int size; // 列表大小
int extendRatio; // 列表每次扩容的倍数 int extendRatio; // 列表每次扩容的倍数
}; } MyList;
typedef struct myList myList;
/* 构造函数 */ /* 构造函数 */
myList *newMyList() { MyList *newMyList() {
myList *nums = malloc(sizeof(myList)); MyList *nums = malloc(sizeof(MyList));
nums->capacity = 10; nums->capacity = 10;
nums->arr = malloc(sizeof(int) * nums->capacity); nums->arr = malloc(sizeof(int) * nums->capacity);
nums->size = 0; nums->size = 0;
@ -1915,35 +1913,35 @@ comments: true
} }
/* 析构函数 */ /* 析构函数 */
void delMyList(myList *nums) { void delMyList(MyList *nums) {
free(nums->arr); free(nums->arr);
free(nums); free(nums);
} }
/* 获取列表长度 */ /* 获取列表长度 */
int size(myList *nums) { int size(MyList *nums) {
return nums->size; return nums->size;
} }
/* 获取列表容量 */ /* 获取列表容量 */
int capacity(myList *nums) { int capacity(MyList *nums) {
return nums->capacity; return nums->capacity;
} }
/* 访问元素 */ /* 访问元素 */
int get(myList *nums, int index) { int get(MyList *nums, int index) {
assert(index >= 0 && index < nums->size); assert(index >= 0 && index < nums->size);
return nums->arr[index]; return nums->arr[index];
} }
/* 更新元素 */ /* 更新元素 */
void set(myList *nums, int index, int num) { void set(MyList *nums, int index, int num) {
assert(index >= 0 && index < nums->size); assert(index >= 0 && index < nums->size);
nums->arr[index] = num; nums->arr[index] = num;
} }
/* 尾部添加元素 */ /* 尾部添加元素 */
void add(myList *nums, int num) { void add(MyList *nums, int num) {
if (size(nums) == capacity(nums)) { if (size(nums) == capacity(nums)) {
extendCapacity(nums); // 扩容 extendCapacity(nums); // 扩容
} }
@ -1952,7 +1950,7 @@ comments: true
} }
/* 中间插入元素 */ /* 中间插入元素 */
void insert(myList *nums, int index, int num) { void insert(MyList *nums, int index, int num) {
assert(index >= 0 && index < size(nums)); assert(index >= 0 && index < size(nums));
// 元素数量超出容量时,触发扩容机制 // 元素数量超出容量时,触发扩容机制
if (size(nums) == capacity(nums)) { if (size(nums) == capacity(nums)) {
@ -1967,7 +1965,7 @@ comments: true
/* 删除元素 */ /* 删除元素 */
// 注意stdio.h 占用了 remove 关键词 // 注意stdio.h 占用了 remove 关键词
int removeNum(myList *nums, int index) { int removeNum(MyList *nums, int index) {
assert(index >= 0 && index < size(nums)); assert(index >= 0 && index < size(nums));
int num = nums->arr[index]; int num = nums->arr[index];
for (int i = index; i < size(nums) - 1; i++) { for (int i = index; i < size(nums) - 1; i++) {
@ -1978,7 +1976,7 @@ comments: true
} }
/* 列表扩容 */ /* 列表扩容 */
void extendCapacity(myList *nums) { void extendCapacity(MyList *nums) {
// 先分配空间 // 先分配空间
int newCapacity = capacity(nums) * nums->extendRatio; int newCapacity = capacity(nums) * nums->extendRatio;
int *extend = (int *)malloc(sizeof(int) * newCapacity); int *extend = (int *)malloc(sizeof(int) * newCapacity);
@ -1997,7 +1995,7 @@ comments: true
} }
/* 将列表转换为 Array 用于打印 */ /* 将列表转换为 Array 用于打印 */
int *toArray(myList *nums) { int *toArray(MyList *nums) {
return nums->arr; return nums->arr;
} }
``` ```

View file

@ -601,25 +601,17 @@ comments: true
=== "C" === "C"
```c title="n_queens.c" ```c title="n_queens.c"
/* 放置结果 */
struct result {
char ***data;
int size;
};
typedef struct result Result;
/* 回溯算法N 皇后 */ /* 回溯算法N 皇后 */
void backtrack(int row, int n, char state[MAX_N][MAX_N], Result *res, void backtrack(int row, int n, char state[MAX_N][MAX_N], char ***res, int *resSize, bool cols[MAX_N],
bool cols[MAX_N], bool diags1[2 * MAX_N - 1], bool diags2[2 * MAX_N - 1]) { bool diags1[2 * MAX_N - 1], bool diags2[2 * MAX_N - 1]) {
// 当放置完所有行时,记录解 // 当放置完所有行时,记录解
if (row == n) { if (row == n) {
res->data[res->size] = (char **)malloc(sizeof(char *) * n); res[*resSize] = (char **)malloc(sizeof(char *) * n);
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
res->data[res->size][i] = (char *)malloc(sizeof(char) * (n + 1)); res[*resSize][i] = (char *)malloc(sizeof(char) * (n + 1));
strcpy(res->data[res->size][i], state[i]); strcpy(res[*resSize][i], state[i]);
} }
res->size++; (*resSize)++;
return; return;
} }
// 遍历所有列 // 遍历所有列
@ -633,7 +625,7 @@ comments: true
state[row][col] = 'Q'; state[row][col] = 'Q';
cols[col] = diags1[diag1] = diags2[diag2] = true; cols[col] = diags1[diag1] = diags2[diag2] = true;
// 放置下一行 // 放置下一行
backtrack(row + 1, n, state, res, cols, diags1, diags2); backtrack(row + 1, n, state, res, resSize, cols, diags1, diags2);
// 回退:将该格子恢复为空位 // 回退:将该格子恢复为空位
state[row][col] = '#'; state[row][col] = '#';
cols[col] = diags1[diag1] = diags2[diag2] = false; cols[col] = diags1[diag1] = diags2[diag2] = false;
@ -642,7 +634,7 @@ comments: true
} }
/* 求解 N 皇后 */ /* 求解 N 皇后 */
Result *nQueens(int n) { char ***nQueens(int n, int *returnSize) {
char state[MAX_N][MAX_N]; char state[MAX_N][MAX_N];
// 初始化 n*n 大小的棋盘,其中 'Q' 代表皇后,'#' 代表空位 // 初始化 n*n 大小的棋盘,其中 'Q' 代表皇后,'#' 代表空位
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
@ -655,10 +647,9 @@ comments: true
bool diags1[2 * MAX_N - 1] = {false}; // 记录主对角线是否有皇后 bool diags1[2 * MAX_N - 1] = {false}; // 记录主对角线是否有皇后
bool diags2[2 * MAX_N - 1] = {false}; // 记录副对角线是否有皇后 bool diags2[2 * MAX_N - 1] = {false}; // 记录副对角线是否有皇后
Result *res = malloc(sizeof(Result)); char ***res = (char ***)malloc(sizeof(char **) * MAX_RES);
res->data = (char ***)malloc(sizeof(char **) * MAX_RES); *returnSize = 0;
res->size = 0; backtrack(0, n, state, res, returnSize, cols, diags1, diags2);
backtrack(0, n, state, res, cols, diags1, diags2);
return res; return res;
} }
``` ```

View file

@ -1254,13 +1254,11 @@ $$
```c title="space_complexity.c" ```c title="space_complexity.c"
/* 哈希表 */ /* 哈希表 */
struct hashTable { typedef struct {
int key; int key;
int val; int val;
UT_hash_handle hh; // 基于 uthash.h 实现 UT_hash_handle hh; // 基于 uthash.h 实现
}; } HashTable;
typedef struct hashTable hashTable;
/* 线性阶 */ /* 线性阶 */
void linear(int n) { void linear(int n) {
@ -1280,16 +1278,16 @@ $$
free(nodes); free(nodes);
// 长度为 n 的哈希表占用 O(n) 空间 // 长度为 n 的哈希表占用 O(n) 空间
hashTable *h = NULL; HashTable *h = NULL;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
hashTable *tmp = malloc(sizeof(hashTable)); HashTable *tmp = malloc(sizeof(HashTable));
tmp->key = i; tmp->key = i;
tmp->val = i; tmp->val = i;
HASH_ADD_INT(h, key, tmp); HASH_ADD_INT(h, key, tmp);
} }
// 内存释放 // 内存释放
hashTable *curr, *tmp; HashTable *curr, *tmp;
HASH_ITER(hh, h, curr, tmp) { HASH_ITER(hh, h, curr, tmp) {
HASH_DEL(h, curr); HASH_DEL(h, curr);
free(curr); free(curr);

View file

@ -404,26 +404,36 @@ comments: true
=== "C" === "C"
```c title="build_tree.c" ```c title="build_tree.c"
/* 构建二叉树 */ /* 构建二叉树:分治 */
fn build_tree(preorder: &[i32], inorder: &[i32]) -> Option<Rc<RefCell<TreeNode>>> { TreeNode *dfs(int *preorder, int *inorderMap, int i, int l, int r, int size) {
// 初始化哈希表,存储 inorder 元素到索引的映射 // 子树区间为空时终止
let mut inorder_map: HashMap<i32, i32> = HashMap::new(); if (r - l < 0)
for i in 0..inorder.len() { return NULL;
inorder_map.insert(inorder[i], i as i32); // 初始化根节点
} TreeNode *root = (TreeNode *)malloc(sizeof(TreeNode));
let root = dfs(preorder, &inorder_map, 0, 0, inorder.len() as i32 - 1); root->val = preorder[i];
root root->left = NULL;
root->right = NULL;
// 查询 m ,从而划分左右子树
int m = inorderMap[preorder[i]];
// 子问题:构建左子树
root->left = dfs(preorder, inorderMap, i + 1, l, m - 1, size);
// 子问题:构建右子树
root->right = dfs(preorder, inorderMap, i + 1 + m - l, m + 1, r, size);
// 返回根节点
return root;
} }
/* 构建二叉树 */ /* 构建二叉树 */
fn build_tree(preorder: &[i32], inorder: &[i32]) -> Option<Rc<RefCell<TreeNode>>> { TreeNode *buildTree(int *preorder, int preorderSize, int *inorder, int inorderSize) {
// 初始化哈希表,存储 inorder 元素到索引的映射 // 初始化哈希表,存储 inorder 元素到索引的映射
let mut inorder_map: HashMap<i32, i32> = HashMap::new(); int *inorderMap = (int *)malloc(sizeof(int) * MAX_N);
for i in 0..inorder.len() { for (int i = 0; i < inorderSize; i++) {
inorder_map.insert(inorder[i], i as i32); inorderMap[inorder[i]] = i;
} }
let root = dfs(preorder, &inorder_map, 0, 0, inorder.len() as i32 - 1); TreeNode *root = dfs(preorder, inorderMap, 0, 0, inorderSize - 1, inorderSize);
root free(inorderMap);
return root;
} }
``` ```

View file

@ -343,7 +343,7 @@ comments: true
int choices[2] = {1, 2}; // 可选择向上爬 1 或 2 阶 int choices[2] = {1, 2}; // 可选择向上爬 1 或 2 阶
int state = 0; // 从第 0 阶开始爬 int state = 0; // 从第 0 阶开始爬
int *res = (int *)malloc(sizeof(int)); int *res = (int *)malloc(sizeof(int));
*res = 0; // 使用 res[0] 记录方案数量 *res = 0; // 使用 res[0] 记录方案数量
int len = sizeof(choices) / sizeof(int); int len = sizeof(choices) / sizeof(int);
backtrack(choices, state, n, res, len); backtrack(choices, state, n, res, len);
int result = *res; int result = *res;

View file

@ -946,143 +946,133 @@ comments: true
```c title="graph_adjacency_matrix.c" ```c title="graph_adjacency_matrix.c"
/* 基于邻接矩阵实现的无向图类结构 */ /* 基于邻接矩阵实现的无向图类结构 */
struct graphAdjMat { typedef struct {
int *vertices; // 顶点列表 int *vertices; // 顶点列表
unsigned int **adjMat; // 邻接矩阵,元素代表“边”,索引代表“顶点索引” int **adjMat; // 邻接矩阵,元素代表“边”,索引代表“顶点索引”
unsigned int size; // 顶点数量 int size; // 顶点数量
unsigned int capacity; // 图容量 int capacity; // 图容量
}; } GraphAdjMat;
typedef struct graphAdjMat graphAdjMat;
/* 添加边 */ /* 添加边 */
// 参数 i, j 对应 vertices 元素索引 // 参数 i, j 对应 vertices 元素索引
void addEdge(graphAdjMat *t, int i, int j) { void addEdge(GraphAdjMat *graph, int i, int j) {
// 越界检查 // 越界检查
if (i < 0 || j < 0 || i >= t->size || j >= t->size || i == j) { if (i < 0 || j < 0 || i >= graph->size || j >= graph->size || i == j) {
printf("Out of range in %s:%d\n", __FILE__, __LINE__); printf("Out of range in %s:%d\n", __FILE__, __LINE__);
exit(1); exit(1);
} }
// 添加边 // 添加边
// 参数 i, j 对应 vertices 元素索引 // 参数 i, j 对应 vertices 元素索引
t->adjMat[i][j] = 1; graph->adjMat[i][j] = 1;
t->adjMat[j][i] = 1; graph->adjMat[j][i] = 1;
} }
/* 删除边 */ /* 删除边 */
// 参数 i, j 对应 vertices 元素索引 // 参数 i, j 对应 vertices 元素索引
void removeEdge(graphAdjMat *t, int i, int j) { void removeEdge(GraphAdjMat *graph, int i, int j) {
// 越界检查 // 越界检查
if (i < 0 || j < 0 || i >= t->size || j >= t->size || i == j) { if (i < 0 || j < 0 || i >= graph->size || j >= graph->size || i == j) {
printf("Out of range in %s:%d\n", __FILE__, __LINE__); printf("Out of range in %s:%d\n", __FILE__, __LINE__);
exit(1); exit(1);
} }
// 删除边 // 删除边
// 参数 i, j 对应 vertices 元素索引 // 参数 i, j 对应 vertices 元素索引
t->adjMat[i][j] = 0; graph->adjMat[i][j] = 0;
t->adjMat[j][i] = 0; graph->adjMat[j][i] = 0;
} }
/* 添加顶点 */ /* 添加顶点 */
void addVertex(graphAdjMat *t, int val) { void addVertex(GraphAdjMat *graph, int val) {
// 如果实际使用不大于预设空间,则直接初始化新空间 // 如果实际使用不大于预设空间,则直接初始化新空间
if (t->size < t->capacity) { if (graph->size < graph->capacity) {
t->vertices[t->size] = val; // 初始化新顶点值 graph->vertices[graph->size] = val; // 初始化新顶点值
for (int i = 0; i < t->size; i++) { for (int i = 0; i < graph->size; i++) {
t->adjMat[i][t->size] = 0; // 邻接矩新列阵置0 graph->adjMat[i][graph->size] = 0; // 邻接矩新列阵置0
} }
memset(t->adjMat[t->size], 0, sizeof(unsigned int) * (t->size + 1)); // 将新增行置 0 memset(graph->adjMat[graph->size], 0, sizeof(int) * (graph->size + 1)); // 将新增行置 0
t->size++; graph->size++;
return; return;
} }
// 扩容,申请新的顶点数组 // 扩容,申请新的顶点数组
int *temp = (int *)malloc(sizeof(int) * (t->size * 2)); int *temp = (int *)malloc(sizeof(int) * (graph->size * 2));
memcpy(temp, t->vertices, sizeof(int) * t->size); memcpy(temp, graph->vertices, sizeof(int) * graph->size);
temp[t->size] = val; temp[graph->size] = val;
// 释放原数组 // 释放原数组
free(t->vertices); free(graph->vertices);
t->vertices = temp; graph->vertices = temp;
// 扩容,申请新的二维数组 // 扩容,申请新的二维数组
unsigned int **tempMat = (unsigned int **)malloc(sizeof(unsigned int *) * t->size * 2); int **tempMat = (int **)malloc(sizeof(int *) * graph->size * 2);
unsigned int *tempMatLine = (unsigned int *)malloc(sizeof(unsigned int) * (t->size * 2) * (t->size * 2)); int *tempMatLine = (int *)malloc(sizeof(int) * (graph->size * 2) * (graph->size * 2));
memset(tempMatLine, 0, sizeof(unsigned int) * (t->size * 2) * (t->size * 2)); memset(tempMatLine, 0, sizeof(int) * (graph->size * 2) * (graph->size * 2));
for (int k = 0; k < t->size * 2; k++) { for (int k = 0; k < graph->size * 2; k++) {
tempMat[k] = tempMatLine + k * (t->size * 2); tempMat[k] = tempMatLine + k * (graph->size * 2);
} }
for (int i = 0; i < graph->size; i++) {
for (int i = 0; i < t->size; i++) { memcpy(tempMat[i], graph->adjMat[i], sizeof(int) * graph->size); // 原数据复制到新数组
memcpy(tempMat[i], t->adjMat[i], sizeof(unsigned int) * t->size); // 原数据复制到新数组
} }
for (int i = 0; i < graph->size; i++) {
for (int i = 0; i < t->size; i++) { tempMat[i][graph->size] = 0; // 将新增列置 0
tempMat[i][t->size] = 0; // 将新增列置 0
} }
memset(tempMat[t->size], 0, sizeof(unsigned int) * (t->size + 1)); // 将新增行置 0 memset(tempMat[graph->size], 0, sizeof(int) * (graph->size + 1)); // 将新增行置 0
// 释放原数组 // 释放原数组
free(t->adjMat[0]); free(graph->adjMat[0]);
free(t->adjMat); free(graph->adjMat);
// 扩容后,指向新地址 // 扩容后,指向新地址
t->adjMat = tempMat; // 指向新的邻接矩阵地址 graph->adjMat = tempMat; // 指向新的邻接矩阵地址
t->capacity = t->size * 2; graph->capacity = graph->size * 2;
t->size++; graph->size++;
} }
/* 删除顶点 */ /* 删除顶点 */
void removeVertex(graphAdjMat *t, unsigned int index) { void removeVertex(GraphAdjMat *graph, int index) {
// 越界检查 // 越界检查
if (index < 0 || index >= t->size) { if (index < 0 || index >= graph->size) {
printf("Out of range in %s:%d\n", __FILE__, __LINE__); printf("Out of range in %s:%d\n", __FILE__, __LINE__);
exit(1); exit(1);
} }
for (int i = index; i < t->size - 1; i++) { for (int i = index; i < graph->size - 1; i++) {
t->vertices[i] = t->vertices[i + 1]; // 清除删除的顶点,并将其后所有顶点前移 graph->vertices[i] = graph->vertices[i + 1]; // 清除删除的顶点,并将其后所有顶点前移
} }
t->vertices[t->size - 1] = 0; // 将被前移的最后一个顶点置 0 graph->vertices[graph->size - 1] = 0; // 将被前移的最后一个顶点置 0
// 清除邻接矩阵中删除的列 // 清除邻接矩阵中删除的列
for (int i = 0; i < t->size - 1; i++) { for (int i = 0; i < graph->size - 1; i++) {
if (i < index) { if (i < index) {
for (int j = index; j < t->size - 1; j++) { for (int j = index; j < graph->size - 1; j++) {
t->adjMat[i][j] = t->adjMat[i][j + 1]; // 被删除列后的所有列前移 graph->adjMat[i][j] = graph->adjMat[i][j + 1]; // 被删除列后的所有列前移
} }
} else { } else {
memcpy(t->adjMat[i], t->adjMat[i + 1], sizeof(unsigned int) * t->size); // 被删除行的下方所有行上移 memcpy(graph->adjMat[i], graph->adjMat[i + 1], sizeof(int) * graph->size); // 被删除行的下方所有行上移
for (int j = index; j < t->size; j++) { for (int j = index; j < graph->size; j++) {
t->adjMat[i][j] = t->adjMat[i][j + 1]; // 被删除列后的所有列前移 graph->adjMat[i][j] = graph->adjMat[i][j + 1]; // 被删除列后的所有列前移
} }
} }
} }
t->size--; graph->size--;
} }
/* 打印顶点与邻接矩阵 */ /* 打印顶点与邻接矩阵 */
void printGraph(graphAdjMat *t) { void printGraph(GraphAdjMat *graph) {
if (t->size == 0) { if (graph->size == 0) {
printf("graph is empty\n"); printf("graph is empty\n");
return; return;
} }
printf("顶点列表 = ["); printf("顶点列表 = [");
for (int i = 0; i < t->size; i++) { for (int i = 0; i < graph->size; i++) {
if (i != t->size - 1) { if (i != graph->size - 1) {
printf("%d, ", t->vertices[i]); printf("%d, ", graph->vertices[i]);
} else { } else {
printf("%d", t->vertices[i]); printf("%d", graph->vertices[i]);
} }
} }
printf("]\n"); printf("]\n");
printf("邻接矩阵 =\n[\n"); printf("邻接矩阵 =\n[\n");
for (int i = 0; i < t->size; i++) { for (int i = 0; i < graph->size; i++) {
printf(" ["); printf(" [");
for (int j = 0; j < t->size; j++) { for (int j = 0; j < graph->size; j++) {
if (j != t->size - 1) { if (j != graph->size - 1) {
printf("%u, ", t->adjMat[i][j]); printf("%u, ", graph->adjMat[i][j]);
} else { } else {
printf("%u", t->adjMat[i][j]); printf("%u", graph->adjMat[i][j]);
} }
} }
printf("],\n"); printf("],\n");
@ -1091,26 +1081,24 @@ comments: true
} }
/* 构造函数 */ /* 构造函数 */
graphAdjMat *newGraphAjdMat(unsigned int numberVertices, int *vertices, unsigned int **adjMat) { GraphAdjMat *newGraphAjdMat(int numberVertices, int *vertices, int **adjMat) {
// 申请内存 // 申请内存
graphAdjMat *newGraph = (graphAdjMat *)malloc(sizeof(graphAdjMat)); // 为图分配内存 GraphAdjMat *newGraph = (GraphAdjMat *)malloc(sizeof(GraphAdjMat)); // 为图分配内存
newGraph->vertices = (int *)malloc(sizeof(int) * numberVertices * 2); // 为顶点列表分配内存 newGraph->vertices = (int *)malloc(sizeof(int) * numberVertices * 2); // 为顶点列表分配内存
newGraph->adjMat = (unsigned int **)malloc(sizeof(unsigned int *) * numberVertices * 2); // 为邻接矩阵分配二维内存 newGraph->adjMat = (int **)malloc(sizeof(int *) * numberVertices * 2); // 为邻接矩阵分配二维内存
unsigned int *temp = (unsigned int *)malloc(sizeof(unsigned int) * numberVertices * 2 * numberVertices * 2); // 为邻接矩阵分配一维内存 int *temp = (int *)malloc(sizeof(int) * numberVertices * 2 * numberVertices * 2); // 为邻接矩阵分配一维内存
newGraph->size = numberVertices; // 初始化顶点数量 newGraph->size = numberVertices; // 初始化顶点数量
newGraph->capacity = numberVertices * 2; // 初始化图容量 newGraph->capacity = numberVertices * 2; // 初始化图容量
// 配置二维数组 // 配置二维数组
for (int i = 0; i < numberVertices * 2; i++) { for (int i = 0; i < numberVertices * 2; i++) {
newGraph->adjMat[i] = temp + i * numberVertices * 2; // 将二维指针指向一维数组 newGraph->adjMat[i] = temp + i * numberVertices * 2; // 将二维指针指向一维数组
} }
// 赋值 // 赋值
memcpy(newGraph->vertices, vertices, sizeof(int) * numberVertices); memcpy(newGraph->vertices, vertices, sizeof(int) * numberVertices);
for (int i = 0; i < numberVertices; i++) { for (int i = 0; i < numberVertices; i++) {
memcpy(newGraph->adjMat[i], adjMat[i], sizeof(unsigned int) * numberVertices); // 将传入的邻接矩阵赋值给结构体内邻接矩阵 memcpy(newGraph->adjMat[i], adjMat[i],
sizeof(int) * numberVertices); // 将传入的邻接矩阵赋值给结构体内邻接矩阵
} }
// 返回结构体指针 // 返回结构体指针
return newGraph; return newGraph;
} }
@ -1979,105 +1967,96 @@ comments: true
```c title="graph_adjacency_list.c" ```c title="graph_adjacency_list.c"
/* 基于邻接链表实现的无向图类结构 */ /* 基于邻接链表实现的无向图类结构 */
struct graphAdjList { typedef struct {
Vertex **verticesList; // 邻接表 Vertex **vertices; // 邻接表
unsigned int size; // 顶点数量 unsigned int size; // 顶点数量
unsigned int capacity; // 顶点容量 unsigned int capacity; // 顶点容量
}; } GraphAdjList;
typedef struct graphAdjList graphAdjList;
/* 添加边 */ /* 添加边 */
void addEdge(graphAdjList *t, int i, int j) { void addEdge(GraphAdjList *graph, int i, int j) {
// 越界检查 // 越界检查
if (i < 0 || j < 0 || i == j || i >= t->size || j >= t->size) { if (i < 0 || j < 0 || i == j || i >= graph->size || j >= graph->size) {
printf("Out of range in %s:%d\n", __FILE__, __LINE__); printf("Out of range in %s:%d\n", __FILE__, __LINE__);
return; return;
} }
// 查找欲添加边的顶点 vet1 - vet2 // 查找欲添加边的顶点 vet1 - vet2
Vertex *vet1 = t->verticesList[i]; Vertex *vet1 = graph->vertices[i];
Vertex *vet2 = t->verticesList[j]; Vertex *vet2 = graph->vertices[j];
// 连接顶点 vet1 - vet2 // 连接顶点 vet1 - vet2
pushBack(vet1->linked, vet2); pushBack(vet1->list, vet2);
pushBack(vet2->linked, vet1); pushBack(vet2->list, vet1);
} }
/* 删除边 */ /* 删除边 */
void removeEdge(graphAdjList *t, int i, int j) { void removeEdge(GraphAdjList *graph, int i, int j) {
// 越界检查 // 越界检查
if (i < 0 || j < 0 || i == j || i >= t->size || j >= t->size) { if (i < 0 || j < 0 || i == j || i >= graph->size || j >= graph->size) {
printf("Out of range in %s:%d\n", __FILE__, __LINE__); printf("Out of range in %s:%d\n", __FILE__, __LINE__);
return; return;
} }
// 查找欲删除边的顶点 vet1 - vet2 // 查找欲删除边的顶点 vet1 - vet2
Vertex *vet1 = t->verticesList[i]; Vertex *vet1 = graph->vertices[i];
Vertex *vet2 = t->verticesList[j]; Vertex *vet2 = graph->vertices[j];
// 移除待删除边 vet1 - vet2 // 移除待删除边 vet1 - vet2
removeLink(vet1->linked, vet2); removeLink(vet1->list, vet2);
removeLink(vet2->linked, vet1); removeLink(vet2->list, vet1);
} }
/* 添加顶点 */ /* 添加顶点 */
void addVertex(graphAdjList *t, int val) { void addVertex(GraphAdjList *graph, int val) {
// 若大小超过容量,则扩容 // 若大小超过容量,则扩容
if (t->size >= t->capacity) { if (graph->size >= graph->capacity) {
Vertex **tempList = (Vertex **)malloc(sizeof(Vertex *) * 2 * t->capacity); Vertex **tempList = (Vertex **)malloc(sizeof(Vertex *) * 2 * graph->capacity);
memcpy(tempList, t->verticesList, sizeof(Vertex *) * t->size); memcpy(tempList, graph->vertices, sizeof(Vertex *) * graph->size);
free(t->verticesList); // 释放原邻接表内存 free(graph->vertices); // 释放原邻接表内存
t->verticesList = tempList; // 指向新邻接表 graph->vertices = tempList; // 指向新邻接表
t->capacity = t->capacity * 2; // 容量扩大至2倍 graph->capacity = graph->capacity * 2; // 容量扩大至2倍
} }
// 申请新顶点内存并将新顶点地址存入顶点列表 // 申请新顶点内存并将新顶点地址存入顶点列表
Vertex *newV = newVertex(val); // 建立新顶点 Vertex *newV = newVertex(val); // 建立新顶点
newV->pos = t->size; // 为新顶点标记下标 newV->pos = graph->size; // 为新顶点标记下标
newV->linked = newLinklist(newV); // 为新顶点建立链表 newV->list = newLinklist(newV); // 为新顶点建立链表
t->verticesList[t->size] = newV; // 将新顶点加入邻接表 graph->vertices[graph->size] = newV; // 将新顶点加入邻接表
t->size++; graph->size++;
} }
/* 删除顶点 */ /* 删除顶点 */
void removeVertex(graphAdjList *t, unsigned int index) { void removeVertex(GraphAdjList *graph, unsigned int index) {
// 越界检查 // 越界检查
if (index < 0 || index >= t->size) { if (index < 0 || index >= graph->size) {
printf("Out of range in %s:%d\n", __FILE__, __LINE__); printf("Out of range in %s:%d\n", __FILE__, __LINE__);
exit(1); exit(1);
} }
Vertex *vet = graph->vertices[index]; // 查找待删节点
Vertex *vet = t->verticesList[index]; // 查找待删节点
if (vet == 0) { // 若不存在该节点,则返回 if (vet == 0) { // 若不存在该节点,则返回
printf("index is:%d\n", index); printf("index is:%d\n", index);
printf("Out of range in %s:%d\n", __FILE__, __LINE__); printf("Out of range in %s:%d\n", __FILE__, __LINE__);
return; return;
} }
// 遍历待删除顶点的链表,将所有与待删除结点有关的边删除 // 遍历待删除顶点的链表,将所有与待删除结点有关的边删除
Node *temp = vet->linked->head->next; Node *temp = vet->list->head->next;
while (temp != 0) { while (temp != 0) {
removeLink(temp->val->linked, vet); // 删除与该顶点有关的边 removeLink(temp->val->list, vet); // 删除与该顶点有关的边
temp = temp->next; temp = temp->next;
} }
// 将顶点前移 // 将顶点前移
for (int i = index; i < t->size - 1; i++) { for (int i = index; i < graph->size - 1; i++) {
t->verticesList[i] = t->verticesList[i + 1]; // 顶点前移 graph->vertices[i] = graph->vertices[i + 1]; // 顶点前移
t->verticesList[i]->pos--; // 所有前移的顶点索引值减1 graph->vertices[i]->pos--; // 所有前移的顶点索引值减1
} }
t->verticesList[t->size - 1] = 0; // 将被删除顶点的位置置 0 graph->vertices[graph->size - 1] = 0; // 将被删除顶点的位置置 0
t->size--; graph->size--;
// 释放内存 // 释放内存
freeVertex(vet); freeVertex(vet);
} }
/* 打印顶点与邻接矩阵 */ /* 打印顶点与邻接矩阵 */
void printGraph(graphAdjList *t) { void printGraph(GraphAdjList *graph) {
printf("邻接表 =\n"); printf("邻接表 =\n");
for (int i = 0; i < t->size; i++) { for (int i = 0; i < graph->size; i++) {
Node *n = t->verticesList[i]->linked->head->next; Node *n = graph->vertices[i]->list->head->next;
printf("%d: [", t->verticesList[i]->val); printf("%d: [", graph->vertices[i]->val);
while (n != 0) { while (n != 0) {
if (n->next != 0) { if (n->next != 0) {
printf("%d, ", n->val->val); printf("%d, ", n->val->val);
@ -2091,14 +2070,14 @@ comments: true
} }
/* 构造函数 */ /* 构造函数 */
graphAdjList *newGraphAdjList(unsigned int verticesCapacity) { GraphAdjList *newGraphAdjList(unsigned int verticesCapacity) {
// 申请内存 // 申请内存
graphAdjList *newGraph = (graphAdjList *)malloc(sizeof(graphAdjList)); GraphAdjList *newGraph = (GraphAdjList *)malloc(sizeof(GraphAdjList));
// 建立顶点表并分配内存 // 建立顶点表并分配内存
newGraph->verticesList = (Vertex **)malloc(sizeof(Vertex *) * verticesCapacity); // 为顶点列表分配内存 newGraph->vertices = (Vertex **)malloc(sizeof(Vertex *) * verticesCapacity); // 为顶点列表分配内存
memset(newGraph->verticesList, 0, sizeof(Vertex *) * verticesCapacity); // 顶点列表置 0 memset(newGraph->vertices, 0, sizeof(Vertex *) * verticesCapacity); // 顶点列表置 0
newGraph->size = 0; // 初始化顶点数量 newGraph->size = 0; // 初始化顶点数量
newGraph->capacity = verticesCapacity; // 初始化顶点容量 newGraph->capacity = verticesCapacity; // 初始化顶点容量
// 返回图指针 // 返回图指针
return newGraph; return newGraph;
} }

View file

@ -344,21 +344,21 @@ BFS 通常借助队列来实现。队列具有“先入先出”的性质,这
```c title="graph_bfs.c" ```c title="graph_bfs.c"
/* 广度优先遍历 */ /* 广度优先遍历 */
// 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点 // 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
Vertex **graphBFS(graphAdjList *t, Vertex *startVet) { Vertex **graphBFS(GraphAdjList *t, Vertex *startVet) {
// 顶点遍历序列 // 顶点遍历序列
Vertex **res = (Vertex **)malloc(sizeof(Vertex *) * t->size); Vertex **res = (Vertex **)malloc(sizeof(Vertex *) * t->size);
memset(res, 0, sizeof(Vertex *) * t->size); memset(res, 0, sizeof(Vertex *) * t->size);
// 队列用于实现 BFS // 队列用于实现 BFS
queue *que = newQueue(t->size); Queue *que = newQueue(t->size);
// 哈希表,用于记录已被访问过的顶点 // 哈希表,用于记录已被访问过的顶点
hashTable *visited = newHash(t->size); HashTable *visited = newHash(t->size);
int resIndex = 0; int resIndex = 0;
queuePush(que, startVet); // 将第一个元素入队 queuePush(que, startVet); // 将第一个元素入队
hashMark(visited, startVet->pos); // 标记第一个入队的顶点 hashMark(visited, startVet->pos); // 标记第一个入队的顶点
// 以顶点 vet 为起点,循环直至访问完所有顶点 // 以顶点 vet 为起点,循环直至访问完所有顶点
while (que->head < que->tail) { while (que->head < que->tail) {
// 遍历该顶点的边链表,将所有与该顶点有连接的,并且未被标记的顶点入队 // 遍历该顶点的边链表,将所有与该顶点有连接的,并且未被标记的顶点入队
Node *n = queueTop(que)->linked->head->next; Node *n = queueTop(que)->list->head->next;
while (n != 0) { while (n != 0) {
// 查询哈希表,若该索引的顶点已入队,则跳过,否则入队并标记 // 查询哈希表,若该索引的顶点已入队,则跳过,否则入队并标记
if (hashQuery(visited, n->val->pos) == 1) { if (hashQuery(visited, n->val->pos) == 1) {
@ -751,7 +751,7 @@ BFS 通常借助队列来实现。队列具有“先入先出”的性质,这
```c title="graph_dfs.c" ```c title="graph_dfs.c"
/* 深度优先遍历 DFS 辅助函数 */ /* 深度优先遍历 DFS 辅助函数 */
int resIndex = 0; int resIndex = 0;
void dfs(graphAdjList *graph, hashTable *visited, Vertex *vet, Vertex **res) { void dfs(GraphAdjList *graph, HashTable *visited, Vertex *vet, Vertex **res) {
if (hashQuery(visited, vet->pos) == 1) { if (hashQuery(visited, vet->pos) == 1) {
return; // 跳过已被访问过的顶点 return; // 跳过已被访问过的顶点
} }
@ -759,7 +759,7 @@ BFS 通常借助队列来实现。队列具有“先入先出”的性质,这
res[resIndex] = vet; // 将顶点存入数组 res[resIndex] = vet; // 将顶点存入数组
resIndex++; resIndex++;
// 遍历该顶点链表 // 遍历该顶点链表
Node *n = vet->linked->head->next; Node *n = vet->list->head->next;
while (n != 0) { while (n != 0) {
// 递归访问邻接顶点 // 递归访问邻接顶点
dfs(graph, visited, n->val, res); dfs(graph, visited, n->val, res);
@ -770,12 +770,12 @@ BFS 通常借助队列来实现。队列具有“先入先出”的性质,这
/* 深度优先遍历 DFS */ /* 深度优先遍历 DFS */
// 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点 // 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
Vertex **graphDFS(graphAdjList *graph, Vertex *startVet) { Vertex **graphDFS(GraphAdjList *graph, Vertex *startVet) {
// 顶点遍历序列 // 顶点遍历序列
Vertex **res = (Vertex **)malloc(sizeof(Vertex *) * graph->size); Vertex **res = (Vertex **)malloc(sizeof(Vertex *) * graph->size);
memset(res, 0, sizeof(Vertex *) * graph->size); memset(res, 0, sizeof(Vertex *) * graph->size);
// 哈希表,用于记录已被访问过的顶点 // 哈希表,用于记录已被访问过的顶点
hashTable *visited = newHash(graph->size); HashTable *visited = newHash(graph->size);
dfs(graph, visited, startVet, res); dfs(graph, visited, startVet, res);
// 释放哈希表内存并将数组索引归零 // 释放哈希表内存并将数组索引归零
freeHash(visited); freeHash(visited);

View file

@ -428,12 +428,10 @@ comments: true
```c title="fractional_knapsack.c" ```c title="fractional_knapsack.c"
/* 物品 */ /* 物品 */
struct Item { typedef struct {
int w; // 物品重量 int w; // 物品重量
int v; // 物品价值 int v; // 物品价值
}; } Item;
typedef struct Item Item;
/* 分数背包:贪心 */ /* 分数背包:贪心 */
float fractionalKnapsack(int wgt[], int val[], int itemCount, int cap) { float fractionalKnapsack(int wgt[], int val[], int itemCount, int cap) {

View file

@ -264,7 +264,7 @@ comments: true
```c title="coin_change_greedy.c" ```c title="coin_change_greedy.c"
/* 零钱兑换:贪心 */ /* 零钱兑换:贪心 */
int coinChangeGreedy(int* coins, int size, int amt) { int coinChangeGreedy(int *coins, int size, int amt) {
// 假设 coins 列表有序 // 假设 coins 列表有序
int i = size - 1; int i = size - 1;
int count = 0; int count = 0;

View file

@ -1150,27 +1150,23 @@ comments: true
```c title="hash_map_chaining.c" ```c title="hash_map_chaining.c"
/* 链表节点 */ /* 链表节点 */
struct node { typedef struct Node {
Pair *pair; Pair *pair;
struct node *next; struct Node *next;
}; } Node;
typedef struct node Node;
/* 链式地址哈希表 */ /* 链式地址哈希表 */
struct hashMapChaining { typedef struct {
int size; // 键值对数量 int size; // 键值对数量
int capacity; // 哈希表容量 int capacity; // 哈希表容量
double loadThres; // 触发扩容的负载因子阈值 double loadThres; // 触发扩容的负载因子阈值
int extendRatio; // 扩容倍数 int extendRatio; // 扩容倍数
Node **buckets; // 桶数组 Node **buckets; // 桶数组
}; } HashMapChaining;
typedef struct hashMapChaining hashMapChaining;
/* 构造方法 */ /* 构造方法 */
hashMapChaining *initHashMapChaining() { HashMapChaining *initHashMapChaining() {
hashMapChaining *hashMap = (hashMapChaining *)malloc(sizeof(hashMapChaining)); HashMapChaining *hashMap = (HashMapChaining *)malloc(sizeof(HashMapChaining));
hashMap->size = 0; hashMap->size = 0;
hashMap->capacity = 4; hashMap->capacity = 4;
hashMap->loadThres = 2.0 / 3.0; hashMap->loadThres = 2.0 / 3.0;
@ -1183,7 +1179,7 @@ comments: true
} }
/* 析构方法 */ /* 析构方法 */
void freeHashMapChaining(hashMapChaining *hashMap) { void freeHashMapChaining(HashMapChaining *hashMap) {
for (int i = 0; i < hashMap->capacity; i++) { for (int i = 0; i < hashMap->capacity; i++) {
Node *cur = hashMap->buckets[i]; Node *cur = hashMap->buckets[i];
while (cur) { while (cur) {
@ -1198,17 +1194,17 @@ comments: true
} }
/* 哈希函数 */ /* 哈希函数 */
int hashFunc(hashMapChaining *hashMap, int key) { int hashFunc(HashMapChaining *hashMap, int key) {
return key % hashMap->capacity; return key % hashMap->capacity;
} }
/* 负载因子 */ /* 负载因子 */
double loadFactor(hashMapChaining *hashMap) { double loadFactor(HashMapChaining *hashMap) {
return (double)hashMap->size / (double)hashMap->capacity; return (double)hashMap->size / (double)hashMap->capacity;
} }
/* 查询操作 */ /* 查询操作 */
char *get(hashMapChaining *hashMap, int key) { char *get(HashMapChaining *hashMap, int key) {
int index = hashFunc(hashMap, key); int index = hashFunc(hashMap, key);
// 遍历桶,若找到 key 则返回对应 val // 遍历桶,若找到 key 则返回对应 val
Node *cur = hashMap->buckets[index]; Node *cur = hashMap->buckets[index];
@ -1222,7 +1218,7 @@ comments: true
} }
/* 添加操作 */ /* 添加操作 */
void put(hashMapChaining *hashMap, int key, const char *val) { void put(HashMapChaining *hashMap, int key, const char *val) {
// 当负载因子超过阈值时,执行扩容 // 当负载因子超过阈值时,执行扩容
if (loadFactor(hashMap) > hashMap->loadThres) { if (loadFactor(hashMap) > hashMap->loadThres) {
extend(hashMap); extend(hashMap);
@ -1249,7 +1245,7 @@ comments: true
} }
/* 扩容哈希表 */ /* 扩容哈希表 */
void extend(hashMapChaining *hashMap) { void extend(HashMapChaining *hashMap) {
// 暂存原哈希表 // 暂存原哈希表
int oldCapacity = hashMap->capacity; int oldCapacity = hashMap->capacity;
Node **oldBuckets = hashMap->buckets; Node **oldBuckets = hashMap->buckets;
@ -1277,7 +1273,7 @@ comments: true
} }
/* 删除操作 */ /* 删除操作 */
void removeKey(hashMapChaining *hashMap, int key) { void removeKey(HashMapChaining *hashMap, int key) {
int index = hashFunc(hashMap, key); int index = hashFunc(hashMap, key);
Node *cur = hashMap->buckets[index]; Node *cur = hashMap->buckets[index];
Node *pre = NULL; Node *pre = NULL;
@ -1301,7 +1297,7 @@ comments: true
} }
/* 打印哈希表 */ /* 打印哈希表 */
void print(hashMapChaining *hashMap) { void print(HashMapChaining *hashMap) {
for (int i = 0; i < hashMap->capacity; i++) { for (int i = 0; i < hashMap->capacity; i++) {
Node *cur = hashMap->buckets[i]; Node *cur = hashMap->buckets[i];
printf("["); printf("[");
@ -2647,20 +2643,18 @@ comments: true
```c title="hash_map_open_addressing.c" ```c title="hash_map_open_addressing.c"
/* 开放寻址哈希表 */ /* 开放寻址哈希表 */
struct hashMapOpenAddressing { typedef struct {
int size; // 键值对数量 int size; // 键值对数量
int capacity; // 哈希表容量 int capacity; // 哈希表容量
double loadThres; // 触发扩容的负载因子阈值 double loadThres; // 触发扩容的负载因子阈值
int extendRatio; // 扩容倍数 int extendRatio; // 扩容倍数
Pair **buckets; // 桶数组 Pair **buckets; // 桶数组
Pair *TOMBSTONE; // 删除标记 Pair *TOMBSTONE; // 删除标记
}; } HashMapOpenAddressing;
typedef struct hashMapOpenAddressing hashMapOpenAddressing;
/* 构造方法 */ /* 构造方法 */
hashMapOpenAddressing *newHashMapOpenAddressing() { HashMapOpenAddressing *newHashMapOpenAddressing() {
hashMapOpenAddressing *hashMap = (hashMapOpenAddressing *)malloc(sizeof(hashMapOpenAddressing)); HashMapOpenAddressing *hashMap = (HashMapOpenAddressing *)malloc(sizeof(HashMapOpenAddressing));
hashMap->size = 0; hashMap->size = 0;
hashMap->capacity = 4; hashMap->capacity = 4;
hashMap->loadThres = 2.0 / 3.0; hashMap->loadThres = 2.0 / 3.0;
@ -2674,7 +2668,7 @@ comments: true
} }
/* 析构方法 */ /* 析构方法 */
void delHashMapOpenAddressing(hashMapOpenAddressing *hashMap) { void delHashMapOpenAddressing(HashMapOpenAddressing *hashMap) {
for (int i = 0; i < hashMap->capacity; i++) { for (int i = 0; i < hashMap->capacity; i++) {
Pair *pair = hashMap->buckets[i]; Pair *pair = hashMap->buckets[i];
if (pair != NULL && pair != hashMap->TOMBSTONE) { if (pair != NULL && pair != hashMap->TOMBSTONE) {
@ -2685,17 +2679,17 @@ comments: true
} }
/* 哈希函数 */ /* 哈希函数 */
int hashFunc(hashMapOpenAddressing *hashMap, int key) { int hashFunc(HashMapOpenAddressing *hashMap, int key) {
return key % hashMap->capacity; return key % hashMap->capacity;
} }
/* 负载因子 */ /* 负载因子 */
double loadFactor(hashMapOpenAddressing *hashMap) { double loadFactor(HashMapOpenAddressing *hashMap) {
return (double)hashMap->size / (double)hashMap->capacity; return (double)hashMap->size / (double)hashMap->capacity;
} }
/* 搜索 key 对应的桶索引 */ /* 搜索 key 对应的桶索引 */
int findBucket(hashMapOpenAddressing *hashMap, int key) { int findBucket(HashMapOpenAddressing *hashMap, int key) {
int index = hashFunc(hashMap, key); int index = hashFunc(hashMap, key);
int firstTombstone = -1; int firstTombstone = -1;
// 线性探测,当遇到空桶时跳出 // 线性探测,当遇到空桶时跳出
@ -2722,7 +2716,7 @@ comments: true
} }
/* 查询操作 */ /* 查询操作 */
char *get(hashMapOpenAddressing *hashMap, int key) { char *get(HashMapOpenAddressing *hashMap, int key) {
// 搜索 key 对应的桶索引 // 搜索 key 对应的桶索引
int index = findBucket(hashMap, key); int index = findBucket(hashMap, key);
// 若找到键值对,则返回对应 val // 若找到键值对,则返回对应 val
@ -2734,7 +2728,7 @@ comments: true
} }
/* 添加操作 */ /* 添加操作 */
void put(hashMapOpenAddressing *hashMap, int key, char *val) { void put(HashMapOpenAddressing *hashMap, int key, char *val) {
// 当负载因子超过阈值时,执行扩容 // 当负载因子超过阈值时,执行扩容
if (loadFactor(hashMap) > hashMap->loadThres) { if (loadFactor(hashMap) > hashMap->loadThres) {
extend(hashMap); extend(hashMap);
@ -2761,7 +2755,7 @@ comments: true
} }
/* 删除操作 */ /* 删除操作 */
void removeItem(hashMapOpenAddressing *hashMap, int key) { void removeItem(HashMapOpenAddressing *hashMap, int key) {
// 搜索 key 对应的桶索引 // 搜索 key 对应的桶索引
int index = findBucket(hashMap, key); int index = findBucket(hashMap, key);
// 若找到键值对,则用删除标记覆盖它 // 若找到键值对,则用删除标记覆盖它
@ -2775,7 +2769,7 @@ comments: true
} }
/* 扩容哈希表 */ /* 扩容哈希表 */
void extend(hashMapOpenAddressing *hashMap) { void extend(HashMapOpenAddressing *hashMap) {
// 暂存原哈希表 // 暂存原哈希表
Pair **bucketsTmp = hashMap->buckets; Pair **bucketsTmp = hashMap->buckets;
int oldCapacity = hashMap->capacity; int oldCapacity = hashMap->capacity;
@ -2796,7 +2790,7 @@ comments: true
} }
/* 打印哈希表 */ /* 打印哈希表 */
void print(hashMapOpenAddressing *hashMap) { void print(HashMapOpenAddressing *hashMap) {
for (int i = 0; i < hashMap->capacity; i++) { for (int i = 0; i < hashMap->capacity; i++) {
Pair *pair = hashMap->buckets[i]; Pair *pair = hashMap->buckets[i];
if (pair == NULL) { if (pair == NULL) {
@ -2820,7 +2814,7 @@ comments: true
平方探测与线性探测类似,都是开放寻址的常见策略之一。当发生冲突时,平方探测不是简单地跳过一个固定的步数,而是跳过“探测次数的平方”的步数,即 $1, 4, 9, \dots$ 步。 平方探测与线性探测类似,都是开放寻址的常见策略之一。当发生冲突时,平方探测不是简单地跳过一个固定的步数,而是跳过“探测次数的平方”的步数,即 $1, 4, 9, \dots$ 步。
平方探测主要具有以下优势。 平方探测主要具有以下优势。
- 平方探测通过跳过平方的距离,试图缓解线性探测的聚集效应。 - 平方探测通过跳过平方的距离,试图缓解线性探测的聚集效应。
- 平方探测会跳过更大的距离来寻找空位置,有助于数据分布得更加均匀。 - 平方探测会跳过更大的距离来寻找空位置,有助于数据分布得更加均匀。

View file

@ -1405,39 +1405,35 @@ index = hash(key) % capacity
```c title="array_hash_map.c" ```c title="array_hash_map.c"
/* 键值对 int->string */ /* 键值对 int->string */
struct pair { typedef struct {
int key; int key;
char *val; char *val;
}; } Pair;
typedef struct pair pair;
/* 基于数组简易实现的哈希表 */ /* 基于数组简易实现的哈希表 */
struct arrayHashMap { typedef struct {
pair *buckets[HASH_MAP_DEFAULT_SIZE]; Pair *buckets[HASH_MAP_DEFAULT_SIZE];
}; } ArrayHashMap;
typedef struct arrayHashMap arrayHashMap;
/* 哈希表初始化函数 */ /* 哈希表初始化函数 */
arrayHashMap *newArrayHashMap() { ArrayHashMap *newArrayHashMap() {
arrayHashMap *map = malloc(sizeof(arrayHashMap)); ArrayHashMap *map = malloc(sizeof(ArrayHashMap));
return map; return map;
} }
/* 添加操作 */ /* 添加操作 */
void put(arrayHashMap *d, const int key, const char *val) { void put(ArrayHashMap *d, const int key, const char *val) {
pair *pair = malloc(sizeof(pair)); Pair *Pair = malloc(sizeof(Pair));
pair->key = key; Pair->key = key;
pair->val = malloc(strlen(val) + 1); Pair->val = malloc(strlen(val) + 1);
strcpy(pair->val, val); strcpy(Pair->val, val);
int index = hashFunc(key); int index = hashFunc(key);
d->buckets[index] = pair; d->buckets[index] = Pair;
} }
/* 删除操作 */ /* 删除操作 */
void removeItem(arrayHashMap *d, const int key) { void removeItem(ArrayHashMap *d, const int key) {
int index = hashFunc(key); int index = hashFunc(key);
free(d->buckets[index]->val); free(d->buckets[index]->val);
free(d->buckets[index]); free(d->buckets[index]);
@ -1445,8 +1441,8 @@ index = hash(key) % capacity
} }
/* 获取所有键值对 */ /* 获取所有键值对 */
void pairSet(arrayHashMap *d, mapSet *set) { void pairSet(ArrayHashMap *d, MapSet *set) {
pair *entries; Pair *entries;
int i = 0, index = 0; int i = 0, index = 0;
int total = 0; int total = 0;
@ -1457,7 +1453,7 @@ index = hash(key) % capacity
} }
} }
entries = malloc(sizeof(pair) * total); entries = malloc(sizeof(Pair) * total);
for (i = 0; i < HASH_MAP_DEFAULT_SIZE; i++) { for (i = 0; i < HASH_MAP_DEFAULT_SIZE; i++) {
if (d->buckets[i] != NULL) { if (d->buckets[i] != NULL) {
entries[index].key = d->buckets[i]->key; entries[index].key = d->buckets[i]->key;
@ -1472,7 +1468,7 @@ index = hash(key) % capacity
} }
/* 获取所有键 */ /* 获取所有键 */
void keySet(arrayHashMap *d, mapSet *set) { void keySet(ArrayHashMap *d, MapSet *set) {
int *keys; int *keys;
int i = 0, index = 0; int i = 0, index = 0;
int total = 0; int total = 0;
@ -1497,7 +1493,7 @@ index = hash(key) % capacity
} }
/* 获取所有值 */ /* 获取所有值 */
void valueSet(arrayHashMap *d, mapSet *set) { void valueSet(ArrayHashMap *d, MapSet *set) {
char **vals; char **vals;
int i = 0, index = 0; int i = 0, index = 0;
int total = 0; int total = 0;
@ -1522,11 +1518,11 @@ index = hash(key) % capacity
} }
/* 打印哈希表 */ /* 打印哈希表 */
void print(arrayHashMap *d) { void print(ArrayHashMap *d) {
int i; int i;
mapSet set; MapSet set;
pairSet(d, &set); pairSet(d, &set);
pair *entries = (pair *)set.set; Pair *entries = (Pair *)set.set;
for (i = 0; i < set.len; i++) { for (i = 0; i < set.len; i++) {
printf("%d -> %s\n", entries[i].key, entries[i].val); printf("%d -> %s\n", entries[i].key, entries[i].val);
} }

View file

@ -172,9 +172,9 @@ comments: true
```c title="my_heap.c" ```c title="my_heap.c"
/* 构造函数,根据切片建堆 */ /* 构造函数,根据切片建堆 */
maxHeap *newMaxHeap(int nums[], int size) { MaxHeap *newMaxHeap(int nums[], int size) {
// 所有元素入堆 // 所有元素入堆
maxHeap *h = (maxHeap *)malloc(sizeof(maxHeap)); MaxHeap *h = (MaxHeap *)malloc(sizeof(MaxHeap));
h->size = size; h->size = size;
memcpy(h->data, nums, size * sizeof(int)); memcpy(h->data, nums, size * sizeof(int));
for (int i = parent(h, size - 1); i >= 0; i--) { for (int i = parent(h, size - 1); i >= 0; i--) {

View file

@ -565,17 +565,17 @@ comments: true
```c title="my_heap.c" ```c title="my_heap.c"
/* 获取左子节点索引 */ /* 获取左子节点索引 */
int left(maxHeap *h, int i) { int left(MaxHeap *h, int i) {
return 2 * i + 1; return 2 * i + 1;
} }
/* 获取右子节点索引 */ /* 获取右子节点索引 */
int right(maxHeap *h, int i) { int right(MaxHeap *h, int i) {
return 2 * i + 2; return 2 * i + 2;
} }
/* 获取父节点索引 */ /* 获取父节点索引 */
int parent(maxHeap *h, int i) { int parent(MaxHeap *h, int i) {
return (i - 1) / 2; return (i - 1) / 2;
} }
``` ```
@ -697,7 +697,7 @@ comments: true
```c title="my_heap.c" ```c title="my_heap.c"
/* 访问堆顶元素 */ /* 访问堆顶元素 */
int peek(maxHeap *h) { int peek(MaxHeap *h) {
return h->data[0]; return h->data[0];
} }
``` ```
@ -1026,7 +1026,7 @@ comments: true
```c title="my_heap.c" ```c title="my_heap.c"
/* 元素入堆 */ /* 元素入堆 */
void push(maxHeap *h, int val) { void push(MaxHeap *h, int val) {
// 默认情况下,不应该添加这么多节点 // 默认情况下,不应该添加这么多节点
if (h->size == MAX_SIZE) { if (h->size == MAX_SIZE) {
printf("heap is full!"); printf("heap is full!");
@ -1041,7 +1041,7 @@ comments: true
} }
/* 从节点 i 开始,从底至顶堆化 */ /* 从节点 i 开始,从底至顶堆化 */
void siftUp(maxHeap *h, int i) { void siftUp(MaxHeap *h, int i) {
while (true) { while (true) {
// 获取节点 i 的父节点 // 获取节点 i 的父节点
int p = parent(h, i); int p = parent(h, i);
@ -1519,7 +1519,7 @@ comments: true
```c title="my_heap.c" ```c title="my_heap.c"
/* 元素出堆 */ /* 元素出堆 */
int pop(maxHeap *h) { int pop(MaxHeap *h) {
// 判空处理 // 判空处理
if (isEmpty(h)) { if (isEmpty(h)) {
printf("heap is empty!"); printf("heap is empty!");
@ -1538,7 +1538,7 @@ comments: true
} }
/* 从节点 i 开始,从顶至底堆化 */ /* 从节点 i 开始,从顶至底堆化 */
void siftDown(maxHeap *h, int i) { void siftDown(MaxHeap *h, int i) {
while (true) { while (true) {
// 判断节点 i, l, r 中值最大的节点,记为 max // 判断节点 i, l, r 中值最大的节点,记为 max
int l = left(h, i); int l = left(h, i);

View file

@ -437,26 +437,24 @@ comments: true
```c title="two_sum.c" ```c title="two_sum.c"
/* 哈希表 */ /* 哈希表 */
struct hashTable { typedef struct {
int key; int key;
int val; int val;
UT_hash_handle hh; // 基于 uthash.h 实现 UT_hash_handle hh; // 基于 uthash.h 实现
}; } HashTable;
typedef struct hashTable hashTable;
/* 哈希表查询 */ /* 哈希表查询 */
hashTable *find(hashTable *h, int key) { HashTable *find(HashTable *h, int key) {
hashTable *tmp; HashTable *tmp;
HASH_FIND_INT(h, &key, tmp); HASH_FIND_INT(h, &key, tmp);
return tmp; return tmp;
} }
/* 哈希表元素插入 */ /* 哈希表元素插入 */
void insert(hashTable *h, int key, int val) { void insert(HashTable *h, int key, int val) {
hashTable *t = find(h, key); HashTable *t = find(h, key);
if (t == NULL) { if (t == NULL) {
hashTable *tmp = malloc(sizeof(hashTable)); HashTable *tmp = malloc(sizeof(HashTable));
tmp->key = key, tmp->val = val; tmp->key = key, tmp->val = val;
HASH_ADD_INT(h, key, tmp); HASH_ADD_INT(h, key, tmp);
} else { } else {
@ -466,9 +464,9 @@ comments: true
/* 方法二:辅助哈希表 */ /* 方法二:辅助哈希表 */
int *twoSumHashTable(int *nums, int numsSize, int target, int *returnSize) { int *twoSumHashTable(int *nums, int numsSize, int target, int *returnSize) {
hashTable *hashtable = NULL; HashTable *hashtable = NULL;
for (int i = 0; i < numsSize; i++) { for (int i = 0; i < numsSize; i++) {
hashTable *t = find(hashtable, target - nums[i]); HashTable *t = find(hashtable, target - nums[i]);
if (t != NULL) { if (t != NULL) {
int *res = malloc(sizeof(int) * 2); int *res = malloc(sizeof(int) * 2);
res[0] = t->val, res[1] = i; res[0] = t->val, res[1] = i;

View file

@ -1685,17 +1685,15 @@ comments: true
```c title="linkedlist_deque.c" ```c title="linkedlist_deque.c"
/* 双向链表节点 */ /* 双向链表节点 */
struct doublyListNode { typedef struct DoublyListNode {
int val; // 节点值 int val; // 节点值
struct doublyListNode *next; // 后继节点 struct DoublyListNode *next; // 后继节点
struct doublyListNode *prev; // 前驱节点 struct DoublyListNode *prev; // 前驱节点
}; } DoublyListNode;
typedef struct doublyListNode doublyListNode;
/* 构造函数 */ /* 构造函数 */
doublyListNode *newDoublyListNode(int num) { DoublyListNode *newDoublyListNode(int num) {
doublyListNode *new = (doublyListNode *)malloc(sizeof(doublyListNode)); DoublyListNode *new = (DoublyListNode *)malloc(sizeof(DoublyListNode));
new->val = num; new->val = num;
new->next = NULL; new->next = NULL;
new->prev = NULL; new->prev = NULL;
@ -1703,21 +1701,19 @@ comments: true
} }
/* 析构函数 */ /* 析构函数 */
void delDoublyListNode(doublyListNode *node) { void delDoublyListNode(DoublyListNode *node) {
free(node); free(node);
} }
/* 基于双向链表实现的双向队列 */ /* 基于双向链表实现的双向队列 */
struct linkedListDeque { typedef struct {
doublyListNode *front, *rear; // 头节点 front ,尾节点 rear DoublyListNode *front, *rear; // 头节点 front ,尾节点 rear
int queSize; // 双向队列的长度 int queSize; // 双向队列的长度
}; } LinkedListDeque;
typedef struct linkedListDeque linkedListDeque;
/* 构造函数 */ /* 构造函数 */
linkedListDeque *newLinkedListDeque() { LinkedListDeque *newLinkedListDeque() {
linkedListDeque *deque = (linkedListDeque *)malloc(sizeof(linkedListDeque)); LinkedListDeque *deque = (LinkedListDeque *)malloc(sizeof(LinkedListDeque));
deque->front = NULL; deque->front = NULL;
deque->rear = NULL; deque->rear = NULL;
deque->queSize = 0; deque->queSize = 0;
@ -1725,10 +1721,10 @@ comments: true
} }
/* 析构函数 */ /* 析构函数 */
void delLinkedListdeque(linkedListDeque *deque) { void delLinkedListdeque(LinkedListDeque *deque) {
// 释放所有节点 // 释放所有节点
for (int i = 0; i < deque->queSize && deque->front != NULL; i++) { for (int i = 0; i < deque->queSize && deque->front != NULL; i++) {
doublyListNode *tmp = deque->front; DoublyListNode *tmp = deque->front;
deque->front = deque->front->next; deque->front = deque->front->next;
free(tmp); free(tmp);
} }
@ -1737,18 +1733,18 @@ comments: true
} }
/* 获取队列的长度 */ /* 获取队列的长度 */
int size(linkedListDeque *deque) { int size(LinkedListDeque *deque) {
return deque->queSize; return deque->queSize;
} }
/* 判断队列是否为空 */ /* 判断队列是否为空 */
bool empty(linkedListDeque *deque) { bool empty(LinkedListDeque *deque) {
return (size(deque) == 0); return (size(deque) == 0);
} }
/* 入队 */ /* 入队 */
void push(linkedListDeque *deque, int num, bool isFront) { void push(LinkedListDeque *deque, int num, bool isFront) {
doublyListNode *node = newDoublyListNode(num); DoublyListNode *node = newDoublyListNode(num);
// 若链表为空,则令 front, rear 都指向node // 若链表为空,则令 front, rear 都指向node
if (empty(deque)) { if (empty(deque)) {
deque->front = deque->rear = node; deque->front = deque->rear = node;
@ -1771,36 +1767,36 @@ comments: true
} }
/* 队首入队 */ /* 队首入队 */
void pushFirst(linkedListDeque *deque, int num) { void pushFirst(LinkedListDeque *deque, int num) {
push(deque, num, true); push(deque, num, true);
} }
/* 队尾入队 */ /* 队尾入队 */
void pushLast(linkedListDeque *deque, int num) { void pushLast(LinkedListDeque *deque, int num) {
push(deque, num, false); push(deque, num, false);
} }
/* 访问队首元素 */ /* 访问队首元素 */
int peekFirst(linkedListDeque *deque) { int peekFirst(LinkedListDeque *deque) {
assert(size(deque) && deque->front); assert(size(deque) && deque->front);
return deque->front->val; return deque->front->val;
} }
/* 访问队尾元素 */ /* 访问队尾元素 */
int peekLast(linkedListDeque *deque) { int peekLast(LinkedListDeque *deque) {
assert(size(deque) && deque->rear); assert(size(deque) && deque->rear);
return deque->rear->val; return deque->rear->val;
} }
/* 出队 */ /* 出队 */
int pop(linkedListDeque *deque, bool isFront) { int pop(LinkedListDeque *deque, bool isFront) {
if (empty(deque)) if (empty(deque))
return -1; return -1;
int val; int val;
// 队首出队操作 // 队首出队操作
if (isFront) { if (isFront) {
val = peekFirst(deque); // 暂存头节点值 val = peekFirst(deque); // 暂存头节点值
doublyListNode *fNext = deque->front->next; DoublyListNode *fNext = deque->front->next;
if (fNext) { if (fNext) {
fNext->prev = NULL; fNext->prev = NULL;
deque->front->next = NULL; deque->front->next = NULL;
@ -1811,7 +1807,7 @@ comments: true
// 队尾出队操作 // 队尾出队操作
else { else {
val = peekLast(deque); // 暂存尾节点值 val = peekLast(deque); // 暂存尾节点值
doublyListNode *rPrev = deque->rear->prev; DoublyListNode *rPrev = deque->rear->prev;
if (rPrev) { if (rPrev) {
rPrev->next = NULL; rPrev->next = NULL;
deque->rear->prev = NULL; deque->rear->prev = NULL;
@ -1824,21 +1820,21 @@ comments: true
} }
/* 队首出队 */ /* 队首出队 */
int popFirst(linkedListDeque *deque) { int popFirst(LinkedListDeque *deque) {
return pop(deque, true); return pop(deque, true);
} }
/* 队尾出队 */ /* 队尾出队 */
int popLast(linkedListDeque *deque) { int popLast(LinkedListDeque *deque) {
return pop(deque, false); return pop(deque, false);
} }
/* 打印队列 */ /* 打印队列 */
void printLinkedListDeque(linkedListDeque *deque) { void printLinkedListDeque(LinkedListDeque *deque) {
int arr[deque->queSize]; int arr[deque->queSize];
// 拷贝链表中的数据到数组 // 拷贝链表中的数据到数组
int i; int i;
doublyListNode *node; DoublyListNode *node;
for (i = 0, node = deque->front; i < deque->queSize; i++) { for (i = 0, node = deque->front; i < deque->queSize; i++) {
arr[i] = node->val; arr[i] = node->val;
node = node->next; node = node->next;
@ -3119,18 +3115,16 @@ comments: true
```c title="array_deque.c" ```c title="array_deque.c"
/* 基于环形数组实现的双向队列 */ /* 基于环形数组实现的双向队列 */
struct arrayDeque { typedef struct {
int *nums; // 用于存储队列元素的数组 int *nums; // 用于存储队列元素的数组
int front; // 队首指针,指向队首元素 int front; // 队首指针,指向队首元素
int queSize; // 尾指针,指向队尾 + 1 int queSize; // 尾指针,指向队尾 + 1
int queCapacity; // 队列容量 int queCapacity; // 队列容量
}; } ArrayDeque;
typedef struct arrayDeque arrayDeque;
/* 构造函数 */ /* 构造函数 */
arrayDeque *newArrayDeque(int capacity) { ArrayDeque *newArrayDeque(int capacity) {
arrayDeque *deque = (arrayDeque *)malloc(sizeof(arrayDeque)); ArrayDeque *deque = (ArrayDeque *)malloc(sizeof(ArrayDeque));
// 初始化数组 // 初始化数组
deque->queCapacity = capacity; deque->queCapacity = capacity;
deque->nums = (int *)malloc(sizeof(int) * deque->queCapacity); deque->nums = (int *)malloc(sizeof(int) * deque->queCapacity);
@ -3139,28 +3133,28 @@ comments: true
} }
/* 析构函数 */ /* 析构函数 */
void delArrayDeque(arrayDeque *deque) { void delArrayDeque(ArrayDeque *deque) {
free(deque->nums); free(deque->nums);
deque->queCapacity = 0; deque->queCapacity = 0;
} }
/* 获取双向队列的容量 */ /* 获取双向队列的容量 */
int capacity(arrayDeque *deque) { int capacity(ArrayDeque *deque) {
return deque->queCapacity; return deque->queCapacity;
} }
/* 获取双向队列的长度 */ /* 获取双向队列的长度 */
int size(arrayDeque *deque) { int size(ArrayDeque *deque) {
return deque->queSize; return deque->queSize;
} }
/* 判断双向队列是否为空 */ /* 判断双向队列是否为空 */
bool empty(arrayDeque *deque) { bool empty(ArrayDeque *deque) {
return deque->queSize == 0; return deque->queSize == 0;
} }
/* 计算环形数组索引 */ /* 计算环形数组索引 */
int dequeIndex(arrayDeque *deque, int i) { int dequeIndex(ArrayDeque *deque, int i) {
// 通过取余操作实现数组首尾相连 // 通过取余操作实现数组首尾相连
// 当 i 越过数组尾部时,回到头部 // 当 i 越过数组尾部时,回到头部
// 当 i 越过数组头部后,回到尾部 // 当 i 越过数组头部后,回到尾部
@ -3168,7 +3162,7 @@ comments: true
} }
/* 队首入队 */ /* 队首入队 */
void pushFirst(arrayDeque *deque, int num) { void pushFirst(ArrayDeque *deque, int num) {
if (deque->queSize == capacity(deque)) { if (deque->queSize == capacity(deque)) {
printf("双向队列已满\r\n"); printf("双向队列已满\r\n");
return; return;
@ -3182,7 +3176,7 @@ comments: true
} }
/* 队尾入队 */ /* 队尾入队 */
void pushLast(arrayDeque *deque, int num) { void pushLast(ArrayDeque *deque, int num) {
if (deque->queSize == capacity(deque)) { if (deque->queSize == capacity(deque)) {
printf("双向队列已满\r\n"); printf("双向队列已满\r\n");
return; return;
@ -3195,14 +3189,14 @@ comments: true
} }
/* 访问队首元素 */ /* 访问队首元素 */
int peekFirst(arrayDeque *deque) { int peekFirst(ArrayDeque *deque) {
// 访问异常:双向队列为空 // 访问异常:双向队列为空
assert(empty(deque) == 0); assert(empty(deque) == 0);
return deque->nums[deque->front]; return deque->nums[deque->front];
} }
/* 访问队尾元素 */ /* 访问队尾元素 */
int peekLast(arrayDeque *deque) { int peekLast(ArrayDeque *deque) {
// 访问异常:双向队列为空 // 访问异常:双向队列为空
assert(empty(deque) == 0); assert(empty(deque) == 0);
int last = dequeIndex(deque, deque->front + deque->queSize - 1); int last = dequeIndex(deque, deque->front + deque->queSize - 1);
@ -3210,7 +3204,7 @@ comments: true
} }
/* 队首出队 */ /* 队首出队 */
int popFirst(arrayDeque *deque) { int popFirst(ArrayDeque *deque) {
int num = peekFirst(deque); int num = peekFirst(deque);
// 队首指针向后移动一位 // 队首指针向后移动一位
deque->front = dequeIndex(deque, deque->front + 1); deque->front = dequeIndex(deque, deque->front + 1);
@ -3219,14 +3213,14 @@ comments: true
} }
/* 队尾出队 */ /* 队尾出队 */
int popLast(arrayDeque *deque) { int popLast(ArrayDeque *deque) {
int num = peekLast(deque); int num = peekLast(deque);
deque->queSize--; deque->queSize--;
return num; return num;
} }
/* 打印队列 */ /* 打印队列 */
void printArrayDeque(arrayDeque *deque) { void printArrayDeque(ArrayDeque *deque) {
int arr[deque->queSize]; int arr[deque->queSize];
// 拷贝 // 拷贝
for (int i = 0, j = deque->front; i < deque->queSize; i++, j++) { for (int i = 0, j = deque->front; i < deque->queSize; i++, j++) {

View file

@ -1031,16 +1031,14 @@ comments: true
```c title="linkedlist_queue.c" ```c title="linkedlist_queue.c"
/* 基于链表实现的队列 */ /* 基于链表实现的队列 */
struct linkedListQueue { typedef struct {
ListNode *front, *rear; ListNode *front, *rear;
int queSize; int queSize;
}; } LinkedListQueue;
typedef struct linkedListQueue linkedListQueue;
/* 构造函数 */ /* 构造函数 */
linkedListQueue *newLinkedListQueue() { LinkedListQueue *newLinkedListQueue() {
linkedListQueue *queue = (linkedListQueue *)malloc(sizeof(linkedListQueue)); LinkedListQueue *queue = (LinkedListQueue *)malloc(sizeof(LinkedListQueue));
queue->front = NULL; queue->front = NULL;
queue->rear = NULL; queue->rear = NULL;
queue->queSize = 0; queue->queSize = 0;
@ -1048,7 +1046,7 @@ comments: true
} }
/* 析构函数 */ /* 析构函数 */
void delLinkedListQueue(linkedListQueue *queue) { void delLinkedListQueue(LinkedListQueue *queue) {
// 释放所有节点 // 释放所有节点
for (int i = 0; i < queue->queSize && queue->front != NULL; i++) { for (int i = 0; i < queue->queSize && queue->front != NULL; i++) {
ListNode *tmp = queue->front; ListNode *tmp = queue->front;
@ -1060,17 +1058,17 @@ comments: true
} }
/* 获取队列的长度 */ /* 获取队列的长度 */
int size(linkedListQueue *queue) { int size(LinkedListQueue *queue) {
return queue->queSize; return queue->queSize;
} }
/* 判断队列是否为空 */ /* 判断队列是否为空 */
bool empty(linkedListQueue *queue) { bool empty(LinkedListQueue *queue) {
return (size(queue) == 0); return (size(queue) == 0);
} }
/* 入队 */ /* 入队 */
void push(linkedListQueue *queue, int num) { void push(LinkedListQueue *queue, int num) {
// 尾节点处添加 node // 尾节点处添加 node
ListNode *node = newListNode(num); ListNode *node = newListNode(num);
// 如果队列为空,则令头、尾节点都指向该节点 // 如果队列为空,则令头、尾节点都指向该节点
@ -1087,13 +1085,13 @@ comments: true
} }
/* 访问队首元素 */ /* 访问队首元素 */
int peek(linkedListQueue *queue) { int peek(LinkedListQueue *queue) {
assert(size(queue) && queue->front); assert(size(queue) && queue->front);
return queue->front->val; return queue->front->val;
} }
/* 出队 */ /* 出队 */
void pop(linkedListQueue *queue) { void pop(LinkedListQueue *queue) {
int num = peek(queue); int num = peek(queue);
ListNode *tmp = queue->front; ListNode *tmp = queue->front;
queue->front = queue->front->next; queue->front = queue->front->next;
@ -1102,7 +1100,7 @@ comments: true
} }
/* 打印队列 */ /* 打印队列 */
void printLinkedListQueue(linkedListQueue *queue) { void printLinkedListQueue(LinkedListQueue *queue) {
int arr[queue->queSize]; int arr[queue->queSize];
// 拷贝链表中的数据到数组 // 拷贝链表中的数据到数组
int i; int i;
@ -1954,18 +1952,16 @@ comments: true
```c title="array_queue.c" ```c title="array_queue.c"
/* 基于环形数组实现的队列 */ /* 基于环形数组实现的队列 */
struct arrayQueue { typedef struct {
int *nums; // 用于存储队列元素的数组 int *nums; // 用于存储队列元素的数组
int front; // 队首指针,指向队首元素 int front; // 队首指针,指向队首元素
int queSize; // 尾指针,指向队尾 + 1 int queSize; // 尾指针,指向队尾 + 1
int queCapacity; // 队列容量 int queCapacity; // 队列容量
}; } ArrayQueue;
typedef struct arrayQueue arrayQueue;
/* 构造函数 */ /* 构造函数 */
arrayQueue *newArrayQueue(int capacity) { ArrayQueue *newArrayQueue(int capacity) {
arrayQueue *queue = (arrayQueue *)malloc(sizeof(arrayQueue)); ArrayQueue *queue = (ArrayQueue *)malloc(sizeof(ArrayQueue));
// 初始化数组 // 初始化数组
queue->queCapacity = capacity; queue->queCapacity = capacity;
queue->nums = (int *)malloc(sizeof(int) * queue->queCapacity); queue->nums = (int *)malloc(sizeof(int) * queue->queCapacity);
@ -1974,34 +1970,34 @@ comments: true
} }
/* 析构函数 */ /* 析构函数 */
void delArrayQueue(arrayQueue *queue) { void delArrayQueue(ArrayQueue *queue) {
free(queue->nums); free(queue->nums);
queue->queCapacity = 0; queue->queCapacity = 0;
} }
/* 获取队列的容量 */ /* 获取队列的容量 */
int capacity(arrayQueue *queue) { int capacity(ArrayQueue *queue) {
return queue->queCapacity; return queue->queCapacity;
} }
/* 获取队列的长度 */ /* 获取队列的长度 */
int size(arrayQueue *queue) { int size(ArrayQueue *queue) {
return queue->queSize; return queue->queSize;
} }
/* 判断队列是否为空 */ /* 判断队列是否为空 */
bool empty(arrayQueue *queue) { bool empty(ArrayQueue *queue) {
return queue->queSize == 0; return queue->queSize == 0;
} }
/* 访问队首元素 */ /* 访问队首元素 */
int peek(arrayQueue *queue) { int peek(ArrayQueue *queue) {
assert(size(queue) != 0); assert(size(queue) != 0);
return queue->nums[queue->front]; return queue->nums[queue->front];
} }
/* 入队 */ /* 入队 */
void push(arrayQueue *queue, int num) { void push(ArrayQueue *queue, int num) {
if (size(queue) == capacity(queue)) { if (size(queue) == capacity(queue)) {
printf("队列已满\r\n"); printf("队列已满\r\n");
return; return;
@ -2015,7 +2011,7 @@ comments: true
} }
/* 出队 */ /* 出队 */
void pop(arrayQueue *queue) { void pop(ArrayQueue *queue) {
int num = peek(queue); int num = peek(queue);
// 队首指针向后移动一位,若越过尾部则返回到数组头部 // 队首指针向后移动一位,若越过尾部则返回到数组头部
queue->front = (queue->front + 1) % queue->queCapacity; queue->front = (queue->front + 1) % queue->queCapacity;
@ -2023,7 +2019,7 @@ comments: true
} }
/* 打印队列 */ /* 打印队列 */
void printArrayQueue(arrayQueue *queue) { void printArrayQueue(ArrayQueue *queue) {
int arr[queue->queSize]; int arr[queue->queSize];
// 拷贝 // 拷贝
for (int i = 0, j = queue->front; i < queue->queSize; i++, j++) { for (int i = 0, j = queue->front; i < queue->queSize; i++, j++) {

View file

@ -937,23 +937,21 @@ comments: true
```c title="linkedlist_stack.c" ```c title="linkedlist_stack.c"
/* 基于链表实现的栈 */ /* 基于链表实现的栈 */
struct linkedListStack { typedef struct {
ListNode *top; // 将头节点作为栈顶 ListNode *top; // 将头节点作为栈顶
int size; // 栈的长度 int size; // 栈的长度
}; } LinkedListStack;
typedef struct linkedListStack linkedListStack;
/* 构造函数 */ /* 构造函数 */
linkedListStack *newLinkedListStack() { LinkedListStack *newLinkedListStack() {
linkedListStack *s = malloc(sizeof(linkedListStack)); LinkedListStack *s = malloc(sizeof(LinkedListStack));
s->top = NULL; s->top = NULL;
s->size = 0; s->size = 0;
return s; return s;
} }
/* 析构函数 */ /* 析构函数 */
void delLinkedListStack(linkedListStack *s) { void delLinkedListStack(LinkedListStack *s) {
while (s->top) { while (s->top) {
ListNode *n = s->top->next; ListNode *n = s->top->next;
free(s->top); free(s->top);
@ -963,26 +961,26 @@ comments: true
} }
/* 获取栈的长度 */ /* 获取栈的长度 */
int size(linkedListStack *s) { int size(LinkedListStack *s) {
assert(s); assert(s);
return s->size; return s->size;
} }
/* 判断栈是否为空 */ /* 判断栈是否为空 */
bool isEmpty(linkedListStack *s) { bool isEmpty(LinkedListStack *s) {
assert(s); assert(s);
return size(s) == 0; return size(s) == 0;
} }
/* 访问栈顶元素 */ /* 访问栈顶元素 */
int peek(linkedListStack *s) { int peek(LinkedListStack *s) {
assert(s); assert(s);
assert(size(s) != 0); assert(size(s) != 0);
return s->top->val; return s->top->val;
} }
/* 入栈 */ /* 入栈 */
void push(linkedListStack *s, int num) { void push(LinkedListStack *s, int num) {
assert(s); assert(s);
ListNode *node = (ListNode *)malloc(sizeof(ListNode)); ListNode *node = (ListNode *)malloc(sizeof(ListNode));
node->next = s->top; // 更新新加节点指针域 node->next = s->top; // 更新新加节点指针域
@ -992,7 +990,7 @@ comments: true
} }
/* 出栈 */ /* 出栈 */
int pop(linkedListStack *s) { int pop(LinkedListStack *s) {
if (s->size == 0) { if (s->size == 0) {
printf("stack is empty.\n"); printf("stack is empty.\n");
return INT_MAX; return INT_MAX;
@ -1576,16 +1574,14 @@ comments: true
```c title="array_stack.c" ```c title="array_stack.c"
/* 基于数组实现的栈 */ /* 基于数组实现的栈 */
struct arrayStack { typedef struct {
int *data; int *data;
int size; int size;
}; } ArrayStack;
typedef struct arrayStack arrayStack;
/* 构造函数 */ /* 构造函数 */
arrayStack *newArrayStack() { ArrayStack *newArrayStack() {
arrayStack *s = malloc(sizeof(arrayStack)); ArrayStack *s = malloc(sizeof(ArrayStack));
// 初始化一个大容量,避免扩容 // 初始化一个大容量,避免扩容
s->data = malloc(sizeof(int) * MAX_SIZE); s->data = malloc(sizeof(int) * MAX_SIZE);
s->size = 0; s->size = 0;
@ -1593,17 +1589,17 @@ comments: true
} }
/* 获取栈的长度 */ /* 获取栈的长度 */
int size(arrayStack *s) { int size(ArrayStack *s) {
return s->size; return s->size;
} }
/* 判断栈是否为空 */ /* 判断栈是否为空 */
bool isEmpty(arrayStack *s) { bool isEmpty(ArrayStack *s) {
return s->size == 0; return s->size == 0;
} }
/* 入栈 */ /* 入栈 */
void push(arrayStack *s, int num) { void push(ArrayStack *s, int num) {
if (s->size == MAX_SIZE) { if (s->size == MAX_SIZE) {
printf("stack is full.\n"); printf("stack is full.\n");
return; return;
@ -1613,7 +1609,7 @@ comments: true
} }
/* 访问栈顶元素 */ /* 访问栈顶元素 */
int peek(arrayStack *s) { int peek(ArrayStack *s) {
if (s->size == 0) { if (s->size == 0) {
printf("stack is empty.\n"); printf("stack is empty.\n");
return INT_MAX; return INT_MAX;
@ -1622,7 +1618,7 @@ comments: true
} }
/* 出栈 */ /* 出栈 */
int pop(arrayStack *s) { int pop(ArrayStack *s) {
if (s->size == 0) { if (s->size == 0) {
printf("stack is empty.\n"); printf("stack is empty.\n");
return INT_MAX; return INT_MAX;

View file

@ -1068,26 +1068,24 @@ comments: true
```c title="array_binary_tree.c" ```c title="array_binary_tree.c"
/* 数组表示下的二叉树类 */ /* 数组表示下的二叉树类 */
struct arrayBinaryTree { typedef struct {
vector *tree; vector *tree;
}; } ArrayBinaryTree;
typedef struct arrayBinaryTree arrayBinaryTree;
/* 构造函数 */ /* 构造函数 */
arrayBinaryTree *newArrayBinaryTree(vector *arr) { ArrayBinaryTree *newArrayBinaryTree(vector *arr) {
arrayBinaryTree *newABT = malloc(sizeof(arrayBinaryTree)); ArrayBinaryTree *newABT = malloc(sizeof(ArrayBinaryTree));
newABT->tree = arr; newABT->tree = arr;
return newABT; return newABT;
} }
/* 节点数量 */ /* 节点数量 */
int size(arrayBinaryTree *abt) { int size(ArrayBinaryTree *abt) {
return abt->tree->size; return abt->tree->size;
} }
/* 获取索引为 i 节点的值 */ /* 获取索引为 i 节点的值 */
int val(arrayBinaryTree *abt, int i) { int val(ArrayBinaryTree *abt, int i) {
// 若索引越界,则返回 INT_MAX ,代表空位 // 若索引越界,则返回 INT_MAX ,代表空位
if (i < 0 || i >= size(abt)) if (i < 0 || i >= size(abt))
return INT_MAX; return INT_MAX;
@ -1095,7 +1093,7 @@ comments: true
} }
/* 深度优先遍历 */ /* 深度优先遍历 */
void dfs(arrayBinaryTree *abt, int i, const char *order, vector *res) { void dfs(ArrayBinaryTree *abt, int i, const char *order, vector *res) {
// 若为空位,则返回 // 若为空位,则返回
if (val(abt, i) == INT_MAX) if (val(abt, i) == INT_MAX)
return; return;
@ -1119,7 +1117,7 @@ comments: true
} }
/* 层序遍历 */ /* 层序遍历 */
vector *levelOrder(arrayBinaryTree *abt) { vector *levelOrder(ArrayBinaryTree *abt) {
vector *res = newVector(); vector *res = newVector();
// 直接遍历数组 // 直接遍历数组
for (int i = 0; i < size(abt); i++) { for (int i = 0; i < size(abt); i++) {
@ -1132,21 +1130,21 @@ comments: true
} }
/* 前序遍历 */ /* 前序遍历 */
vector *preOrder(arrayBinaryTree *abt) { vector *preOrder(ArrayBinaryTree *abt) {
vector *res = newVector(); vector *res = newVector();
dfs(abt, 0, "pre", res); dfs(abt, 0, "pre", res);
return res; return res;
} }
/* 中序遍历 */ /* 中序遍历 */
vector *inOrder(arrayBinaryTree *abt) { vector *inOrder(ArrayBinaryTree *abt) {
vector *res = newVector(); vector *res = newVector();
dfs(abt, 0, "in", res); dfs(abt, 0, "in", res);
return res; return res;
} }
/* 后序遍历 */ /* 后序遍历 */
vector *postOrder(arrayBinaryTree *abt) { vector *postOrder(ArrayBinaryTree *abt) {
vector *res = newVector(); vector *res = newVector();
dfs(abt, 0, "post", res); dfs(abt, 0, "post", res);
return res; return res;

View file

@ -189,14 +189,12 @@ AVL 树既是二叉搜索树也是平衡二叉树,同时满足这两类二叉
```c title="" ```c title=""
/* AVL 树节点结构体 */ /* AVL 树节点结构体 */
struct TreeNode { TreeNode struct TreeNode {
int val; int val;
int height; int height;
struct TreeNode *left; struct TreeNode *left;
struct TreeNode *right; struct TreeNode *right;
}; } TreeNode;
typedef struct TreeNode TreeNode;
/* 构造函数 */ /* 构造函数 */
TreeNode *newTreeNode(int val) { TreeNode *newTreeNode(int val) {
@ -1836,7 +1834,7 @@ AVL 树的节点插入操作与二叉搜索树在主体上类似。唯一的区
```c title="avl_tree.c" ```c title="avl_tree.c"
/* 插入节点 */ /* 插入节点 */
void insert(aVLTree *tree, int val) { void insert(AVLTree *tree, int val) {
tree->root = insertHelper(tree->root, val); tree->root = insertHelper(tree->root, val);
} }
@ -2361,7 +2359,7 @@ AVL 树的节点插入操作与二叉搜索树在主体上类似。唯一的区
```c title="avl_tree.c" ```c title="avl_tree.c"
/* 删除节点 */ /* 删除节点 */
// 由于引入了 stdio.h ,此处无法使用 remove 关键词 // 由于引入了 stdio.h ,此处无法使用 remove 关键词
void removeItem(aVLTree *tree, int val) { void removeItem(AVLTree *tree, int val) {
TreeNode *root = removeHelper(tree->root, val); TreeNode *root = removeHelper(tree->root, val);
} }

View file

@ -274,7 +274,7 @@ comments: true
```c title="binary_search_tree.c" ```c title="binary_search_tree.c"
/* 查找节点 */ /* 查找节点 */
TreeNode *search(binarySearchTree *bst, int num) { TreeNode *search(BinarySearchTree *bst, int num) {
TreeNode *cur = bst->root; TreeNode *cur = bst->root;
// 循环查找,越过叶节点后跳出 // 循环查找,越过叶节点后跳出
while (cur != NULL) { while (cur != NULL) {
@ -673,7 +673,7 @@ comments: true
```c title="binary_search_tree.c" ```c title="binary_search_tree.c"
/* 插入节点 */ /* 插入节点 */
void insert(binarySearchTree *bst, int num) { void insert(BinarySearchTree *bst, int num) {
// 若树为空,则初始化根节点 // 若树为空,则初始化根节点
if (bst->root == NULL) { if (bst->root == NULL) {
bst->root = newTreeNode(num); bst->root = newTreeNode(num);
@ -1357,7 +1357,7 @@ comments: true
```c title="binary_search_tree.c" ```c title="binary_search_tree.c"
/* 删除节点 */ /* 删除节点 */
// 由于引入了 stdio.h ,此处无法使用 remove 关键词 // 由于引入了 stdio.h ,此处无法使用 remove 关键词
void removeItem(binarySearchTree *bst, int num) { void removeItem(BinarySearchTree *bst, int num) {
// 若树为空,直接提前返回 // 若树为空,直接提前返回
if (bst->root == NULL) if (bst->root == NULL)
return; return;

View file

@ -161,14 +161,12 @@ comments: true
```c title="" ```c title=""
/* 二叉树节点结构体 */ /* 二叉树节点结构体 */
struct TreeNode { typedef struct TreeNode {
int val; // 节点值 int val; // 节点值
int height; // 节点高度 int height; // 节点高度
struct TreeNode *left; // 左子节点指针 struct TreeNode *left; // 左子节点指针
struct TreeNode *right; // 右子节点指针 struct TreeNode *right; // 右子节点指针
}; } TreeNode;
typedef struct TreeNode TreeNode;
/* 构造函数 */ /* 构造函数 */
TreeNode *newTreeNode(int val) { TreeNode *newTreeNode(int val) {
@ -616,11 +614,11 @@ comments: true
<div class="center-table" markdown> <div class="center-table" markdown>
| | 完美二叉树 | 链表 | | | 完美二叉树 | 链表 |
| ----------------------------- | ---------- | ---------- | | ----------------------- | ------------------ | ------- |
| 第 $i$ 层的节点数量 | $2^{i-1}$ | $1$ | | 第 $i$ 层的节点数量 | $2^{i-1}$ | $1$ |
| 高度 $h$ 树的叶节点数量 | $2^h$ | $1$ | | 高度 $h$ 树的叶节点数量 | $2^h$ | $1$ |
| 高度 $h$ 树的节点总数 | $2^{h+1} - 1$ | $h + 1$ | | 高度 $h$ 树的节点总数 | $2^{h+1} - 1$ | $h + 1$ |
| 节点总数 $n$ 树的高度 | $\log_2 (n+1) - 1$ | $n - 1$ | | 节点总数 $n$ 树的高度 | $\log_2 (n+1) - 1$ | $n - 1$ |
</div> </div>