容器与迭代器,C实现《第五篇,list实现容器》

前言

上一篇博文记录了使用vector来实现容器,这篇将会介绍使用双向链表list来实现容器。

list

双向链表定义如下:

typedef struct _list_node list_node_t;
struct _list_node
{
    /* 数据节点的data,要放在首段,否则会出现灾难性后果 */
    type_value_t data;
    list_node_t* prev;
    list_node_t* next;
};

typedef struct _list 
{
    container_t container;
    list_node_t _sentinel;
    size_t _size;
} list_t;
  • 列表中节点node,node中的第一个字段必须是type_value_t。否则迭代器器的iterator_dereference宏将会有错误的操作。如果不把type_value_t放在第一个字段,dereference操作会错误把其他字节的内存拷贝出来。
  • 同样,container_t 接口必须放在list结构体的第一个字段。
  • sentinel,标兵。用于head与tail的作用。
list接口实现
  • list的一些宏
#define list_head(list) (&(((list_t*)list)->_sentinel))
#define list_tail(list) (&(((list_t*)list)->_sentinel))
#define list_first(list) (list_head(list)->next)
#define list_last(list)  (list_tail(list)->prev)
  • first
static iterator_t _list_first (container_t* plist)
{
    return _get_iter(list_first(plist), plist);
}
  • last
static iterator_t _list_last (container_t* plist)
{
    return _get_iter(list_last(plist), plist);
}
  • search
static iterator_t _list_search (container_t* container, iterator_t offset, type_value_t find, int(compare)(type_value_t data1, type_value_t data2))
{
    iterator_t first = offset;
    iterator_t tail  = container_tail(container);
    for(;!iterator_equal(first, tail); first = iterator_next(first)) {
        if (compare(iterator_dereference(first), find) == 0) {
            return first;
        }
    }
    // 返回边界的指针
    return first;
}
  • insert
static int _list_insert(container_t* container, iterator_t pos, type_value_t data)
{

    list_node_t *pnode = iterator_reference(pos);
    list_node_t *pnew = allocate(container_pool(container), sizeof(list_node_t));
    // 赋值 和 插入

    pnew->data = data;
    pnew->prev = pnode->prev;
    pnew->next = pnode;

    pnode->prev->next = pnew;
    pnode->prev = pnew;

    list_t *plist = container;
    plist->_size++;
    return 0;
}
  • remove
static int _list_remove(container_t* container, iterator_t pos, type_value_t* rdata)
{
    // 删除
    // 边界的东西不能移除
    if (!iterator_is_boundary(pos)){

        list_t* list = container;
        list_node_t* pnode = iterator_reference(pos);
        
        pnode->prev->next = pnode->next;
        pnode->next->prev = pnode->prev;

        if (rdata) {
            *rdata = iterator_dereference(pos);
        }
        
        // 回收
        deallocate(container_pool(container), pnode);
        list->_size--;
        return 0;
    }
  • size
static size_t _list_size(container_t* container) 
{
    return ((list_t*)container)->_size;
}
  • sort
static int _list_sort(container_t* container, int(*compare)(type_value_t, type_value_t))
{
    return quick_sort(container_first(container), container_last(container), compare);
}
  • 绑定容器接口
void init_list(list_t* list, pool_t* _pool) {
    
    initialize_container(list, _list_first, _list_last, _list_search, _list_insert, _list_remove, _list_sort, _list_size, _pool);
    list_first(list) = list_head(list);
    list_last(list) = list_tail(list);
    list->_size = 0;
    list->_sentinel.data = int_type(-1);      
    return;
}
  • 迭代器接口
static iterator_t _move(iterator_t it, int step)
{
    list_node_t* pnode = iterator_reference(it);
   
    for(int next = step; next; next = step > 0? --step:++step) {
        if (next > 0) pnode = pnode->next;
        else if (next < 0) pnode = pnode->prev;
    }
    return iterator_set_reference(it, pnode);
}

《第一篇,数据类型》
《第二篇,迭代器》
《第三篇,容器接口》
《第四篇,vector实现的容器》
《第五篇,list实现的容器》
《第六篇,排序》
项目地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值