glibc 库双向链表操作--解析(源码: list.h)

注意:  1.使用时包含头文件<List.h>

           2.或者<tls.h>

           3.如果头文件不存在就将以下代码另存且包含: include "list.h"

           4.Linux内核在<linux/list.h>目录下也提供了链表操作函数, 但是接口不太一样, 但是功能更全

以下是源代码及其使用方法:

#ifndef _LIST_H
#define _LIST_H	1

/* The definitions of this file are adopted from those which can be
   found in the Linux kernel headers to enable people familiar with
   the latter find their way in these sources as well.  */


/* Basic type for the double-link list.  */
typedef struct list_head
{
  struct list_head *next;
  struct list_head *prev;
} list_t;

// 定义/创建一个名为name的链表头, 上一项自己, 下一项也指向自己
/* Define a variable with the head and tail of the list.  */
#define LIST_HEAD(name) \
  list_t name = { &(name), &(name) }


// 将传入的ptr作为链表头
/* Initialize a new list head.  */
#define INIT_LIST_HEAD(ptr) \
  (ptr)->next = (ptr)->prev = (ptr)

/* 紧挨着链表头增加新节点(节点不包含数据)
		head   new(节点)	  2		
*/
/* Add new element at the head of the list.  */
static inline void
list_add (list_t *newp, list_t *head)
{
  head->next->prev = newp;		// 2的上一项是new
  newp->next = head->next;		// new的下一项是2
  newp->prev = head;			// new的上一项是head
  head->next = newp;			// head的下一项是new
}

/* 添加新元素到链表尾部
	head 	1	2	3 new
*/
/* Add new element at the tail of the list.  */
static inline void
list_add_tail (list_t *newp, list_t *head)
{
  head->prev->next = newp;	// 3的下一项是new
  newp->next = head;		// new的下一项时head
  newp->prev = head->prev;	// new的上一项时3
  head->prev = newp;		// 头的上一项new
}

/* 删除指定元素:
	(1)   1 elem 2
	(2) 当链表中只有链表头时, 链表头没有没删除(因为节点不包含数据)
		head	// 自己的上一项是自己
				// 自己的下一项也是自己
*/
/* Remove element from list.  */
static inline void
list_del (list_t *elem)
{
  elem->next->prev = elem->prev;	// 2的上一项是1
  elem->prev->next = elem->next;	// 1的下一项时2
}

/* 拼接两个链表:
	1.如果新增的链表只有一个链表头就不做任何处理(因为链表头不包含数据)
	2.	(head 	 2) 	+	(add  4  5)	
		==> (head 	(5 	 6)   2   3)		// 抛弃链表头add
*/
/* Join two lists.  */
static inline void
list_splice (list_t *add, list_t *head)
{
  /* Do nothing if the list which gets added is empty.  */
  if (add != add->next)
    {
      add->next->prev = head;		// 5的上一项是head
      add->prev->next = head->next; // 6的下一项是2
      head->next->prev = add->prev; // 2的上一项是6
      head->next = add->next;		// head的下一项是5
    }
}

// 根据节点ptr的地址,得到其type结构体的首地址, member是type结构体中的节点变量名
/* Get typed element from list at a given position.  */
#define list_entry(ptr, type, member) \
  ((type *) ((char *) (ptr) - (unsigned long) (&((type *) 0)->member)))


// 从第一个节点(head的下一项开始, 向后遍历head链表中的所有节点)
/* Iterate forward over the elements of the list.  */
#define list_for_each(pos, head) \
  for (pos = (head)->next; pos != (head); pos = pos->next)

// 从第最后一个节点(head的上一项开始, 向前遍历head链表中的所有节点)
/* Iterate forward over the elements of the list.  */
#define list_for_each_prev(pos, head) \
  for (pos = (head)->prev; pos != (head); pos = pos->prev)

// 1.从第最后一个节点(head的上一项开始, 向前遍历head链表中的所有节点)
// 2.当遍历过程中需要删除节点时, 用此函数
// 3.如果使用list_for_each_prev, 在删除节点后pos = pos->prev会出错
/* Iterate backwards over the elements list.  The list elements can be
   removed from the list while doing this.  */
#define list_for_each_prev_safe(pos, p, head) \
  for (pos = (head)->prev, p = pos->prev; \
       pos != (head); \
       pos = p, p = pos->prev)

#endif	/* list.h */

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值