飞道的博客

单向链表删除并清空操作 注意

476人阅读  评论(0)

    在之前的文章《深入理解Linux内核之链表 list.h 功能实现原理、接口说明及示例代码》中详细的分析了链表的各种操作,我们经常使用的操作是“初始化”、“ 添加节点”、“遍历”、“删除”,对于链表节点的删除,使用的相对少,而且由于 删除操作的 宏函数 定义的复杂,容易混淆,本文基于此,对 链表的删除清空做下备忘录。

以单向链表结构 为例,用到的宏函数有2个,分别为:


  
  1. /*
  2. * Iterate over list of given type safe against removal of list entry.
  3. *
  4. * @param[in] queue the head for your list.
  5. * @param[in] tmp the type * to use as a temp.
  6. * @param[in] node the type * to use as a loop cursor.
  7. * @param[in] type the type of the struct this is embedded in.
  8. * @param[in] member the name of the slist_t within the struct.
  9. */
  10. #define slist_for_each_entry_safe(queue, tmp, node, type, member) \
  11. for (node = container_of((queue)->next, type, member), \
  12. tmp = (queue)->next ? (queue)->next->next : NULL; \
  13. &node->member; \
  14. node = container_of(tmp, type, member), tmp = tmp ? tmp->next : tmp)
  15. /* 节点删除 */
  16. static inline void slist_del(slist_t *node, slist_t *head)
  17. {
  18. while (head->next) {
  19. if (head->next == node) {
  20. head->next = node->next;
  21. break;
  22. }
  23. head = head->next;
  24. }
  25. }

   其中 slist_for_each_entry_safe 中包含了 “safe” ,含义是 “安全”, 专用于 链表删除 的 遍历动作。这个函数的参数类型容易有歧义,这里我们做下 解释:


  
  1. /*
  2. * Iterate over list of given type safe against removal of list entry.
  3. *
  4. * @param[in] queue 链表 头 head 指针, 是一个指针
  5. * @param[in] tmp struct slist_s * 类型的 临时指针变量
  6. * @param[in] node 我们自己的 链表结构 节点 指针,.
  7. * @param[in] type 我们自己定义的 链表结构体类型, 必须要包含 struct slist_s list 成员.
  8. * @param[in] member 我们自己定义的 链表结构体类型 中的 list 成员
  9. */
  10. #define slist_for_each_entry_safe(queue, tmp, node, type, member)

  而 slist_del(slist_t *node, slist_t *head) 的参数解释如下:


  
  1. /*
  2. * Iterate over list of given type safe against removal of list entry.
  3. *
  4. * @param[in] node struct slist_s * 类型的 节点变量,是一个指针
  5. * @param[in] head 链表 头 head 指针, 是一个指针
  6. */
  7. static inline void slist_del(slist_t *node, slist_t *head)

  删除并释放 所有链表节点的 程序案例:


  
  1. /* 自定义的 链表结构体*/
  2. typedef struct{
  3. int id
  4. int a;
  5. int b;
  6. struct slist_s list;
  7. } usr_list_info_t;
  8. /*--------------- 删除整个链表的伪操作 ---------------*/
  9. struct slist_s *head = get_usr_list_head();
  10. struct slist_s *tmp = NULL;
  11. usr_list_info_t *node = NULL;
  12. slist_for_each_entry_safe(head, tmp, node, usr_list_info_t, list){
  13. slist_del(&(node->list), head);
  14. free(node);
  15. }

     如果想删除某一个节点,也是上面的套路,只不过在遍历所有的节点同时,判断当前节点是否是我们想要删除的节点,如果是,则删除,不是则接着遍历。


转载:https://blog.csdn.net/u012351051/article/details/103736625
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场