zoukankan      html  css  js  c++  java
  • linux中链表的使用【转】

    转自:http://blog.csdn.net/finewind/article/details/8074990

     Linux下链表的使用方法跟我们常规的不一样,通常情况下,链表的next指针都指向节点的起始位置,但linux中链表指向的是下一个节点中链表所在的地址,这是一种很好的处理方法,不用每换一种数据结构就处理,这种方法的难点在于从链表地址中推算出原始结构体的地址。
    
       整理后的代码如下:
    
    list.h
    
    [cpp] view plain copy
    
        #ifndef _LIST_H_  
        #define _LIST_H_  
          
        /********************************************************** 
        功能: 计算MEMBER成员在TYPE结构体中的偏移量 
        **********************************************************/  
        #define offsetof(TYPE, MEMBER)  (unsigned long)(&(((TYPE*)0)->MEMBER))  
          
          
        /********************************************************** 
        功能: 计算链表元素的起始地址 
        输入:  
            ptr:    type结构体中的链表指针 
            type:   结构体类型 
            member: 链表成员名称 
        **********************************************************/  
        #define container_of(ptr, type, member) (type *)((char*)(ptr) - offsetof(type, member))  
          
        #define LIST_HEAD_INIT(name)    {&(name), &(name)}  
          
        struct list  
        {  
            struct list *prev, *next;  
        };  
          
        static inline void list_init(struct list *list)  
        {  
            list->next = list;  
            list->prev = list;  
        }  
          
        static inline int list_empty(struct list *list)  
        {  
            return list->next == list;  
        }  
          
        // 将new_link插入到link之前  
        static inline void list_insert(struct list *link, struct list *new_link)  
        {  
            new_link->prev        = link->prev;  
            new_link->next        = link;  
            new_link->prev->next = new_link;  
            new_link->next->prev = new_link;  
        }  
          
        /********************************************************** 
        功能: 将new_link节点附加到list链表中 
        **********************************************************/  
        static inline void list_append(struct list *list, struct list *new_link)  
        {  
            list_insert(list, new_link);  
        }  
          
        /********************************************************** 
            功能: 从链表中移除节点 
        **********************************************************/  
        static inline void list_remove(struct list *link)  
        {  
            link->prev->next = link->next;  
            link->next->prev = link->prev;  
        }  
          
        /********************************************************** 
        获取link节点对应的结构体变量地址 
        link:   链表节点指针 
        type:   结构体类型名 
        member: 结构体成员变量名 
        **********************************************************/  
        #define list_entry(link, type, member)  container_of(link, type, member)  
          
          
        /********************************************************** 
        获取链表头节点对应的结构体变量地址 
        list:   链表头指针 
        type:   结构体类型名 
        member: 结构体成员变量名 
        Note: 
        链表头节点实际为链表头的下一个节点,链表头未使用,相当于哨兵 
        **********************************************************/  
        #define list_head(list, type, member) list_entry((list)->next, type, member)  
          
        /********************************************************** 
        获取链表尾节点对应的结构体变量地址 
        list:   链表头指针 
        type:   结构体类型名 
        member: 结构体成员变量名 
        **********************************************************/  
        #define list_tail(list, type, member) list_entry((list)->prev, type, member)  
          
        /********************************************************** 
        返回链表下一个节点对应的结构体指针 
        elm:    结构体变量指针 
        type:   结构体类型名 
        member: 结构体成员变量名(链表变量名) 
        **********************************************************/  
        #define list_next(elm,type,member) list_entry((elm)->member.next, type, member)  
          
        /********************************************************** 
        遍历链表所有节点对应的结构体 
        pos : 结构体指针 
        type : 结构体类型名 
        list : 链表头指针 
        member : 结构体成员变量名(链表变量名) 
        Note : 链表头未使用,因此遍历结束后,pos指向的不是有效的结构体地址 
        **********************************************************/  
        #define list_for_each_entry(pos, type, list, member)      
        for (pos = list_head(list, type, member);                 
            &pos->member != (list);                                
            pos = list_next(pos, type, member))  
          
          
        /********************************************************** 
        example function 
        **********************************************************/  
        void list_example(void);  
        #endif  
    
    测试代码:
    
    list.cpp
    [cpp] view plain copy
    
        #include "stdafx.h"  
          
          
        #include "list.h"  
        #include <stdlib.h>  
          
        struct list g_list = LIST_HEAD_INIT(g_list);  
          
        struct test  
        {  
            int a;  
            int b;  
            char c;  
            struct list link;  
        };  
          
        void CreateData(int a, int b, char c)  
        {  
            struct test *pdata = (struct test *)malloc(sizeof(struct test));  
            pdata->a = a;  
            pdata->b = b;  
            pdata->c = c;  
            list_append(&g_list, &(pdata->link));  
        }  
          
        void listTest(void)  
        {  
            // 创建节点  
            CreateData(0,0,0);     
            CreateData(10,11,12);  
            CreateData(20,21,22);  
            CreateData(30,31,32);  
            CreateData(40,41,42);  
              
            // 取节点  
            struct list *templist = &g_list;   
            struct test *pdata;  
            pdata = list_entry(templist->next, struct test, link);   
          
            templist = templist->next;  
            pdata = list_entry(templist->next, struct test, link);  
          
            // 遍历1  
            for (templist = g_list.next; templist != &g_list; templist = templist->next)  
                pdata = list_entry(templist, struct test, link);  
          
            // 遍历2  
            //pdata = list_head(&g_list, struct test, link);  
            for (pdata = list_head(&g_list, struct test, link); &(pdata->link) != &g_list; pdata = list_next(pdata, struct test, link))  
            {  
                pdata->a = 1;  
            }  
          
            // 遍历3  
            list_for_each_entry(pdata, struct test, &g_list, link)  
            {  
                pdata->b = 2;      
            }  
              
          
        }  
  • 相关阅读:
    洛谷P1182 数列分段`Section II`
    洛谷P3902 递增
    洛谷P1678-烦恼的高考志愿
    POJ 3263-Tallest Cow
    洛谷P2280 [HNOI2003]激光炸弹
    POJ 1958
    Vijos 1197
    VirtualBox 导入.vdi文件时报“uuid is exists”错误
    解压常用
    cut 命令
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/7130941.html
Copyright © 2011-2022 走看看