Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(C): fix array_hash_map.c and bucket_sort.c #1272

Merged
merged 9 commits into from
Apr 11, 2024
23 changes: 13 additions & 10 deletions codes/c/chapter_hashing/array_hash_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include "../utils/common.h"

/* 哈希表默认大小 */
#define HASHTABLE_CAPACITY 100
#define MAX_SIZE 100

/* 键值对 int->string */
typedef struct {
Expand All @@ -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]);
Expand All @@ -45,7 +48,7 @@ void delArrayHashMap(ArrayHashMap *hmap) {

/* 哈希函数 */
int hashFunc(int key) {
int index = key % HASHTABLE_CAPACITY;
int index = key % MAX_SIZE;
return index;
}

Expand Down Expand Up @@ -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);
Expand All @@ -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++;
Expand All @@ -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++;
Expand Down
67 changes: 23 additions & 44 deletions codes/c/chapter_sorting/bucket_sort.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -79,4 +58,4 @@ int main() {
printArrayFloat(nums, SIZE);

return 0;
}
}
23 changes: 13 additions & 10 deletions zh-hant/codes/c/chapter_hashing/array_hash_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include "../utils/common.h"

/* 雜湊表預設大小 */
#define HASHTABLE_CAPACITY 100
#define 100

/* 鍵值對 int->string */
typedef struct {
Expand All @@ -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]);
Expand All @@ -45,7 +48,7 @@ void delArrayHashMap(ArrayHashMap *hmap) {

/* 雜湊函式 */
int hashFunc(int key) {
int index = key % HASHTABLE_CAPACITY;
int index = key % MAX_SIZE;
return index;
}

Expand Down Expand Up @@ -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);
Expand All @@ -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++;
Expand All @@ -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++;
Expand Down
67 changes: 23 additions & 44 deletions zh-hant/codes/c/chapter_sorting/bucket_sort.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -79,4 +58,4 @@ int main() {
printArrayFloat(nums, SIZE);

return 0;
}
}