免费网络  

可自由转载, 转载请保留作者信息 jundai2009@gmail.com 和本初始url;

 

既然准备写一个稍微有点规模的软件, 基本的工具API必不可少.

本篇就说说使用的链表. 高手请跳过

 

首先,为什么不使用现成的库呢?

1. 本来就是兴趣项目,练习编码也是目的之一, 当然, 自己造轮子.

2. 自己实现可操作性强一点.

 

主要copy linux中链表的实现, 同时稍微改造下

1. 简化, 只保留本库必须的部分. 不想搞太多没用的代码, 那样也不便维护.

2. 加入排序函数指针, 换句话说, 使用有序链表

 

几个基本小技巧, 再次申明 高手请跳过:

#define offset_of(type, memb) \
 ((unsigned long)(&((type *)0)->memb))

表示结构type中memb的偏移量, 用于下面list_entry

 

#define list_entry(obj, type, memb) \
 ((type *)(((char *)obj) - offset_of(type, memb)))

 

obj是需要使用链表来管理的用户结构的指针, type是用户结构的定义, memb是用户结构中用于本链表连接的参数.

可以看出, 这样管理链表, 比较容易就可以支持一个结构属于多个链表的场景.

具体可以看看下面的例子,应该能很快明白.

 

部分代码如下:

/* list.h

 * All right reserved, 2010

 * jundai2009@gmail.com

*/

#ifndef LIST_H
#define LIST_H
#define LIST_MAGIC 0x20100408

typedef struct list_head_ {
    struct list_head_ *next;
    struct list_head_ *prev;
} list_head;
/* The stand alone, real list header */
typedef struct list_header_ {
    list_head list; /* must be the first element in this structure */
    int count;
    int list_magic;
}list_header;

#define LIST_SIZE(list)      ((list)->count)

#define list_for_each(head, pos) \
 for (pos = (head)->list.next; pos != &((head)->list); pos = pos->next)
#define offset_of(type, memb) \
 ((unsigned long)(&((type *)0)->memb))

#define list_entry(obj, type, memb) \
 ((type *)(((char *)obj) - offset_of(type, memb)))

typedef int (*list_compare_func_t)(list_head *, list_head *);
#endif

 

/*  list.c

 *  All right reserved, 2010

 * jundai2009@gmail.com

*/

void list_init (list_header *list)
{
    assert(list);
   
    list->list.next = &list->list;
    list->list.prev = &list->list;
    list->count = 0;
    list->list_magic = LIST_MAGIC;
}

/* Insert new_element after prev and before next */
void __list_add(list_head *new_elem, list_head *prev, list_head *next)
{
    assert(new_elem);
    assert(prev);
    assert(next);
   
    next->prev = new_elem;
    new_elem->next = next;
    new_elem->prev = prev;
    prev->next = new_elem;
}

BOOL list_insert(list_header *list, list_head *data, list_compare_func_t func)
{
    list_head *element;
    int compare_result;

    assert(list);
    assert(data);
    assert(list->list_magic == LIST_MAGIC);

    if (func == NULL) {
        /* By default, insert to tail of the list*/
        __list_add(data, list->list.prev, &list->list);
        list->count++;
       
        return TRUE;
    }
   
    list_for_each(list, element) {
        compare_result = (*func)(element, data);
        if (compare_result == 0) {
            /* element already in the list */
            return FALSE;
        } else if (compare_result > 0) {
            break;
        }
    }

    __list_add(data, element->prev, element);
    list->count++;

    return TRUE;
}

 

 

单元测试用例

typedef struct payload_ {
    list_head list;
    int val;
}payload;

 

int payload_sort(list_head *data1, list_head *data2)
{
    payload *real1, *real2;

    real1 = list_entry(data1, payload, list);
    real2 = list_entry(data2, payload, list);

    if ( (real1->val) > (real2->val) ) {
        return 1;
    } else if ((real1->val) < (real2->val) ) {
        return -1;
    }

    return 0;
}

 

int main()
{
    list_head *element;
    list_header root;
    payload real_data1, real_data2;
    payload *real_data;

    real_data1.val = 1;
    real_data2.val = 2;
 
    list_init(&root);
    list_insert(&root, &real_data1.list, payload_sort);

    list_for_each(&root, element) {
        real_data = list_entry(element, payload, list);

    }

}

posted on 2010-08-05 22:36  jundai  阅读(429)  评论(2)    收藏  举报