forked from krahets/hello-algo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add C codes for bucket sort, heap sort, selection sort, binary …
…search edge (krahets#525) * fix(codes/cpp): Memory leak fix: the space was not freed when pop removed the element. * fix(codes/cpp): Fix access error when printArray(arr, 0) * Update PrintUtil.hpp * fix(codes/c): Fix some errors of cmake build * feat(codes/c): Add hashing_search.c * styles(codes/c): Modify function description * styles(codes/c): Modify binary_search.c code style * fix(codes/c): Fix the problem in binary_tree_bfs.c and the problem that the memory is not released. * feat: Add preorder_traversal_i_compact.c * feat(codes/c): Add head_sort.c * feat(codes/c): Add bucket_sort.c * feat(codes/c): Add binary_search_edge.c * fix(codes/c): Add programs that are not managed by cmake (c code) * feat(codes/c): Add selection_sort.c * style(codes/c): Change swap in selection_sort.c to `selectionSort` * styles(codes/c): Change style. * fix(codes/c): Fix some formatting errors and temporarily remove backtracking chapters --------- Co-authored-by: Yudong Jin <[email protected]>
- Loading branch information
Showing
8 changed files
with
268 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,5 @@ | ||
add_executable(binary_search binary_search.c) | ||
add_executable(two_sum two_sum.c) | ||
add_executable(two_sum two_sum.c) | ||
add_executable(binary_search_edge binary_search_edge.c) | ||
add_executable(hashing_search hashing_search.c) | ||
add_executable(linear_search linear_search.c) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/** | ||
* File: binary_search_edge.c | ||
* Created Time: 2023-05-31 | ||
* Author: Gonglja ([email protected]) | ||
*/ | ||
|
||
#include "../utils/common.h" | ||
|
||
|
||
/* 二分查找最左一个元素 */ | ||
int binarySearchLeftEdge(int *nums, int size, int target) { | ||
int i = 0, j = size - 1; // 初始化双闭区间 [0, n-1] | ||
while (i <= j) { | ||
int m = i + (j - i) / 2; // 计算中点索引 m | ||
if (nums[m] < target) | ||
i = m + 1; // target 在区间 [m+1, j] 中 | ||
else if (nums[m] > target) | ||
j = m - 1; // target 在区间 [i, m-1] 中 | ||
else | ||
j = m - 1; // 首个小于 target 的元素在区间 [i, m-1] 中 | ||
} | ||
if (i == size || nums[i] != target) | ||
return -1; // 未找到目标元素,返回 -1 | ||
return i; | ||
} | ||
|
||
/* 二分查找最右一个元素 */ | ||
int binarySearchRightEdge(int *nums, int size, int target) { | ||
int i = 0, j = size - 1; // 初始化双闭区间 [0, n-1] | ||
while (i <= j) { | ||
int m = i + (j - i) / 2; // 计算中点索引 m | ||
if (nums[m] < target) | ||
i = m + 1; // target 在区间 [m+1, j] 中 | ||
else if (nums[m] > target) | ||
j = m - 1; // target 在区间 [i, m-1] 中 | ||
else | ||
i = m + 1; // 首个大于 target 的元素在区间 [m+1, j] 中 | ||
} | ||
if (j < 0 || nums[j] != target) | ||
return -1; // 未找到目标元素,返回 -1 | ||
return j; | ||
} | ||
|
||
/* Driver Code */ | ||
int main() { | ||
int target = 6; | ||
int nums[] = {1, 3, 6, 6, 6, 6, 6, 10, 12, 15}; | ||
int size = sizeof(nums) / sizeof(nums[0]); | ||
|
||
// 二分查找最左一个元素 | ||
int indexLeft = binarySearchLeftEdge(nums, size, target); | ||
printf("数组中最左一个元素 6 的索引 = %d\n", indexLeft); | ||
|
||
// 二分查找最右一个元素 | ||
int indexRight = binarySearchRightEdge(nums, size, target); | ||
printf("数组中最右一个元素 6 的索引 = %d\n", indexRight); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/** | ||
* File: bucket_sort.c | ||
* Created Time: 2023-05-30 | ||
* Author: Gonglja ([email protected]) | ||
*/ | ||
|
||
#include "../utils/common.h" | ||
|
||
#define ARRAY_SIZE 10 | ||
|
||
/* 比较两个浮点数的大小 */ | ||
int compare_float(const void *a, const void *b) { | ||
float fa = *(const float *)a; | ||
float fb = *(const float *)b; | ||
return (fa > fb) - (fa < fb); | ||
} | ||
|
||
/* 交换两个浮点数 */ | ||
void swap(float *a, float *b) { | ||
float tmp = *a; | ||
*a = *b; | ||
*b = tmp; | ||
} | ||
|
||
/* 桶排序 */ | ||
void bucketSort(float nums[], int size) { | ||
// 初始化 k = n/2 个桶,预期向每个桶分配 2 个元素 | ||
int k = size / 2; | ||
float **buckets = calloc(k, sizeof(float *)); | ||
for (int i = 0; i < k; i++) { | ||
// 每个桶最多可以分配 k 个元素 | ||
buckets[i] = calloc(ARRAY_SIZE, sizeof(float)); | ||
} | ||
|
||
// 1. 将数组元素分配到各个桶中 | ||
for (int i = 0; i < size; i++) { | ||
// 输入数据范围 [0, 1),使用 num * k 映射到索引范围 [0, k-1] | ||
int bucket_idx = nums[i] * k; | ||
int j = 0; | ||
// 如果桶中有数据且数据小于当前值 nums[i], 要将其放到当前桶的后面,相当于 cpp 中的 push_back | ||
while (buckets[bucket_idx][j] > 0 && buckets[bucket_idx][j] < nums[i]) { | ||
j++; | ||
} | ||
float temp = nums[i]; | ||
while (j < ARRAY_SIZE && buckets[bucket_idx][j] > 0) { | ||
swap(&temp, &buckets[bucket_idx][j]); | ||
j++; | ||
} | ||
buckets[bucket_idx][j] = temp; | ||
} | ||
|
||
// 2. 对各个桶执行排序 | ||
for (int i = 0; i < k; i++) { | ||
qsort(buckets[i], ARRAY_SIZE, sizeof(float), compare_float); | ||
} | ||
|
||
// 3. 遍历桶合并结果 | ||
for (int i = 0, j = 0; j < k; j++) { | ||
for (int l = 0; l < ARRAY_SIZE; l++) { | ||
if (buckets[j][l] > 0) { | ||
nums[i++] = buckets[j][l]; | ||
} | ||
} | ||
} | ||
|
||
// 释放上述分配的内存 | ||
for (int i = 0; i < k; i++) { | ||
free(buckets[i]); | ||
} | ||
free(buckets); | ||
} | ||
|
||
/* Driver Code */ | ||
int main() { | ||
// 设输入数据为浮点数,范围为 [0, 1) | ||
float nums[ARRAY_SIZE] = {0.49f, 0.96f, 0.82f, 0.09f, 0.57f, 0.43f, 0.91f, 0.75f, 0.15f, 0.37f}; | ||
bucketSort(nums, ARRAY_SIZE); | ||
printf("桶排序完成后 nums = "); | ||
printArrayFloat(nums, ARRAY_SIZE); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/** | ||
* File: heap_sort.c | ||
* Created Time: 2023-05-30 | ||
* Author: Gonglja ([email protected]) | ||
*/ | ||
|
||
#include "../utils/common.h" | ||
|
||
/* 堆的长度为 n ,从节点 i 开始,从顶至底堆化 */ | ||
void siftDown(int nums[], int n, int i) { | ||
while (1) { | ||
// 判断节点 i, l, r 中值最大的节点,记为 ma | ||
int l = 2 * i + 1; | ||
int r = 2 * i + 2; | ||
int ma = i; | ||
if (l < n && nums[l] > nums[ma]) | ||
ma = l; | ||
if (r < n && nums[r] > nums[ma]) | ||
ma = r; | ||
// 若节点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 | ||
if (ma == i) { | ||
break; | ||
} | ||
// 交换两节点 | ||
int temp = nums[i]; | ||
nums[i] = nums[ma]; | ||
nums[ma] = temp; | ||
// 循环向下堆化 | ||
i = ma; | ||
} | ||
} | ||
|
||
/* 堆排序 */ | ||
void heapSort(int nums[], int n) { | ||
// 建堆操作:堆化除叶节点以外的其他所有节点 | ||
for (int i = n / 2 - 1; i >= 0; --i) { | ||
siftDown(nums, n, i); | ||
} | ||
// 从堆中提取最大元素,循环 n-1 轮 | ||
for (int i = n - 1; i > 0; --i) { | ||
// 交换根节点与最右叶节点(即交换首元素与尾元素) | ||
int tmp = nums[0]; | ||
nums[0] = nums[i]; | ||
nums[i] = tmp; | ||
// 以根节点为起点,从顶至底进行堆化 | ||
siftDown(nums, i, 0); | ||
} | ||
} | ||
|
||
/* Driver Code */ | ||
int main() { | ||
int nums[] = {4, 1, 3, 1, 5, 2}; | ||
int n = sizeof(nums) / sizeof(nums[0]); | ||
|
||
heapSort(nums, n); | ||
printf("堆排序完成后 nums = "); | ||
printArray(nums, n); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/** | ||
* File: selection_sort.c | ||
* Created Time: 2023-05-31 | ||
* Author: Gonglja ([email protected]) | ||
*/ | ||
|
||
#include "../utils/common.h" | ||
|
||
/* 选择排序 */ | ||
void selectionSort(int nums[], int n) { | ||
// 外循环:未排序区间为 [i, n-1] | ||
for (int i = 0; i < n - 1; i++) { | ||
// 内循环:找到未排序区间内的最小元素 | ||
int k = i; | ||
for (int j = i + 1; j < n; j++) { | ||
if (nums[j] < nums[k]) | ||
k = j; // 记录最小元素的索引 | ||
} | ||
// 将该最小元素与未排序区间的首个元素交换 | ||
int temp = nums[i]; | ||
nums[i] = nums[k]; | ||
nums[k] = temp; | ||
} | ||
} | ||
|
||
/* 主函数 */ | ||
int main() { | ||
int nums[] = {4, 1, 3, 1, 5, 2}; | ||
int n = sizeof(nums) / sizeof(nums[0]); | ||
|
||
selectionSort(nums, n); | ||
|
||
printf("选择排序完成后 nums = "); | ||
printArray(nums, n); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters