通用链表实现(参考Linux List)

  最近参考Linux实现的通用双向链表时,因typeof并不是标准c规定的关键字,除GCC编译器外其他编译器未必支持typeof关键字,所以在使用上并不能想Linux所实现的链表哪样灵活,它要求将连接器即链表结构作为用户自定义结构体的第一个元素使用,话不多说,直接上代码,内嵌详细注释。

IList.h

  1 #ifndef _I_LIST_H_2012_11_23_
  2 #define _I_LIST_H_2012_11_23_
  3 
  4 #ifdef __cplusplus
  5 extern "C" {
  6 #endif
  7 
  8 /** \brief 双向链表连接器
  9  *  \details 实现用户自定义结构链表的连接器的结构定义,使用注意事项:
 10     1. 务必将其嵌入到用户自定义结构体元素的顶端;
 11     2. 务必使用结构类型而非其指针类型嵌入到用户自定义结构体
 12  *  \typedef typedef struct _IList IList,*pIList
 13  */
 14 typedef struct _IList
 15 {
 16     struct _IList *_prev;
 17     struct _IList *_next;
 18 }IList, *pIList;
 19 
 20 /**
 21   \brief    遍历链表所有节点
 22   \details  遍历链表所有节点,在遍历过程中,请勿执行添加、删除操作
 23 
 24   \param[in]  pList 链表对象
 25   \param[out] pLink 节点
 26  */
 27 #define IList_Foreach(pList, pos) \
 28     for ( \
 29         pos = pos = (pList)->_next; \
 30         pos != (pList); \
 31         pos = pos->_next \
 32     )
 33 
 34 /**
 35   \brief    遍历链表所有节点
 36   \details  安全遍历链表所有节点,在遍历过程中,可以删除节点
 37 
 38   \param[in]  pList 链表对象
 39   \param[out] pLink 节点
 40  */
 41 #define IList_Foreach_Salf(pList, temp, pos) \
 42     for ( \
 43         pos = (pList)->_next, temp = pos->_next; \
 44         pos != (pList); \
 45         pos = temp, temp = pos->_next\
 46     )
 47 
 48 /**
 49   \brief    链表初始化
 50 
 51   \param[in]  pList 链表对象
 52  */
 53 void IList_Init(pIList pList);
 54 
 55 /**
 56   \brief    插入新节点
 57   \details  将新节点插入链表指定节点之前
 58 
 59   \param[in]  pList 链表对象
 60   \param[in]  pLink 指定节点
 61   \param[in]  pNewLink 带插入节点
 62  */
 63 void IList_Insert(pIList pLink, pIList pNewLink);
 64 
 65 /**
 66   \brief    插入新节点至链表尾部
 67 
 68   \param[in]  pList 链表对象
 69   \param[in]  pLink 指定节点
 70   \param[in]  pNewLink 带插入节点
 71  */
 72 void IList_Append(pIList pList, pIList pNewLink);
 73 
 74 /**
 75   \brief    插入新节点至链表尾头部
 76 
 77   \param[in]  pList 链表对象
 78   \param[in]  pLink 指定节点
 79   \param[in]  pNewLink 带插入节点
 80  */
 81 void IList_Prepend(pIList pList, pIList pNewLink);
 82 
 83 /**
 84   \brief    删除指定节点
 85 
 86   \param[in]  pList 链表对象
 87   \param[in]  pLink 带删除的节点
 88  */
 89 void IList_Remove(pIList pLink);
 90 
 91 /**
 92   \brief    获取表头节点
 93 
 94   \param[in]  pList 链表对象
 95 
 96   \return   NULL: 链表为空
 97             其他: 表头节点地址
 98  */
 99 pIList IList_Head(pIList pList);
100 
101 /**
102   \brief    获取表尾节点
103 
104   \param[in]  pList 链表对象
105 
106   \return   NULL: 链表为空
107             其他: 表尾节点地址
108  */
109 pIList IList_Tail(pIList pList);
110 
111 /**
112   \brief    检测链表是否为空
113 
114   \param[in]  pList 链表对象
115 
116   \return   0: 链表非空
117             1: 链表为空
118  */
119 int IList_IsEmpty(pIList pList);
120 /**
121   \brief    获取链表节点数
122 
123   \param[in]  pList 链表对象
124 
125   \return   链表节点数
126  */
127 int IList_Size(pIList pList);
128 
129 /**
130   \brief    获取指定节点的后一节点
131 
132   \param[in]  pList 链表对象
133   \param[in]  pLink 指定的节点
134 
135   \return   NULL: 指定节点为尾节点
136             其他: 指定节点后一节点地址
137  */
138 pIList IList_Next(pIList pList, pIList pLink);
139 
140 /**
141   \brief    获取指定节点的前一节点
142 
143   \param[in]  pList 链表对象
144   \param[in]  pLink 指定的节点
145 
146   \return   NULL: 指定节点为头节点
147             其他: 指定节点前一节点地址
148  */
149 pIList IList_Prev(pIList pList, pIList pLink);
150 
151 /**
152   \brief    获取链表中第index个节点
153 
154   \param[in]  pList 链表对象
155   \param[in]  index 节点序号,从1计数
156 
157   \return   NULL: 指定序号无节点
158             其他: 链表中第index所对应的节点
159  */
160 pIList IList_Nth(pIList pList, int index);
161 
162 /**
163   \brief    获取链表中指定节点的序号
164 
165   \param[in]  pList 链表对象
166   \param[in]  pLink 指定节点
167 
168   \return   NULL: 指定序号无节点
169             其他: 链表中第index所对应的节点
170  */
171 int IList_Find(pIList pList, pIList pLink);
172 
173 #ifdef __cplusplus
174 }
175 #endif
176 
177 #endif//_I_LIST_H_2012_11_23_

IList.c

  1 #include <stdio.h>
  2 #include "iList.h"
  3 
  4 void IList_Init(pIList pList)
  5 {
  6     pList->_prev = pList;
  7     pList->_next = pList;
  8 }
  9 
 10 void IList_Insert(pIList pLink, pIList pNewLink)
 11 {
 12     pNewLink->_prev = pLink->_prev;
 13     pNewLink->_next = pLink;
 14     pNewLink->_prev->_next = pNewLink;
 15     pNewLink->_next->_prev = pNewLink;
 16 }
 17 
 18 void IList_Append(pIList pList, pIList pNewLink)
 19 {
 20     IList_Insert(pList, pNewLink);
 21 }
 22 
 23 void IList_Prepend(pIList pList, pIList pNewLink)
 24 {
 25     IList_Insert(pList->_next, pNewLink);
 26 }
 27 
 28 void IList_Remove(pIList pLink)
 29 {
 30     pLink->_prev->_next = pLink->_next;
 31     pLink->_next->_prev = pLink->_prev;
 32 }
 33 
 34 pIList IList_Head(pIList pList)
 35 {
 36     return pList->_next != pList ? pList->_next : NULL;
 37 }
 38 
 39 pIList IList_Tail(pIList pList)
 40 {
 41     return pList->_prev != pList ? pList->_prev : NULL;
 42 }
 43 
 44 int IList_IsEmpty(pIList pList)
 45 {
 46     return pList->_next == pList;
 47 }
 48 
 49 int IList_Size(pIList pList)
 50 {
 51     int count = 0;
 52     pIList temp = NULL;
 53 
 54     if (pList->_next == pList)
 55         return 0;
 56 
 57     IList_Foreach(pList, temp)
 58     {
 59         count ++;
 60     }
 61 
 62     return count;
 63 }
 64 
 65 pIList IList_Next(pIList pList, pIList pLink)
 66 {
 67     return pLink->_next != pList ? pLink->_next : NULL;
 68 }
 69 
 70 pIList IList_Prev(pIList pList, pIList pLink)
 71 {
 72     return pLink->_prev != pList ? pLink->_prev : NULL;
 73 }
 74 
 75 pIList IList_Nth(pIList pList, int index)
 76 {
 77     pIList pLink = NULL;
 78     int count = 0;
 79 
 80     IList_Foreach(pList, pLink)
 81     {
 82         count ++;
 83         if (count == index)
 84             return pLink;
 85     }
 86 
 87     return NULL;
 88 }
 89 
 90 int IList_Find(pIList pList, pIList pLink)
 91 {
 92     pIList pTemp = NULL;
 93     int index = 1;
 94 
 95     pTemp = IList_Head(pList);
 96 
 97     while ((pTemp != NULL) && (pTemp != pLink))
 98     {
 99         index++;
100         pTemp = IList_Next(pList, pTemp);
101     }
102 
103     if (pTemp == NULL)
104         return (-1);
105     else
106         return (index);
107 }

 IListTest.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "iList.h"

typedef struct _Student
{
    IList _list;

    int _id;
    char *name;
}Student, *pStudent;

int main(int argc, char *argv[])
{
    int i = 0;
    int num = 10;
    int count = 0;
    pStudent temp= NULL;
    pIList list, link;

    if (argc > 1)
        num = atoi(argv[1]);

    list = (IList *)malloc(sizeof(IList));
    if (!list)
    {
        printf("Error in malloc.\n");
        return -1;
    }
    memset(list, 0, sizeof(IList));

    IList_Init(list);
    for (i = 0; i < num; i ++)
    {
        temp = malloc(sizeof(Student));
        if (!temp)
            return -1;
        memset(temp, 0, sizeof(Student));
        temp->_id = i + 1;
        IList_Append(list, &temp->_list);
        //IList_Prepend(list, &temp->_list);
    }

    IList_Foreach(list, link)
    {
        temp = (pStudent)link;
        printf("%d\t", temp->_id);
    }
    printf("\n");

    printf("Input the num(1 ~ %d) that you want to:\n", IList_Size(list));
    scanf("%d", &count);
    link = IList_Nth(list, count);
    printf("Num %d id: %d\n", count, ((pStudent)link)->_id);
    printf("Id %d num: %d\n", ((pStudent)link)->_id, IList_Find(list, link));

    printf("List count: %d\n", IList_Size(list));
    /*for (link = IList_Head(list);!IList_IsEmpty(list);)
    {
        pIList tLink = link;
        link = IList_Next(list, link);
        IList_Remove(tLink);
        free(tLink);
    }*/
    do 
    {
        pIList n, pos;
        IList_Foreach_Salf(list, n, pos)
        {
            IList_Remove(pos);
            free(pos);
        }
    } while (0);
    printf("List count: %d\n", IList_Size(list));

    free(list);

    return 0;
}

 

posted @ 2013-08-13 14:05  ╭爵☆爷╯  阅读(746)  评论(0编辑  收藏  举报