前言
上两篇博客我记录了迭代器,与数据类型的实现。这两个实现,最后都是为了容器的实现而服务。
容器接口设计
容器接口设计考虑一下几点:
- 能获取第一个元素以及最后一个元素的迭代器。
- 提供迭代器移动的实现。
- 提供插入、删除、查找、排序、尺寸(size)等功能。
- 使用单独的内存配置器(这个单独一篇博文)。
根据以上几点要求代码实现如下:
typedef struct _container container_t;
typedef struct _iterator iterator_t;
struct _container {
iterator_t (*first) (container_t* container);
iterator_t (*last) (container_t * container);
iterator_t (*search) (container_t* container, iterator_t offset, type_value_t find, int (*compare)(type_value_t, type_value_t));
int (*insert) (container_t* container, iterator_t iter, type_value_t data);
int (*remove) (container_t* container, iterator_t iter, type_value_t* rdata);
int (*sort) (container_t* container, int(*compare)(type_value_t, type_value_t));
size_t (*size) (container_t*);
pool_t* pool;
};
接口的说明
- first 返回容器的第一个元素。
- last 返回容器的最后一个元素
- search 搜索
- insert 插入,这里使用使用前置插入。
- remove 移除。
- pool 是一个小型内存池的实现。
- size 返回容器当前的数据大小。
因为使用的迭代器作为容器访问接口。所以我设计的容器还额外需要两个标志节点,我称之为标兵:head与tail,这是容器first的前一个,与last的后一个。这里head与tail只用作标示作用,不能用于存放数据。
- head 与 tail 的实现如下:
#define container_head(container) iterator_prev(container_first(container))
#define container_tail(container) iterator_next(container_last(container))
假设一个容器xx里面装了int类型的数值,有了head与tail的节点,容器的遍历可以使用如下方式,获取容器里面的数值。
for(iterator_t first = container_first(xx);!iterator_equal(first, container_tail(xx); first = iterator_next(first)
{
int value = type_int(iterator_dereference(first));
// do something with value.
}
容器的宏
为了方便操作容器,这里制作的几个相关容器的宏:
// 容器位置
#define container_first(container) (((container_t*)(container))->first((container_t*)(container)))
#define container_last(container) (((container_t*)(container))->last((container_t*)(container)))
#define container_head(container) iterator_prev(container_first(container))
#define container_tail(container) iterator_next(container_last(container))
// 容器搜索
#define container_search(container, offset, find, compare) (((container_t*)(container))->search(((container_t*)(container)), offset, find, compare))
#define container_find(container, find, compare) container_search(container, container_first(container), find, compare)
// 容器插入
#define container_insert(container, iter, data) (((container_t*)(container))->insert(((container_t*)(container)), iter, data))
#define container_insert_find(container, find, data, compare) container_insert(container, container_find(container, find, compare), data)
#define container_insert_first(container, data) container_insert(container, container_first(container), data)
#define container_insert_tail(container, data) container_insert(container, container_tail(container), data)
// 容器移除
#define container_remove(container, iter, rdata) (((container_t*)(container))->remove(((container_t*)(container)), iter, rdata))
#define container_remove_find(container, find, rdata, compare) container_remove(container, container_find(container, find, compare), rdata)
#define container_remove_first(container, rdata) container_remove(container, container_first(container), rdata)
#define container_remove_last(container, rdata) container_remove(container, container_last(container), rdata)
// 容器测试
#define container_has(container, find, compare) (!iterator_is_boundary(container_find(container, find, compare)))
// 容器排序
#define container_sort(container, compare) ((container_t*)(container))->sort((container_t*)(container), compare)
// 容器的内存池
#define container_pool(container) (((container_t*)(container))->pool)
// 两个容器合并。
#define container_merge(container_1, container2) do { \
container_t* c1 = (container_t*)(container_1); \
container_t* c2 = (container_t*)(container_2); \
iterator_t first2 = container_first(c2); \
iterator_t tail2 = container_tail(c2); \
for(; !iterator_equal(first2, tail2); first2 = iterator_next(first2)) { \
type_value_t data = iterator_dereference(first2); \
container_insert_tail(c1, data); \
} \
}while(0)
#define container_size(container) (((container_t*)container)->size((container_t*)container))
下一章,探讨具体如何实现一个容器。
完
《第一篇,数据类型》
《第二篇,迭代器》
《第三篇,容器接口》
《第四篇,vector实现的容器》
《第五篇,list实现的容器》
《第六篇,排序》
项目地址