前面我们介绍了如何在 C 语言中引入面向对象语言的一些特性来进行面向对象编程,从本篇开始,我们使用前面提到的技巧,陆续实现几个例子,最后呢,会提供一个基本的 http server 实现(使用 libevent )。在这篇文章里,我们实现一个通用的数据结构:单链表。

这里实现的单链表,可以存储任意数据类型,支持增、删、改、查找、插入等基本操作。(本文提供的是完整代码,可能有些长。)

下面是头文件:

[cpp] view plaincopy print?
  1. #ifndef SLIST_H
  2. #define SLIST_H
  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif
  6. #define NODE_T(ptr, type) ((type*)ptr)
  7. struct slist_node {
  8. struct slist_node * next;
  9. };
  10. typedef void (*list_op_free_node)(struct slist_node *node);
  11. /*
  12. * return 0 on hit key, else return none zero
  13. */
  14. typedef int (*list_op_key_hit_test)(struct slist_node *node, void *key);
  15. struct single_list {
  16. /* all the members must not be changed manually by callee */
  17. struct slist_node * head;
  18. struct slist_node * tail;
  19. int size; /* length of the list, do not change it manually*/
  20. /* free method to delete the node
  21. */
  22. void (*free_node)(struct slist_node *node);
  23. /*
  24. * should be set by callee, used to locate node by key(*_by_key() method)
  25. * return 0 on hit key, else return none zero
  26. */
  27. int (*key_hit_test)(struct slist_node *node, void *key);
  28. struct single_list *(*add)(struct single_list * list, struct slist_node * node);
  29. struct single_list *(*insert)(struct single_list * list, int pos, struct slist_node *node);
  30. /* NOTE: the original node at the pos will be freed by free_node */
  31. struct single_list *(*replace)(struct single_list *list, int pos, struct slist_node *node);
  32. struct slist_node *(*find_by_key)(struct single_list *, void * key);
  33. struct slist_node *(*first)(struct single_list* list);
  34. struct slist_node *(*last)(struct single_list* list);
  35. struct slist_node *(*at)(struct single_list * list, int pos);
  36. struct slist_node *(*take_at)(struct single_list * list, int pos);
  37. struct slist_node *(*take_by_key)(struct single_list * list, void *key);
  38. struct single_list *(*remove)(struct single_list * list, struct slist_node * node);
  39. struct single_list *(*remove_at)(struct single_list *list, int pos);
  40. struct single_list *(*remove_by_key)(struct single_list *list, void *key);
  41. int (*length)(struct single_list * list);
  42. void (*clear)(struct single_list * list);
  43. void (*deletor)(struct single_list *list);
  44. };
  45. struct single_list * new_single_list(list_op_free_node op_free, list_op_key_hit_test op_cmp);
  46. #ifdef __cplusplus
  47. }
  48. #endif
  49. #endif // SLIST_H
#ifndef SLIST_H
#define SLIST_H#ifdef __cplusplus
extern "C" {
#endif#define NODE_T(ptr, type) ((type*)ptr)struct slist_node {struct slist_node * next;
};typedef void (*list_op_free_node)(struct slist_node *node);
/** return 0 on hit key, else return none zero*/
typedef int (*list_op_key_hit_test)(struct slist_node *node, void *key);struct single_list {/* all the members must not be changed manually by callee */struct slist_node * head;struct slist_node * tail;int size; /* length of the list, do not change it manually*//* free method to delete the node*/void (*free_node)(struct slist_node *node);/** should be set by callee, used to locate node by key(*_by_key() method)* return 0 on hit key, else return none zero*/int (*key_hit_test)(struct slist_node *node, void *key);struct single_list *(*add)(struct single_list * list, struct slist_node * node);struct single_list *(*insert)(struct single_list * list, int pos, struct slist_node *node);/* NOTE: the original node at the pos will be freed by free_node */struct single_list *(*replace)(struct single_list *list, int pos, struct slist_node *node);struct slist_node *(*find_by_key)(struct single_list *, void * key);struct slist_node *(*first)(struct single_list* list);struct slist_node *(*last)(struct single_list* list);struct slist_node *(*at)(struct single_list * list, int pos);struct slist_node *(*take_at)(struct single_list * list, int pos);struct slist_node *(*take_by_key)(struct single_list * list, void *key);struct single_list *(*remove)(struct single_list * list, struct slist_node * node);struct single_list *(*remove_at)(struct single_list *list, int pos);struct single_list *(*remove_by_key)(struct single_list *list, void *key);int (*length)(struct single_list * list);void (*clear)(struct single_list * list);void (*deletor)(struct single_list *list);
};struct single_list * new_single_list(list_op_free_node op_free, list_op_key_hit_test op_cmp);#ifdef __cplusplus
}
#endif#endif // SLIST_H

struct single_list 这个类,遵循我们前面介绍的基本原则,不再一一细说。有几点需要提一下:

  • 我们定义了 slist_node 作为链表节点的基类,用户自定义的节点,都必须从 slist_node 继承
  • 为了支持节点( node )的释放,我们引入一个回调函数 list_op_free_node ,这个回调需要在创建链表时传入
  • 为了支持查找,引入另外一个回调函数 list_op_key_hit_test

好了,下面看实现文件:

[cpp] view plaincopy print?
  1. #include "slist.h"
  2. #include <malloc.h>
  3. static struct single_list * _add_node(struct single_list *list, struct slist_node *node)
  4. {
  5. if(list->tail)
  6. {
  7. list->tail->next = node;
  8. node->next = 0;
  9. list->tail = node;
  10. list->size++;
  11. }
  12. else
  13. {
  14. list->head = node;
  15. list->tail = node;
  16. node->next = 0;
  17. list->size = 1;
  18. }
  19. return list;
  20. }
  21. static struct single_list * _insert_node(struct single_list * list, int pos, struct slist_node *node)
  22. {
  23. if(pos < list->size)
  24. {
  25. int i = 0;
  26. struct slist_node * p = list->head;
  27. struct slist_node * prev = list->head;
  28. for(; i < pos; i++)
  29. {
  30. prev = p;
  31. p = p->next;
  32. }
  33. if(p == list->head)
  34. {
  35. /* insert at head */
  36. node->next = list->head;
  37. list->head = node;
  38. }
  39. else
  40. {
  41. prev->next = node;
  42. node->next = p;
  43. }
  44. if(node->next == 0) list->tail = node;
  45. list->size++;
  46. }
  47. else
  48. {
  49. list->add(list, node);
  50. }
  51. return list;
  52. }
  53. static struct single_list * _replace(struct single_list * list, int pos, struct slist_node *node)
  54. {
  55. if(pos < list->size)
  56. {
  57. int i = 0;
  58. struct slist_node * p = list->head;
  59. struct slist_node * prev = list->head;
  60. for(; i < pos; i++)
  61. {
  62. prev = p;
  63. p = p->next;
  64. }
  65. if(p == list->head)
  66. {
  67. /* replace at head */
  68. node->next = list->head->next;
  69. list->head = node;
  70. }
  71. else
  72. {
  73. prev->next = node;
  74. node->next = p->next;
  75. }
  76. if(node->next == 0) list->tail = node;
  77. if(list->free_node) list->free_node(p);
  78. else free(p);
  79. }
  80. return list;
  81. }
  82. static struct slist_node * _find_by_key(struct single_list *list, void * key)
  83. {
  84. if(list->key_hit_test)
  85. {
  86. struct slist_node * p = list->head;
  87. while(p)
  88. {
  89. if(list->key_hit_test(p, key) == 0) return p;
  90. p = p->next;
  91. }
  92. }
  93. return 0;
  94. }
  95. static struct slist_node *_first_of(struct single_list* list)
  96. {
  97. return list->head;
  98. }
  99. static struct slist_node *_last_of(struct single_list* list)
  100. {
  101. return list->tail;
  102. }
  103. static struct slist_node *_node_at(struct single_list * list, int pos)
  104. {
  105. if(pos < list->size)
  106. {
  107. int i = 0;
  108. struct slist_node * p = list->head;
  109. for(; i < pos; i++)
  110. {
  111. p = p->next;
  112. }
  113. return p;
  114. }
  115. return 0;
  116. }
  117. static struct slist_node * _take_at(struct single_list * list, int pos)
  118. {
  119. if(pos < list->size)
  120. {
  121. int i = 0;
  122. struct slist_node * p = list->head;
  123. struct slist_node * prev = p;
  124. for(; i < pos ; i++)
  125. {
  126. prev = p;
  127. p = p->next;
  128. }
  129. if(p == list->head)
  130. {
  131. list->head = p->next;
  132. if(list->head == 0) list->tail = 0;
  133. }
  134. else if(p == list->tail)
  135. {
  136. list->tail = prev;
  137. prev->next = 0;
  138. }
  139. else
  140. {
  141. prev->next = p->next;
  142. }
  143. list->size--;
  144. p->next = 0;
  145. return p;
  146. }
  147. return 0;
  148. }
  149. static struct slist_node * _take_by_key(struct single_list * list, void *key)
  150. {
  151. if(list->key_hit_test)
  152. {
  153. struct slist_node * p = list->head;
  154. struct slist_node * prev = p;
  155. while(p)
  156. {
  157. if(list->key_hit_test(p, key) == 0) break;
  158. prev = p;
  159. p = p->next;
  160. }
  161. if(p)
  162. {
  163. if(p == list->head)
  164. {
  165. list->head = p->next;
  166. if(list->head == 0) list->tail = 0;
  167. }
  168. else if(p == list->tail)
  169. {
  170. list->tail = prev;
  171. prev->next = 0;
  172. }
  173. else
  174. {
  175. prev->next = p->next;
  176. }
  177. list->size--;
  178. p->next = 0;
  179. return p;
  180. }
  181. }
  182. return 0;
  183. }
  184. static struct single_list *_remove_node(struct single_list * list, struct slist_node * node)
  185. {
  186. struct slist_node * p = list->head;
  187. struct slist_node * prev = p;
  188. while(p)
  189. {
  190. if(p == node) break;
  191. prev = p;
  192. p = p->next;
  193. }
  194. if(p)
  195. {
  196. if(p == list->head)
  197. {
  198. list->head = list->head->next;
  199. if(list->head == 0) list->tail = 0;
  200. }
  201. else if(p == list->tail)
  202. {
  203. prev->next = 0;
  204. list->tail = prev;
  205. }
  206. else
  207. {
  208. prev->next = p->next;
  209. }
  210. if(list->free_node) list->free_node(p);
  211. else free(p);
  212. list->size--;
  213. }
  214. return list;
  215. }
  216. static struct single_list *_remove_at(struct single_list *list, int pos)
  217. {
  218. if(pos < list->size)
  219. {
  220. int i = 0;
  221. struct slist_node * p = list->head;
  222. struct slist_node * prev = p;
  223. for(; i < pos ; i++)
  224. {
  225. prev = p;
  226. p = p->next;
  227. }
  228. if(p == list->head)
  229. {
  230. list->head = p->next;
  231. if(list->head == 0) list->tail = 0;
  232. }
  233. else if(p == list->tail)
  234. {
  235. list->tail = prev;
  236. prev->next = 0;
  237. }
  238. else
  239. {
  240. prev->next = p->next;
  241. }
  242. if(list->free_node) list->free_node(p);
  243. else free(p);
  244. list->size--;
  245. }
  246. return list;
  247. }
  248. static struct single_list *_remove_by_key(struct single_list *list, void *key)
  249. {
  250. if(list->key_hit_test)
  251. {
  252. struct slist_node * p = list->head;
  253. struct slist_node * prev = p;
  254. while(p)
  255. {
  256. if(list->key_hit_test(p, key) == 0) break;
  257. prev = p;
  258. p = p->next;
  259. }
  260. if(p)
  261. {
  262. if(p == list->head)
  263. {
  264. list->head = list->head->next;
  265. if(list->head == 0) list->tail = 0;
  266. }
  267. else if(p == list->tail)
  268. {
  269. prev->next = 0;
  270. list->tail = prev;
  271. }
  272. else
  273. {
  274. prev->next = p->next;
  275. }
  276. if(list->free_node) list->free_node(p);
  277. else free(p);
  278. list->size--;
  279. }
  280. }
  281. return list;
  282. }
  283. static int _length_of(struct single_list * list)
  284. {
  285. return list->size;
  286. }
  287. static void _clear_list(struct single_list * list)
  288. {
  289. struct slist_node * p = list->head;
  290. struct slist_node * p2;
  291. while(p)
  292. {
  293. p2 = p;
  294. p = p->next;
  295. if(list->free_node) list->free_node(p2);
  296. else free(p2);
  297. }
  298. list->head = 0;
  299. list->tail = 0;
  300. list->size = 0;
  301. }
  302. static void _delete_single_list(struct single_list *list)
  303. {
  304. list->clear(list);
  305. free(list);
  306. }
  307. struct single_list * new_single_list(list_op_free_node op_free, list_op_key_hit_test op_cmp)
  308. {
  309. struct single_list *list = (struct single_list *)malloc(sizeof(struct single_list));
  310. list->head = 0;
  311. list->tail = 0;
  312. list->size = 0;
  313. list->free_node = op_free;
  314. list->key_hit_test = op_cmp;
  315. list->add = _add_node;
  316. list->insert = _insert_node;
  317. list->replace = _replace;
  318. list->find_by_key = _find_by_key;
  319. list->first = _first_of;
  320. list->last = _last_of;
  321. list->at = _node_at;
  322. list->take_at = _take_at;
  323. list->take_by_key = _take_by_key;
  324. list->remove = _remove_node;
  325. list->remove_at = _remove_at;
  326. list->remove_by_key = _remove_by_key;
  327. list->length = _length_of;
  328. list->clear = _clear_list;
  329. list->deletor = _delete_single_list;
  330. return list;
  331. }
#include "slist.h"
#include <malloc.h>static struct single_list * _add_node(struct single_list *list, struct slist_node *node)
{if(list->tail){list->tail->next = node;node->next = 0;list->tail = node;list->size++;}else{list->head = node;list->tail = node;node->next = 0;list->size = 1;}return list;
}static struct single_list * _insert_node(struct single_list * list, int pos, struct slist_node *node)
{if(pos < list->size){int i = 0;struct slist_node * p = list->head;struct slist_node * prev = list->head;for(; i < pos; i++){prev = p;p = p->next;}if(p == list->head){/* insert at head */node->next = list->head;list->head = node;}else{prev->next = node;node->next = p;}if(node->next == 0) list->tail = node;list->size++;}else{list->add(list, node);}return list;
}static struct single_list * _replace(struct single_list * list, int pos, struct slist_node *node)
{if(pos < list->size){int i = 0;struct slist_node * p = list->head;struct slist_node * prev = list->head;for(; i < pos; i++){prev = p;p = p->next;}if(p == list->head){/* replace at head */node->next = list->head->next;list->head = node;}else{prev->next = node;node->next = p->next;}if(node->next == 0) list->tail = node;if(list->free_node) list->free_node(p);else free(p);}return list;
}static struct slist_node * _find_by_key(struct single_list *list, void * key)
{if(list->key_hit_test){struct slist_node * p = list->head;while(p){if(list->key_hit_test(p, key) == 0) return p;p = p->next;}}return 0;
}static struct slist_node *_first_of(struct single_list* list)
{return list->head;
}static struct slist_node *_last_of(struct single_list* list)
{return list->tail;
}static struct slist_node *_node_at(struct single_list * list, int pos)
{if(pos < list->size){int i = 0;struct slist_node * p = list->head;for(; i < pos; i++){p = p->next;}return p;}return 0;
}static struct slist_node * _take_at(struct single_list * list, int pos)
{if(pos < list->size){int i = 0;struct slist_node * p = list->head;struct slist_node * prev = p;for(; i < pos ; i++){prev = p;p = p->next;}if(p == list->head){list->head = p->next;if(list->head == 0) list->tail = 0;}else if(p == list->tail){list->tail = prev;prev->next = 0;}else{prev->next = p->next;}list->size--;p->next = 0;return p;}return 0;
}static struct slist_node * _take_by_key(struct single_list * list, void *key)
{if(list->key_hit_test){struct slist_node * p = list->head;struct slist_node * prev = p;while(p){if(list->key_hit_test(p, key) == 0) break;prev = p;p = p->next;}if(p){if(p == list->head){list->head = p->next;if(list->head == 0) list->tail = 0;}else if(p == list->tail){list->tail = prev;prev->next = 0;}else{prev->next = p->next;}list->size--;p->next = 0;return p;}}return 0;
}static struct single_list *_remove_node(struct single_list * list, struct slist_node * node)
{struct slist_node * p = list->head;struct slist_node * prev = p;while(p){if(p == node) break;prev = p;p = p->next;}if(p){if(p == list->head){list->head = list->head->next;if(list->head == 0) list->tail = 0;}else if(p == list->tail){prev->next = 0;list->tail = prev;}else{prev->next = p->next;}if(list->free_node) list->free_node(p);else free(p);list->size--;}return list;
}static struct single_list *_remove_at(struct single_list *list, int pos)
{if(pos < list->size){int i = 0;struct slist_node * p = list->head;struct slist_node * prev = p;for(; i < pos ; i++){prev = p;p = p->next;}if(p == list->head){list->head = p->next;if(list->head == 0) list->tail = 0;}else if(p == list->tail){list->tail = prev;prev->next = 0;}else{prev->next = p->next;}if(list->free_node) list->free_node(p);else free(p);list->size--;}return list;
}static struct single_list *_remove_by_key(struct single_list *list, void *key)
{if(list->key_hit_test){struct slist_node * p = list->head;struct slist_node * prev = p;while(p){if(list->key_hit_test(p, key) == 0) break;prev = p;p = p->next;}if(p){if(p == list->head){list->head = list->head->next;if(list->head == 0) list->tail = 0;}else if(p == list->tail){prev->next = 0;list->tail = prev;}else{prev->next = p->next;}if(list->free_node) list->free_node(p);else free(p);list->size--;}}return list;
}static int _length_of(struct single_list * list)
{return list->size;
}static void _clear_list(struct single_list * list)
{struct slist_node * p = list->head;struct slist_node * p2;while(p){p2 = p;p = p->next;if(list->free_node) list->free_node(p2);else free(p2);}list->head = 0;list->tail = 0;list->size = 0;
}static void _delete_single_list(struct single_list *list)
{list->clear(list);free(list);
}struct single_list * new_single_list(list_op_free_node op_free, list_op_key_hit_test op_cmp)
{struct single_list *list = (struct single_list *)malloc(sizeof(struct single_list));list->head = 0;list->tail = 0;list->size = 0;list->free_node = op_free;list->key_hit_test = op_cmp;list->add = _add_node;list->insert = _insert_node;list->replace = _replace;list->find_by_key = _find_by_key;list->first = _first_of;list->last = _last_of;list->at = _node_at;list->take_at = _take_at;list->take_by_key = _take_by_key;list->remove = _remove_node;list->remove_at = _remove_at;list->remove_by_key = _remove_by_key;list->length = _length_of;list->clear = _clear_list;list->deletor = _delete_single_list;return list;
}

上面的代码就不一一细说了,下面是测试代码:

[cpp] view plaincopy print?
  1. /* call 1 or N arguments function of struct */
  2. #define ST_CALL(THIS,func,args...) ((THIS)->func(THIS,args))
  3. /* call none-arguments function of struct */
  4. #define ST_CALL_0(THIS,func) ((THIS)->func(THIS))
  5. struct int_node {
  6. struct slist_node node;
  7. int id;
  8. };
  9. struct string_node {
  10. struct slist_node node;
  11. char name[16];
  12. };
  13. static int int_free_flag = 0;
  14. static void _int_child_free(struct slist_node *node)
  15. {
  16. free(node);
  17. if(!int_free_flag)
  18. {
  19. int_free_flag = 1;
  20. printf("int node free\n");
  21. }
  22. }
  23. static int _int_slist_hittest(struct slist_node * node, void *key)
  24. {
  25. struct int_node * inode = NODE_T(node, struct int_node);
  26. int ikey = (int)key;
  27. return (inode->id == ikey ? 0 : 1);
  28. }
  29. static int string_free_flag = 0;
  30. static void _string_child_free(struct slist_node *node)
  31. {
  32. free(node);
  33. if(!string_free_flag)
  34. {
  35. string_free_flag = 1;
  36. printf("string node free\n");
  37. }
  38. }
  39. static int _string_slist_hittest(struct slist_node * node, void *key)
  40. {
  41. struct string_node * sn = (struct string_node*)node;
  42. return strcmp(sn->name, (char*)key);
  43. }
  44. void int_slist_test()
  45. {
  46. struct single_list * list = new_single_list(_int_child_free, _int_slist_hittest);
  47. struct int_node * node = 0;
  48. struct slist_node * bn = 0;
  49. int i = 0;
  50. printf("create list && nodes:\n");
  51. for(; i < 100; i++)
  52. {
  53. node = (struct int_node*)malloc(sizeof(struct int_node));
  54. node->id = i;
  55. if(i%10)
  56. {
  57. list->add(list, node);
  58. }
  59. else
  60. {
  61. list->insert(list, 1, node);
  62. }
  63. }
  64. printf("create 100 nodes end\n----\n");
  65. printf("first is : %d, last is: %d\n----\n",
  66. NODE_T( ST_CALL_0(list, first), struct int_node )->id,
  67. NODE_T( ST_CALL_0(list, last ), struct int_node )->id);
  68. assert(list->size == 100);
  69. printf("list traverse:\n");
  70. for(i = 0; i < 100; i++)
  71. {
  72. if(i%10 == 0) printf("\n");
  73. bn = list->at(list, i);
  74. node = NODE_T(bn, struct int_node);
  75. printf(" %d", node->id);
  76. }
  77. printf("\n-----\n");
  78. printf("find by key test, key=42:\n");
  79. bn = list->find_by_key(list, (void*)42);
  80. assert(bn != 0);
  81. node = NODE_T(bn, struct int_node);
  82. printf("find node(key=42), %d\n------\n", node->id);
  83. printf("remove node test, remove the 10th node:\n");
  84. bn = list->at(list, 10);
  85. node = NODE_T(bn, struct int_node);
  86. printf("  node 10 is: %d\n", node->id);
  87. printf("  now remove node 10\n");
  88. list->remove_at(list, 10);
  89. printf(" node 10 was removed, check node 10 again:\n");
  90. bn = list->at(list, 10);
  91. node = NODE_T(bn, struct int_node);
  92. printf("  now node 10 is: %d\n------\n", node->id);
  93. printf("replace test, replace node 12 with id 1200:\n");
  94. bn = list->at(list, 12);
  95. node = NODE_T(bn, struct int_node);
  96. printf("  now node 12 is : %d\n", node->id);
  97. node = (struct int_node*)malloc(sizeof(struct int_node));
  98. node->id = 1200;
  99. list->replace(list, 12, node);
  100. bn = list->at(list, 12);
  101. node = NODE_T(bn, struct int_node);
  102. printf("  replaced, now node 12 is : %d\n----\n", node->id);
  103. printf("test remove:\n");
  104. ST_CALL(list, remove, bn);
  105. bn = ST_CALL(list, find_by_key, (void*)1200);
  106. assert(bn == 0);
  107. printf("test remove ok\n----\n");
  108. printf("test remove_by_key(90):\n");
  109. ST_CALL(list, remove_by_key, (void*)90);
  110. bn = ST_CALL(list, find_by_key, (void*)90);
  111. assert(bn == 0);
  112. printf("test remove_by_key(90) end\n----\n");
  113. printf("test take_at(80):\n");
  114. bn = ST_CALL(list, take_at, 80);
  115. printf("  node 80 is: %d\n", NODE_T(bn, struct int_node)->id);
  116. free(bn);
  117. printf("test take_at(80) end\n");
  118. int_free_flag = 0;
  119. printf("delete list && nodes:\n");
  120. list->deletor(list);
  121. printf("delete list && nodes end\n");
  122. printf("\n test add/insert/remove/delete/find_by_key/replace...\n");
  123. }
  124. void string_slist_test()
  125. {
  126. struct single_list * list = new_single_list(_string_child_free, _string_slist_hittest);
  127. }
  128. void slist_test()
  129. {
  130. int_slist_test();
  131. string_slist_test();
  132. }
/* call 1 or N arguments function of struct */
#define ST_CALL(THIS,func,args...) ((THIS)->func(THIS,args))/* call none-arguments function of struct */
#define ST_CALL_0(THIS,func) ((THIS)->func(THIS))struct int_node {struct slist_node node;int id;
};struct string_node {struct slist_node node;char name[16];
};static int int_free_flag = 0;
static void _int_child_free(struct slist_node *node)
{free(node);if(!int_free_flag){int_free_flag = 1;printf("int node free\n");}
}static int _int_slist_hittest(struct slist_node * node, void *key)
{struct int_node * inode = NODE_T(node, struct int_node);int ikey = (int)key;return (inode->id == ikey ? 0 : 1);
}static int string_free_flag = 0;
static void _string_child_free(struct slist_node *node)
{free(node);if(!string_free_flag){string_free_flag = 1;printf("string node free\n");}
}static int _string_slist_hittest(struct slist_node * node, void *key)
{struct string_node * sn = (struct string_node*)node;return strcmp(sn->name, (char*)key);
}void int_slist_test()
{struct single_list * list = new_single_list(_int_child_free, _int_slist_hittest);struct int_node * node = 0;struct slist_node * bn = 0;int i = 0;printf("create list && nodes:\n");for(; i < 100; i++){node = (struct int_node*)malloc(sizeof(struct int_node));node->id = i;if(i%10){list->add(list, node);}else{list->insert(list, 1, node);}}printf("create 100 nodes end\n----\n");printf("first is : %d, last is: %d\n----\n",NODE_T( ST_CALL_0(list, first), struct int_node )->id,NODE_T( ST_CALL_0(list, last ), struct int_node )->id);assert(list->size == 100);printf("list traverse:\n");for(i = 0; i < 100; i++){if(i%10 == 0) printf("\n");bn = list->at(list, i);node = NODE_T(bn, struct int_node);printf(" %d", node->id);}printf("\n-----\n");printf("find by key test, key=42:\n");bn = list->find_by_key(list, (void*)42);assert(bn != 0);node = NODE_T(bn, struct int_node);printf("find node(key=42), %d\n------\n", node->id);printf("remove node test, remove the 10th node:\n");bn = list->at(list, 10);node = NODE_T(bn, struct int_node);printf("  node 10 is: %d\n", node->id);printf("  now remove node 10\n");list->remove_at(list, 10);printf(" node 10 was removed, check node 10 again:\n");bn = list->at(list, 10);node = NODE_T(bn, struct int_node);printf("  now node 10 is: %d\n------\n", node->id);printf("replace test, replace node 12 with id 1200:\n");bn = list->at(list, 12);node = NODE_T(bn, struct int_node);printf("  now node 12 is : %d\n", node->id);node = (struct int_node*)malloc(sizeof(struct int_node));node->id = 1200;list->replace(list, 12, node);bn = list->at(list, 12);node = NODE_T(bn, struct int_node);printf("  replaced, now node 12 is : %d\n----\n", node->id);printf("test remove:\n");ST_CALL(list, remove, bn);bn = ST_CALL(list, find_by_key, (void*)1200);assert(bn == 0);printf("test remove ok\n----\n");printf("test remove_by_key(90):\n");ST_CALL(list, remove_by_key, (void*)90);bn = ST_CALL(list, find_by_key, (void*)90);assert(bn == 0);printf("test remove_by_key(90) end\n----\n");printf("test take_at(80):\n");bn = ST_CALL(list, take_at, 80);printf("  node 80 is: %d\n", NODE_T(bn, struct int_node)->id);free(bn);printf("test take_at(80) end\n");int_free_flag = 0;printf("delete list && nodes:\n");list->deletor(list);printf("delete list && nodes end\n");printf("\n test add/insert/remove/delete/find_by_key/replace...\n");
}void string_slist_test()
{struct single_list * list = new_single_list(_string_child_free, _string_slist_hittest);
}void slist_test()
{int_slist_test();string_slist_test();
}

测试代码里主要演示了:

  • 自定义链表节点类型
  • 定义释放回调
  • 定义用于查找的 hit test 回调
  • 如何创建链表
  • 如何使用( add 、remove 、 take 、find 、 insert 等)

相信到这里,单链表的使用已经不成问题了。

以单链表为基础,可以进一步实现很多数据结构,比如树(兄弟孩子表示法),比如 key-value 链表等等。接下来根据例子的需要,会择机进行展示。

C语言面向对象编程(五):单链表实现相关推荐

  1. c语言面向对象编程显示,c语言面向对象编程

    场景:C语言面向对象编程(6):配置文件解析 C语言面向对象编程(六):配置文件解析 在实际项目中,经常会把软件的某些选项写入配置文件. Windows 平台上的 INI 文件格式简单易用,本篇文章利 ...

  2. C语言面向对象编程(六):配置文件解析

    在实际项目中,经常会把软件的某些选项写入配置文件. Windows 平台上的 INI 文件格式简单易用,本篇文章利用<C语言面向对象编程(五):单链表实现>中实现的单链表,设计了一个&qu ...

  3. C语言面向对象编程(四):面向接口编程

    Java 中有 interface 关键字,C++ 中有抽象类或纯虚类可以与 interface 比拟,C 语言中也可以实现类似的特性. 在面试 Java 程序员时我经常问的一个问题是:接口和抽象类有 ...

  4. 《数据结构》c语言版学习笔记——单链表结构(线性表的链式存储结构Part1)

    线性表的链式存储结构 数据结构系列文章 第二章 单链表结构 文章目录 线性表的链式存储结构 前言 一.单链表的建立 代码 二.单链表的读取 代码 三.单链表的插入 代码 四.单链表的删除 代码 五.单 ...

  5. java 168转换成861_java实验-java语言面向对象编程基础

    java实验-java语言面向对象编程基础 (12页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 8.90 积分 广州大学学生实验报告广州大学学生实验报告 ...

  6. c语言面向对象编程中的类_C ++中的面向对象编程

    c语言面向对象编程中的类 Object oriented programming, OOP for short, aims to implement real world entities like ...

  7. C语言面向对象编程(二):继承详解

    在  C 语言面向对象编程(一)里说到继承,这里再详细说一下. C++ 中的继承,从派生类与基类的关系来看(出于对比 C 与 C++,只说公有继承): 派生类内部可以直接使用基类的 public .p ...

  8. 我所偏爱的 C 语言面向对象编程范式

    我所偏爱的 C 语言面向对象编程范式 面向对象编程不是银弹.大部分场合,我对面向对象的使用非常谨慎,能不用则不用.相关的讨论就不展开了. 但是,某些场合下,采用面向对象的确是比较好的方案.比如 UI ...

  9. c语言二维图形变换程序,C语言图形编程(五、二维图形变换-01)(国外英文资料).doc...

    C语言图形编程(五.二维图形变换-01)(国外英文资料) C语言图形编程(五.二维图形变换-01)(国外英文资料) The first user coordinates to the screen c ...

  10. Nwafu-OJ-1485 Problem o C语言实习题八——单链表结点的阶乘和

    问题 : C语言实习题八--单链表结点的阶乘和 时间限制: 1 Sec  内存限制: 128 MB 提交: 5120  解决: 1555 [提交][状态][讨论版] 题目描述 要求实现一个函数,求单向 ...

最新文章

  1. 异常处理python要求输入的为英文_python(异常处理)
  2. JavaScript 是传值调用还是传引用调用?
  3. 存储过程——介绍(一)
  4. python解释器环境中用于表示上一次运算结果的特殊变量_判断正误 PUSH CL_学小易找答案...
  5. 高级技巧之Lambda表达式
  6. 深度学习数据集制作_深度学习时代的数据驱动建模之探讨
  7. python 单链表是否有回路_(Python3)数据结构--单链表之判断链表是否有环
  8. JQuery使用总结
  9. [蓝桥杯]试题 基础练习 Huffuman树
  10. 在信号处理函数中调用longjmp
  11. 如何高效率获取作物类型分布数据?
  12. 95后妈妈8成是全职,爸爸去哪了?
  13. js html实体编码转换,字符串js编码转换成实体html编码的方法(防范XSS攻击)
  14. LayUI表单验证select定位失效问题
  15. IP这么火究竟什么才是有价值的IP
  16. 传感器技术—压电式传感器(学习笔记八)
  17. Elasticsearch优化的一些建议
  18. python 转Excel二维表为一维表
  19. 面试被问扔鸡蛋问题:100层扔鸡蛋问题(扔球问题)
  20. OPNET入门2-Basic Process

热门文章

  1. idea在目录中前添加目录_[LaTeX Beamer] 为目录项添加页码
  2. am5728 是否支持aarch64_am5728开启uart0接口通讯
  3. pintos实验三文档_实验室如何实现智能、数字化管理?
  4. java mysql 清空表_MySQL 删除数据表
  5. 201671030125+词频统计软件项目报告
  6. 「日常训练」Skills(Codeforce Round #339 Div.2 D)
  7. 《mysql必知必会》学习_第11章_20180801_欢
  8. 你应该知道的 RPC 原理
  9. C# viewstate
  10. 从一次线下读书会获得的收获