双向循环链表---仿照linux内核实现

myList.h

#ifndef MYLIST_H_INCLUDED
#define MYLIST_H_INCLUDED

/*
仿照linux的链表操作的实现
*/

#undef NULL
#ifdef __cplusplus
    #define NULL 0
#else
    #define NULL ((void *)0)
#endif

struct list_head
{
    struct list_head *next;
    struct list_head *prev;
};

#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
	struct list_head name = LIST_HEAD_INIT(name)

//在(TYPE*)结构体中找到(MEMBER)成员的位置
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
//找到type的开始位置
#define list_entry(ptr, type, member) \
	(type *)((char *)ptr - offsetof(type,member))

//向后遍历链表。pos为当前位置,head为开始位置
#define list_for_each(pos, head) \
	for (pos = (head)->next; pos != (head); pos = pos->next)
#define list_for_each_safe(pos, n, head) \
	for (pos = (head)->next, n = pos->next; pos != (head); pos = n, n = pos->next)

//向前遍历链表。pos为当前位置,head为开始位置
#define list_for_each_prev(pos, head) \
    for (pos = (head)->prev; pos != (head); pos = pos->prev)
#define list_for_each_prev_safe(pos, n, head) \
	for (pos = (head)->prev, n = pos->prev; pos != (head); pos = n, n = pos->prev)

//???
#define list_first_entry(ptr, type, member) \
	list_entry((ptr)->next, type, member)

//初始化链表(链表头)
static inline void INIT_LIST_HEAD(struct list_head *list)
{
	list->next = list;
	list->prev = list;
}

//添加一个节点到链表中的基本操作
static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next)
{
	next->prev = new;
	new->next = next;
	new->prev = prev;
	prev->next = new;
}

//在链表头之后增加一个新节点。如1->2->3,增加4之后为1->4->2->3
static inline void list_add(struct list_head *new, struct list_head *head)
{
	__list_add(new, head, head->next);
}

//在链表的尾部增加一个新节点,如1->2->3,增加4之后为1->2->3->4
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
	__list_add(new, head->prev, head);
}

//删除一个链表中的节点,基本操作
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
	next->prev = prev;
	prev->next = next;
}

//删除一个链表中的节点,*entry为从链表找中摘除的节点,如果有内存申请则需要手动释放
static inline void list_del(struct list_head *entry)
{
	__list_del(entry->prev, entry->next);
	entry->next = NULL;
	entry->prev = NULL;
}

//删除一个链表中的节点并把删除的节点初始化,*entry为从链表找中摘除的节点,如果有内存申请则需要手动释放
static inline void list_del_init(struct list_head *entry)
{
	__list_del(entry->prev, entry->next);
    INIT_LIST_HEAD(entry);
}

//使用new替换链表中的old
static inline void list_replace(struct list_head *old, struct list_head *new)
{
	new->next = old->next;
	new->next->prev = new;
	new->prev = old->prev;
	new->prev->next = new;
}

//使用new替换链表中的old并且把old初始化,如果old是链表头则相当于清空链表
static inline void list_replace_init(struct list_head *old, struct list_head *new)
{
	list_replace(old, new);
	INIT_LIST_HEAD(old);
}

//将list从链表中取出,然后移动到head的之后的位置。如果head是链表头则是移动到链表的第一个位置
static inline void list_move(struct list_head *list, struct list_head *head)
{
	__list_del(list->prev, list->next);
	list_add(list, head);
}

//将list从链表中取出,然后移动到head的最后一个位置。如果head是链表头则是移动到链表的尾部
static inline void list_move_tail(struct list_head *list, struct list_head *head)
{
	__list_del(list->prev, list->next);
	list_add_tail(list, head);
}

//判断链表是否为空
static inline int list_empty(const struct list_head *head)
{
	return head->next == head;
}

//判断链表是否为空。条件更加充足
static inline int list_empty_careful(const struct list_head *head)
{
	struct list_head *next = head->next;
	return (next == head) && (next == head->prev);
}

/*******************************不常用的操作*********************************/

//判断list是否为链表最后一个节点
static inline int list_is_last(const struct list_head *list, const struct list_head *head)
{
	return list->next == head;
}

//判断链表中是否只有一个节点
static inline int list_is_singular(const struct list_head *head)
{
	return !list_empty(head) && (head->next == head->prev);
}

//将一个链表拆分为两条链表的基本操作
static inline void __list_cut_position(struct list_head *list, struct list_head *head, struct list_head *entry)
{
	struct list_head *new_first = entry->next;
	list->next = head->next;
	list->next->prev = list;
	list->prev = entry;
	entry->next = list;
	head->next = new_first;
	new_first->prev = head;
}

/*
将一个链表拆分成两条
*list为拆分后的新链表的头,*head为被拆分链表的头,*entry为拆分位置
拆分后list->next = entry, head->next = entry->next
既是entry后面的节点被加到list的后面,原链表保留entry之前的节点
head->1->2->3->10->20->30,entry->10.拆分后:head->10->20->30, list->1->2->3
*/
static inline void list_cut_position(struct list_head *list, struct list_head *head, struct list_head *entry)
{
	if (list_empty(head))
		return;
	if (list_is_singular(head) &&
		(head->next != entry && head != entry))
		return;
	if (entry == head)
		INIT_LIST_HEAD(list);
	else
		__list_cut_position(list, head, entry);
}

//合并两条聊表的基本操作
static inline void __list_splice(const struct list_head *list, struct list_head *prev, struct list_head *next)
{
	struct list_head *first = list->next;
	struct list_head *last = list->prev;

	first->prev = prev;
	prev->next = first;

	last->next = next;
	next->prev = last;
}

/*
合并两条链表
将list链表加入到head的后面
list->1->2->3,head->10->20->30。合并后:head->1->2->3->10->20->30
*/
static inline void list_splice(const struct list_head *list, struct list_head *head)
{
	if (!list_empty(list))
		__list_splice(list, head, head->next);
}

/*
合并两条链表
将list链表加入到head的后面,list为必须为链表头,合并后将其初始化
list->1->2->3,head->10->20->30。合并后:head->1->2->3->10->20->30
*/
static inline void list_splice_init(struct list_head *list, struct list_head *head)
{
	if (!list_empty(list))
    {
		__list_splice(list, head, head->next);
		INIT_LIST_HEAD(list);
	}
}

/*
合并两条链表
将list链表加入到head的链表尾部
list->1->2->3,head->10->20->30。合并后:head->10->20->30->1->2->3
*/
static inline void list_splice_tail(struct list_head *list, struct list_head *head)
{
	if (!list_empty(list))
		__list_splice(list, head->prev, head);
}

/*
合并两条链表
将list链表加入到head的链表尾部。list必须是头节点,合并后初始化list
list->1->2->3,head->10->20->30。合并后:head->10->20->30->1->2->3
*/
static inline void list_splice_tail_init(struct list_head *list, struct list_head *head)
{
	if (!list_empty(list))
    {
		__list_splice(list, head->prev, head);
		INIT_LIST_HEAD(list);
	}
}
#endif // MYLIST_H_INCLUDED

main.c

#include <stdio.h>
#include <stdlib.h>
#include "myList.h"
#include "memory.h"

#define RETURN_OK 0
#define RETURN_ERROR -1

//结构体的定义需要放在头文件中,此处做了简便处理
typedef struct tag_myList
{
    int data;
    struct list_head stListNode;  //该指针一般放在结构体定义的开头
}myList;

struct list_head g_stListHead;    //全局变量,作为链表的头

//申请一个节点
myList* newNode()
{
    myList *pstTemp = NULL;

    //为节点申请内存
    pstTemp = (myList*)malloc(sizeof(myList));
    if (NULL == pstTemp)
    {
        return NULL;
    }

    INIT_LIST_HEAD(&(pstTemp->stListNode));
    pstTemp->data = 0;

    return pstTemp;
}

int main()
{
    int i;
    struct list_head stTempHead;    //作为拆分或者合并的链表的头节点
    struct list_head *pstEntry = NULL;
    myList* pstTemp = NULL;
    struct list_head *pos = NULL;
    struct list_head *n = NULL;

    //初始化
    INIT_LIST_HEAD(&g_stListHead);
    INIT_LIST_HEAD(&stTempHead);

    for (i = 0; i < 5; i++)
    {
        pstTemp = newNode();
        if (NULL == pstTemp)
        {
            exit(0);    //内存申请失败则退出,简单的处理
        }

        pstTemp->data = i;

        //将节点加入链表头部
        list_add(&pstTemp->stListNode, &g_stListHead);
    }

    for (i = 5; i < 10; i++)
    {
        pstTemp = newNode();
        if (NULL == pstTemp)
        {
            exit(0);    //内存申请失败则退出,简单的处理
        }

        pstTemp->data = i;

        //将节点加入链表尾部
        list_add_tail(&pstTemp->stListNode, &g_stListHead);
    }

    //遍历链表
    list_for_each(pos, &g_stListHead)
    {
        //通过偏移找到结构体开始的位置,list_entry已经将偏移后的指针强制转换为该结构体
        pstTemp = list_entry(pos, myList, stListNode);
        printf("%d\t", pstTemp->data);
        if (0 == pstTemp->data)
        {
            pstEntry = &pstTemp->stListNode;     //将0所在的位置作为拆分或者合并的节点位置
        }
    }

    printf("\n");

    list_cut_position(&stTempHead, &g_stListHead, pstEntry);

    printf("cut node after g_stListHead:");
    list_for_each(pos, &g_stListHead)
    {
        //通过偏移找到结构体开始的位置,list_entry已经将偏移后的指针强制转换为该结构体
        pstTemp = list_entry(pos, myList, stListNode);
        printf("%d\t", pstTemp->data);
    }

    printf("\n");

    printf("cut node after stTempHead:");
    list_for_each(pos, &stTempHead)
    {
        //通过偏移找到结构体开始的位置,list_entry已经将偏移后的指针强制转换为该结构体
        pstTemp = list_entry(pos, myList, stListNode);
        printf("%d\t", pstTemp->data);
    }
    printf("\n");

    list_splice_init(&g_stListHead, &stTempHead);   //list_splice在遍历的时候就会有问题
    printf("splice node after stTempHead:\t");
    list_for_each(pos, &stTempHead)
    {
        //通过偏移找到结构体开始的位置,list_entry已经将偏移后的指针强制转换为该结构体
        pstTemp = list_entry(pos, myList, stListNode);
        printf("%d\t", pstTemp->data);
    }

    printf("\n");
    printf("splice node after g_stListHead:\t");
    list_for_each(pos, &g_stListHead)
    {
        //通过偏移找到结构体开始的位置,list_entry已经将偏移后的指针强制转换为该结构体
        pstTemp = list_entry(pos, myList, stListNode);
        printf("%d\t", pstTemp->data);
    }
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值