From aca850244bc6d678f2c1b443f45367327bb13d24 Mon Sep 17 00:00:00 2001 From: Lanjing Gong <39959756+Gonglja@users.noreply.github.com> Date: Fri, 12 Apr 2024 03:03:18 +0800 Subject: [PATCH] fix(C): fix array_hash_map.c and bucket_sort.c (#1272) * fix: Fix coding error, https://github.com/krahets/hello-algo/discussions/440#discussioncomment-8958379 * fix: Fix issue 1237 https://github.com/krahets/hello-algo/issues/1237 * Update array_hash_map.c * Update bucket_sort.c * Update bucket_sort.c * Update array_hash_map.c * Update bucket_sort.c * Update bucket_sort.c --------- Co-authored-by: Yudong Jin --- codes/c/chapter_hashing/array_hash_map.c | 23 ++++--- codes/c/chapter_sorting/bucket_sort.c | 67 +++++++------------ .../codes/c/chapter_hashing/array_hash_map.c | 23 ++++--- zh-hant/codes/c/chapter_sorting/bucket_sort.c | 67 +++++++------------ 4 files changed, 72 insertions(+), 108 deletions(-) diff --git a/codes/c/chapter_hashing/array_hash_map.c b/codes/c/chapter_hashing/array_hash_map.c index 1150093c2..17044934f 100644 --- a/codes/c/chapter_hashing/array_hash_map.c +++ b/codes/c/chapter_hashing/array_hash_map.c @@ -7,7 +7,7 @@ #include "../utils/common.h" /* 哈希表默认大小 */ -#define HASHTABLE_CAPACITY 100 +#define MAX_SIZE 100 /* 键值对 int->string */ typedef struct { @@ -23,18 +23,21 @@ typedef struct { /* 基于数组实现的哈希表 */ typedef struct { - Pair *buckets[HASHTABLE_CAPACITY]; + Pair *buckets[MAX_SIZE]; } ArrayHashMap; /* 构造函数 */ ArrayHashMap *newArrayHashMap() { ArrayHashMap *hmap = malloc(sizeof(ArrayHashMap)); + for (int i=0; i < MAX_SIZE; i++) { + hmap->buckets[i] = NULL; + } return hmap; } /* 析构函数 */ void delArrayHashMap(ArrayHashMap *hmap) { - for (int i = 0; i < HASHTABLE_CAPACITY; i++) { + for (int i = 0; i < MAX_SIZE; i++) { if (hmap->buckets[i] != NULL) { free(hmap->buckets[i]->val); free(hmap->buckets[i]); @@ -45,7 +48,7 @@ void delArrayHashMap(ArrayHashMap *hmap) { /* 哈希函数 */ int hashFunc(int key) { - int index = key % HASHTABLE_CAPACITY; + int index = key % MAX_SIZE; return index; } @@ -83,13 +86,13 @@ void pairSet(ArrayHashMap *hmap, MapSet *set) { int i = 0, index = 0; int total = 0; /* 统计有效键值对数量 */ - for (i = 0; i < HASHTABLE_CAPACITY; i++) { + for (i = 0; i < MAX_SIZE; i++) { if (hmap->buckets[i] != NULL) { total++; } } entries = malloc(sizeof(Pair) * total); - for (i = 0; i < HASHTABLE_CAPACITY; i++) { + for (i = 0; i < MAX_SIZE; i++) { if (hmap->buckets[i] != NULL) { entries[index].key = hmap->buckets[i]->key; entries[index].val = malloc(strlen(hmap->buckets[i]->val) + 1); @@ -107,13 +110,13 @@ void keySet(ArrayHashMap *hmap, MapSet *set) { int i = 0, index = 0; int total = 0; /* 统计有效键值对数量 */ - for (i = 0; i < HASHTABLE_CAPACITY; i++) { + for (i = 0; i < MAX_SIZE; i++) { if (hmap->buckets[i] != NULL) { total++; } } keys = malloc(total * sizeof(int)); - for (i = 0; i < HASHTABLE_CAPACITY; i++) { + for (i = 0; i < MAX_SIZE; i++) { if (hmap->buckets[i] != NULL) { keys[index] = hmap->buckets[i]->key; index++; @@ -129,13 +132,13 @@ void valueSet(ArrayHashMap *hmap, MapSet *set) { int i = 0, index = 0; int total = 0; /* 统计有效键值对数量 */ - for (i = 0; i < HASHTABLE_CAPACITY; i++) { + for (i = 0; i < MAX_SIZE; i++) { if (hmap->buckets[i] != NULL) { total++; } } vals = malloc(total * sizeof(char *)); - for (i = 0; i < HASHTABLE_CAPACITY; i++) { + for (i = 0; i < MAX_SIZE; i++) { if (hmap->buckets[i] != NULL) { vals[index] = hmap->buckets[i]->val; index++; diff --git a/codes/c/chapter_sorting/bucket_sort.c b/codes/c/chapter_sorting/bucket_sort.c index 0d9ef6b75..88f6ce4b0 100644 --- a/codes/c/chapter_sorting/bucket_sort.c +++ b/codes/c/chapter_sorting/bucket_sort.c @@ -8,66 +8,45 @@ #define SIZE 10 -/* 比较两个浮点数的大小 */ -int compare_float(const void *a, const void *b) { +/* 用于 qsort 的比较函数 */ +int compare(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++) { - // 每个桶最多可以分配 size 个元素 - buckets[i] = calloc(size, sizeof(float)); +void bucketSort(float nums[], int n) { + int k = n / 2; // 初始化 k = n/2 个桶 + int *sizes = malloc(k * sizeof(int)); // 记录每个桶的大小 + float **buckets = malloc(k * sizeof(float *)); // 动态数组的数组(桶) + + for (int i = 0; i < k; ++i) { + // 为每个桶预分配足够的空间 + buckets[i] = (float *)malloc(n * sizeof(float)); + sizes[i] = 0; } // 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 < size && buckets[bucket_idx][j] > 0) { - swap(&temp, &buckets[bucket_idx][j]); - j++; - } - buckets[bucket_idx][j] = temp; + for (int i = 0; i < n; ++i) { + int idx = (int)(nums[i] * k); + buckets[idx][sizes[idx]++] = nums[i]; } // 2. 对各个桶执行排序 - for (int i = 0; i < k; i++) { - qsort(buckets[i], size, sizeof(float), compare_float); + for (int i = 0; i < k; ++i) { + qsort(buckets[i], sizes[i], sizeof(float), compare); } - // 3. 遍历桶合并结果 - for (int i = 0, j = 0; j < k; j++) { - for (int l = 0; l < size; l++) { - if (buckets[j][l] > 0) { - nums[i++] = buckets[j][l]; - } + // 3. 合并排序后的桶 + int idx = 0; + for (int i = 0; i < k; ++i) { + for (int j = 0; j < sizes[i]; ++j) { + nums[idx++] = buckets[i][j]; } - } - - // 释放上述分配的内存 - for (int i = 0; i < k; i++) { + // 释放内存 free(buckets[i]); } - free(buckets); } /* Driver Code */ @@ -79,4 +58,4 @@ int main() { printArrayFloat(nums, SIZE); return 0; -} \ No newline at end of file +} diff --git a/zh-hant/codes/c/chapter_hashing/array_hash_map.c b/zh-hant/codes/c/chapter_hashing/array_hash_map.c index 1a44f42d2..af2f8c609 100644 --- a/zh-hant/codes/c/chapter_hashing/array_hash_map.c +++ b/zh-hant/codes/c/chapter_hashing/array_hash_map.c @@ -7,7 +7,7 @@ #include "../utils/common.h" /* 雜湊表預設大小 */ -#define HASHTABLE_CAPACITY 100 +#define 100 /* 鍵值對 int->string */ typedef struct { @@ -23,18 +23,21 @@ typedef struct { /* 基於陣列實現的雜湊表 */ typedef struct { - Pair *buckets[HASHTABLE_CAPACITY]; + Pair *buckets[MAX_SIZE]; } ArrayHashMap; /* 建構子 */ ArrayHashMap *newArrayHashMap() { ArrayHashMap *hmap = malloc(sizeof(ArrayHashMap)); + for (int i = 0; i < MAX_SIZE; i++) { + hmap->buckets[i] = NULL; + } return hmap; } /* 析構函式 */ void delArrayHashMap(ArrayHashMap *hmap) { - for (int i = 0; i < HASHTABLE_CAPACITY; i++) { + for (int i = 0; i < MAX_SIZE; i++) { if (hmap->buckets[i] != NULL) { free(hmap->buckets[i]->val); free(hmap->buckets[i]); @@ -45,7 +48,7 @@ void delArrayHashMap(ArrayHashMap *hmap) { /* 雜湊函式 */ int hashFunc(int key) { - int index = key % HASHTABLE_CAPACITY; + int index = key % MAX_SIZE; return index; } @@ -83,13 +86,13 @@ void pairSet(ArrayHashMap *hmap, MapSet *set) { int i = 0, index = 0; int total = 0; /* 統計有效鍵值對數量 */ - for (i = 0; i < HASHTABLE_CAPACITY; i++) { + for (i = 0; i < MAX_SIZE; i++) { if (hmap->buckets[i] != NULL) { total++; } } entries = malloc(sizeof(Pair) * total); - for (i = 0; i < HASHTABLE_CAPACITY; i++) { + for (i = 0; i < MAX_SIZE; i++) { if (hmap->buckets[i] != NULL) { entries[index].key = hmap->buckets[i]->key; entries[index].val = malloc(strlen(hmap->buckets[i]->val) + 1); @@ -107,13 +110,13 @@ void keySet(ArrayHashMap *hmap, MapSet *set) { int i = 0, index = 0; int total = 0; /* 統計有效鍵值對數量 */ - for (i = 0; i < HASHTABLE_CAPACITY; i++) { + for (i = 0; i < MAX_SIZE; i++) { if (hmap->buckets[i] != NULL) { total++; } } keys = malloc(total * sizeof(int)); - for (i = 0; i < HASHTABLE_CAPACITY; i++) { + for (i = 0; i < MAX_SIZE; i++) { if (hmap->buckets[i] != NULL) { keys[index] = hmap->buckets[i]->key; index++; @@ -129,13 +132,13 @@ void valueSet(ArrayHashMap *hmap, MapSet *set) { int i = 0, index = 0; int total = 0; /* 統計有效鍵值對數量 */ - for (i = 0; i < HASHTABLE_CAPACITY; i++) { + for (i = 0; i < MAX_SIZE; i++) { if (hmap->buckets[i] != NULL) { total++; } } vals = malloc(total * sizeof(char *)); - for (i = 0; i < HASHTABLE_CAPACITY; i++) { + for (i = 0; i < MAX_SIZE; i++) { if (hmap->buckets[i] != NULL) { vals[index] = hmap->buckets[i]->val; index++; diff --git a/zh-hant/codes/c/chapter_sorting/bucket_sort.c b/zh-hant/codes/c/chapter_sorting/bucket_sort.c index f426a7bc1..aca80083c 100644 --- a/zh-hant/codes/c/chapter_sorting/bucket_sort.c +++ b/zh-hant/codes/c/chapter_sorting/bucket_sort.c @@ -8,66 +8,45 @@ #define SIZE 10 -/* 比較兩個浮點數的大小 */ -int compare_float(const void *a, const void *b) { +/* 用於 qsort 的比較函式 */ +int compare(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++) { - // 每個桶最多可以分配 size 個元素 - buckets[i] = calloc(size, sizeof(float)); +void bucketSort(float nums[], int n) { + int k = n / 2; // 初始化 k = n/2 個桶 + int *sizes = malloc(k * sizeof(int)); // 記錄每個桶的大小 + float **buckets = malloc(k * sizeof(float *)); // 動態陣列的陣列(桶) + + for (int i = 0; i < k; ++i) { + // 為每個桶預分配足夠的空間 + buckets[i] = (float *)malloc(n * sizeof(float)); + sizes[i] = 0; } // 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 < size && buckets[bucket_idx][j] > 0) { - swap(&temp, &buckets[bucket_idx][j]); - j++; - } - buckets[bucket_idx][j] = temp; + for (int i = 0; i < n; ++i) { + int idx = (int)(nums[i] * k); + buckets[idx][sizes[idx]++] = nums[i]; } // 2. 對各個桶執行排序 - for (int i = 0; i < k; i++) { - qsort(buckets[i], size, sizeof(float), compare_float); + for (int i = 0; i < k; ++i) { + qsort(buckets[i], sizes[i], sizeof(float), compare); } - // 3. 走訪桶合併結果 - for (int i = 0, j = 0; j < k; j++) { - for (int l = 0; l < size; l++) { - if (buckets[j][l] > 0) { - nums[i++] = buckets[j][l]; - } + // 3. 合併排序後的桶 + int idx = 0; + for (int i = 0; i < k; ++i) { + for (int j = 0; j < sizes[i]; ++j) { + nums[idx++] = buckets[i][j]; } - } - - // 釋放上述分配的記憶體 - for (int i = 0; i < k; i++) { + // 釋放記憶體 free(buckets[i]); } - free(buckets); } /* Driver Code */ @@ -79,4 +58,4 @@ int main() { printArrayFloat(nums, SIZE); return 0; -} \ No newline at end of file +}