map容器的c实现



原文来自:http://blog.chinaunix.net/uid-21457204-id-3063180.html

主要是使用红黑树这种数据结构封装一个MAP容器,本来想模仿STL MAP,不过现在暂时实现,今后会改进,目前还没实现加锁这功能,不过可以支持win32和linux平台。。。

以下是源代码:

  1. /*
  2. * file: main.c
  3. * author: vincent.cws2008@gmail.com
  4. * history:
  5. * initial @ 2012-01-31
  6. */

  7. #define DEBUG

  8. #include <stdio.h>
  9. #include <time.h>
  10. #include <stdlib.h>
  11. #include <string.h>

  12. #include "map.h"

  13. #ifdef DEBUG
  14. #define dump(a,s) __dump((a),(s))
  15. #else
  16. #define dump(a,s)
  17. #endif


  18. typedef struct word_info {
  19. unsigned long hash_major;
  20. unsigned long hash_minor;
  21. char *path;
  22. unsigned long line;
  23. unsigned long col;
  24. }word_info_t;

  25. typedef struct priv_info {
  26. unsigned long key;
  27. char val[10];
  28. }priv_info_t;


  29. static void __dump(priv_info_t *array, size_t num)
  30. {
  31. int i;
  32. printf("-- DUMP START -- \n");
  33. for (i=0; i < num; i++)
  34. {
  35. printf("array[%d].key=%03d, array[%d].val=%s\n",
  36. i, array[i].key, i, array[i].val);
  37. }
  38. printf("-- DUMP END -- \n");
  39. }

  40. #define map_info(pm) {\
  41. printf("-- dump map start ... --\n"); \
  42. map_dump(pm); \
  43. printf("-- dump map end ... --\n"); \
  44. }

  45. #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))

  46. #define MAX_NUM 20

  47. int main()
  48. {
  49. map_t map1;
  50. int key;
  51. int i, j;
  52. priv_info_t priv_info[MAX_NUM];

  53. srand(time(0));

  54. memset(priv_info, 0, sizeof(priv_info));
  55. for (i=0; i<MAX_NUM; i++)
  56. {
  57. key = rand()%MAX_NUM;
  58. priv_info[i].key = key;
  59. sprintf(priv_info[i].val, "i am %d", key);
  60. }
  61. dump(priv_info, ARRAY_SIZE(priv_info));

  62. map_init(&map1);

  63. i = 0;
  64. while (i < MAX_NUM)
  65. {
  66. struct mnode* node;
  67. printf("-- %d -- \n", i);
  68. node = map_find(&map1,&(priv_info[i].key), NULL);
  69. if (!node) {
  70. printf("->>> insert node: priv_info[%d].key=%d \n", i, priv_info[i].key);
  71. map_insert_alloc(&map1, &(priv_info[i].key),
  72. &priv_info[i], sizeof(priv_info[i]), NULL);
  73. } else {
  74. /* key not matched, so just print out */
  75. printf("priv_info[%d].key=%d is exist!\n", i, priv_info[i].key);
  76. for (j=0; j < MAX_NUM; j++) {
  77. if(priv_info[j].key == priv_info[i].key && i!=j)
  78. printf("\t|-- priv_info[%d].key=%d\n", j, priv_info[j].key);
  79. }
  80. }
  81. map_info(&map1);

  82. i++;
  83. }
  84. map_info(&map1);

  85. printf("-----------------------------------\n");
  86. for (i=0; i < MAX_NUM; i++)
  87. {
  88. struct mnode* node;
  89. node = map_find(&map1,&i, NULL);
  90. if (node){
  91. map_remove_free(&map1, &i, NULL);
  92. printf("--> key=%03d deleted!\n", i);
  93. map_info(&map1);
  94. }else{
  95. printf("key=%03d not found!\n", i);
  96. }
  97. }
  98. map_info(&map1);

  99. map_exit(&map1);
  100. return 0;
  101. }

.............................................................................................
.............................................................................................


  1. /*
  2. * file: map.h
  3. * author: vincent.cws2008@gmail.com
  4. * history:
  5. * initial @ 2012-01-31
  6. */
  7. #ifndef __MAP_H__
  8. #define __MAP_H__

  9. #include <stdlib.h>
  10. #include "platform.h"
  11. #include "rbtree.h"

  12. #define lock_t int
  13. #define lock_init(x)
  14. #define lock_exit(x)

  15. #ifndef NULL
  16. #define NULL 0
  17. #endif

  18. #define __assert(x)
  19. #define __free(x) free(x)
  20. #define __malloc(x) malloc(x)
  21. #define __memcpy(d,s,len) memcpy((d),(s),(len))

  22. extern struct map;

  23. typedef int (*CMP_FUNC)(const void *d1, const void *d2);

  24. typedef struct mnode{
  25. struct rb_node node;
  26. void *key;
  27. void *private;
  28. }mnode_t;

  29. /*
  30. typedef struct ops{
  31. struct mnode*(*find)(struct map *map, void *key, CMP_FUNC cmpf);
  32. int (*insert_alloc)(struct map *map, void *key,
  33. void *private, size_t size, CMP_FUNC cmpf);
  34. int (*remove_free)(struct map *map, void *key, CMP_FUNC cmpf);
  35. int (*insert)(struct map *map, struct mnode *data, CMP_FUNC cmpf);
  36. int (*remove)(struct map *map, void *key, CMP_FUNC cmpf);
  37. }ops_t;
  38. */

  39. typedef struct map{
  40. struct rb_root root;
  41. lock_t lock;
  42. }map_t;

  43. extern int map_init(struct map* map);
  44. extern int map_exit(struct map* map);

  45. struct mnode* __rbfind(struct map *map, void *key, CMP_FUNC cmpf);
  46. int __rbinsert_alloc(struct map *map, void *key,
  47. void *private, size_t size, CMP_FUNC cmpf);
  48. int __rbremove_free(struct map *map, void *key, CMP_FUNC cmpf);
  49. int __rbinsert(struct map *map, struct mnode *data, CMP_FUNC cmpf);
  50. int __rbremove(struct map *map, void *key, CMP_FUNC cmpf);

  51. #define map_find(map,key,cmpf) \
  52. __rbfind((map),(key),(cmpf))

  53. #define map_insert_alloc(map,key,priv,size,cmpf) \
  54. __rbinsert_alloc((map),(key),(priv),(size),(cmpf))

  55. #define map_remove_free(map,key,cmpf) \
  56. __rbremove_free((map),(key),(cmpf))

  57. #if 0
  58. #define map_insert(map,data,cmpf) \
  59. __rbinsert((map),(data),(cmpf))
  60. #define map_remove(map,key,cmpf) \
  61. __rbremove((map),(key),(cmpf))
  62. #endif


  63. #define map_entry(ptr, type, member) container_of(ptr, type, member)

  64. extern struct mnode *map_first(const struct map *map);
  65. extern struct mnode *map_last(const struct map *map);
  66. extern struct mnode *map_next(const struct mnode *mnode);
  67. extern struct mnode *map_prev(const struct mnode *mnode);

  68. extern void map_dump(const struct map* map);


  69. #endif
.............................................................................................
.............................................................................................

  1. /*
  2. * file: map.c
  3. * author: vincent.cws2008@gmail.com
  4. * history:
  5. * initial @ 2012-01-31
  6. */
  7. #define DEBUG
  8. #include "map.h"

  9. #define mnode_init(mnode) {\
  10. (mnode)->node.rb_parent_color=0; \
  11. (mnode)->node.rb_right=0; \
  12. (mnode)->node.rb_left=0; \
  13. (mnode)->key=0; \
  14. (mnode)->private=0; \
  15. }


  16. void map_dump(const struct map* map)
  17. {
  18. struct mnode *mnode;
  19. int cnt=0;
  20. for (mnode = map_first(map); mnode; mnode = map_next(mnode))
  21. printf("key=%03d%s", *(int*)mnode->key, ++cnt%10==0?"\n":" ");
  22. printf("\n");
  23. }


  24. static int __cmp_default(long *d1, long *d2)
  25. {
  26. // printf("-- d1:%d, d2:%d\n", *d1, *d2);
  27. if (*d1 < *d2) return -1;
  28. else if (*d1 > *d2) return 1;
  29. else return 0;
  30. }

  31. struct mnode* __rbfind(struct map *map, void *key, CMP_FUNC cmpf)
  32. {
  33. int result;
  34. CMP_FUNC cmp;
  35. struct mnode *data;
  36. struct rb_node *node = map->root.rb_node;

  37. __assert(map && key);

  38. cmp = cmpf ? cmpf : __cmp_default;
  39. /* printf("==> entry %s key:%d\n", __func__, *(int*)key); */
  40. while (node)
  41. {
  42. data = container_of(node, struct mnode, node);
  43. /* printf("data->key:%d VS key:%d\n", *(int*)(data->key), *(int*)key);*/
  44. result = cmp(key, data->key);
  45. /*printf("result=%d, node->rb_left=%p, node->rb_right=%p\n",
  46. result, node->rb_left, node->rb_right);*/
  47. if (result < 0)
  48. node = node->rb_left;
  49. else if (result > 0)
  50. node = node->rb_right;
  51. else
  52. return data;
  53. }
  54. //printf("node=%p\n", node);
  55. return NULL;
  56. }

  57. int __rbinsert(struct map *map, struct mnode *data, CMP_FUNC cmpf)
  58. {
  59. int result;
  60. struct mnode *this;
  61. CMP_FUNC cmp;
  62. struct rb_node **new = &(map->root.rb_node), *parent = NULL;

  63. __assert(map && data);

  64. cmp = cmpf ? cmpf : __cmp_default;

  65. /* Figure out where to put new node */
  66. while (*new)
  67. {
  68. this = container_of(*new, struct mnode, node);
  69. result = cmp(data->key, this->key);

  70. parent = *new;
  71. if (result < 0) new = &((*new)->rb_left);
  72. else if (result > 0) new = &((*new)->rb_right);
  73. else return -2;
  74. }
  75. /* Add new node and rebalance tree. */
  76. rb_link_node(&(data->node), parent, new);
  77. rb_insert_color(&(data->node), &(map->root));
  78. return 0;
  79. }

  80. int __rbremove(struct map *map, void *key, CMP_FUNC cmpf)
  81. {
  82. struct mnode* data = __rbfind(map, key, cmpf);
  83. __assert(map && key);
  84. if (data)
  85. rb_erase(&(data->node), &(map->root));
  86. return 0;
  87. }

  88. int __rbinsert_alloc(struct map *map, void *key,
  89. void *private, size_t size, CMP_FUNC cmpf)
  90. {
  91. struct mnode *new;
  92. __assert(map && key && private);
  93. new = (struct mnode*)__malloc(size+sizeof(struct mnode));
  94. __assert(new);
  95. mnode_init(new);
  96. new->key = key;
  97. new->private = new+1;
  98. if (private)
  99. __memcpy(new->private, private, size);

  100. return __rbinsert(map, new, cmpf);
  101. }

  102. int __rbremove_free(struct map *map, void *key, CMP_FUNC cmpf)
  103. {
  104. struct mnode* data;
  105. __assert(map && key);
  106. data = __rbfind(map, key, cmpf);
  107. /* printf("%s: key: %d\n", __func__, *(int*)(data->key)); */
  108. if (data)
  109. {
  110. /* printf("%s: deleted!\n", __func__);*/
  111. rb_erase(&(data->node), &(map->root));
  112. __free(data);
  113. }
  114. return 0;
  115. }

  116. struct mnode *map_first(const struct map *map)
  117. {
  118. struct rb_node *node;
  119. __assert(map);
  120. node = rb_first(&(map->root));
  121. if(node)
  122. return map_entry(node, struct mnode, node);
  123. return NULL;
  124. }

  125. struct mnode *map_last(const struct map *map)
  126. {
  127. struct rb_node *node;
  128. __assert(map);
  129. node = rb_last(&(map->root));
  130. if(node)
  131. return map_entry(node, struct mnode, node);
  132. return NULL;
  133. }

  134. struct mnode *map_next(const struct mnode *mnode)
  135. {
  136. struct rb_node *node;
  137. __assert(mnode);
  138. node = rb_next(&(mnode->node));
  139. if(node)
  140. return map_entry(node, struct mnode, node);
  141. return NULL;
  142. }

  143. struct mnode *map_prev(const struct mnode *mnode)
  144. {
  145. struct rb_node *node;
  146. __assert(mnode);
  147. node = rb_prev(&(mnode->node));
  148. if(node)
  149. return map_entry(node, struct mnode, node);
  150. return NULL;
  151. }


  152. int map_init(struct map* map)
  153. {
  154. map->root.rb_node = NULL;
  155. lock_init(map->lock);
  156. return 0;
  157. }

  158. int map_exit(struct map* map)
  159. {
  160. lock_exit(map->lock);
  161. return 0;
  162. }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
unordered_map 是 C++ 标准库中的一个容器,用于存储键值对,并支持快速的插入、删除和查找操作。C++ 的 unordered_map 可以通过哈希表来实现。 要在 C 中实现一个类似 unordered_map 的数据结构,你可以使用哈希表和链表的组合。下面是一个简单的示例: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define TABLE_SIZE 100 // 哈希表中的节点 typedef struct Node { char key[20]; int value; struct Node* next; } Node; // 哈希表 typedef struct HashMap { Node* table[TABLE_SIZE]; } HashMap; // 计算哈希值 int hash(const char* key) { int hash = 0; while (*key) { hash += *key; key++; } return hash % TABLE_SIZE; } // 初始化哈希表 HashMap* HashMap_Create() { HashMap* map = (HashMap*)malloc(sizeof(HashMap)); memset(map->table, 0, sizeof(map->table)); return map; } // 向哈希表中插入键值对 void HashMap_Insert(HashMap* map, const char* key, int value) { int index = hash(key); Node* newNode = (Node*)malloc(sizeof(Node)); strcpy(newNode->key, key); newNode->value = value; newNode->next = NULL; if (map->table[index] == NULL) { map->table[index] = newNode; } else { Node* current = map->table[index]; while (current->next != NULL) { current = current->next; } current->next = newNode; } } // 从哈希表中删除指定键的节点 void HashMap_Remove(HashMap* map, const char* key) { int index = hash(key); Node* current = map->table[index]; Node* previous = NULL; while (current != NULL && strcmp(current->key, key) != 0) { previous = current; current = current->next; } if (current == NULL) { return; // 未找到指定键的节点 } if (previous == NULL) { map->table[index] = current->next; } else { previous->next = current->next; } free(current); } // 从哈希表中获取指定键对应的值 int HashMap_Get(HashMap* map, const char* key) { int index = hash(key); Node* current = map->table[index]; while (current != NULL && strcmp(current->key, key) != 0) { current = current->next; } if (current == NULL) { return -1; // 未找到指定键的节点 } return current->value; } // 销毁哈希表 void HashMap_Destroy(HashMap* map) { for (int i = 0; i < TABLE_SIZE; i++) { Node* current = map->table[i]; while (current != NULL) { Node* next = current->next; free(current); current = next; } } free(map); } int main() { HashMap* map = HashMap_Create(); HashMap_Insert(map, "key1", 1); HashMap_Insert(map, "key2", 2); HashMap_Insert(map, "key3", 3); printf("value for key1: %d\n", HashMap_Get(map, "key1")); printf("value for key2: %d\n", HashMap_Get(map, "key2")); printf("value for key3: %d\n", HashMap_Get(map, "key3")); HashMap_Remove(map, "key2"); printf("value for key2: %d\n", HashMap_Get(map, "key2")); HashMap_Destroy(map); return 0; } ``` 这个示例演示了如何使用哈希表和链表组合来实现一个类似 unordered_map 的数据结构。你可以根据实际需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值