TBOX中提供了各类列表操做:linux
因为双链和单链的接口使用相似,这里主要就讲解双链的具体使用。git
那什么是内部维护和外部维护呢? 简单地说:github
外部维护:就是链表容器自己不存储元素,不开辟内存空间,仅仅是一个节点头,这样比较节省内存,更加灵活。(尤为是在多个链表间元素迁移的时候,或者多个链表须要统一内存池维护的时候)。性能
内部维护:就是链表容器自己回去开辟一块空间,去单独存储元素内容,这种方式对接口的操做比较简单,可是灵活性和性能不如前一种,若是不须要多个链表维护同一种元素,那么使用这种模式简单操做下,更为稳当。(并且内部元素的存储也是用内存池优化过的)。优化
##list的使用.net
list的使用很简单,接口用起来也很方便,这里给个简单的例子:code
// 建立一个long类型的双链,参数0表示采用默认的自动元素增加大小,也能够手动设置更适合的大小 tb_list_ref_t list = tb_list_init(0, tb_element_long()); if (list) { // 在链表头部插入元素:1,并返回这个新元素的迭代器索引 tb_size_t itor = tb_list_insert_head(list, (tb_pointer_t)1); // 在以前新的元素后面插入一个新元素:2 tb_list_insert_next(list, itor, (tb_pointer_t)2); // 在链表尾部插入元素:3 tb_list_insert_tail(list, (tb_pointer_t)3); // 移除指定的元素 tb_list_remove(list, itor); // 遍历全部链表元素, tb_for_all(tb_long_t, item, list) { // 打印元素值 tb_trace_i("%ld", item); } // 销毁list tb_list_exit(list); }
list_entry因为是外置式的容器,须要在外面本身定义的结构体上进行操做,例如定义:索引
// 链表元素结构体 typedef struct __tb_demo_entry_t { // 外置双链的节点,用于链表维护 tb_list_entry_t entry; // 元素的实际数据 tb_size_t data; }tb_demo_entry_t;
对链表的具体操做以下:接口
// 定义一些静态元素,用于插入链表(实际使用可能须要本身动态建立他们) tb_demo_entry_t entries[12] = { {{0}, 0} , {{0}, 1} , {{0}, 2} , {{0}, 3} , {{0}, 4} , {{0}, 5} , {{0}, 6} , {{0}, 7} , {{0}, 8} , {{0}, 9} , {{0}, 10} , {{0}, 11} }; // 初始化链表,须要指定外置元素的结构体类型,链表的节点名字 tb_list_entry_head_t list; tb_list_entry_init(&list, tb_demo_entry_t, entry, tb_null); // 插入一些元素,注意:全部操做都是在外置结构体中的list_entry节点上操做 tb_list_entry_insert_tail(&list, &entries[5].entry); tb_list_entry_insert_tail(&list, &entries[6].entry); tb_list_entry_insert_tail(&list, &entries[7].entry); tb_list_entry_insert_tail(&list, &entries[8].entry); tb_list_entry_insert_tail(&list, &entries[9].entry); tb_list_entry_insert_head(&list, &entries[4].entry); tb_list_entry_insert_head(&list, &entries[3].entry); tb_list_entry_insert_head(&list, &entries[2].entry); tb_list_entry_insert_head(&list, &entries[1].entry); tb_list_entry_insert_head(&list, &entries[0].entry); // 访问具体某个节点的元素数据 tb_demo_entry_t* entry = (tb_demo_entry_t*)tb_list_entry(&list, &entries[5].entry); tb_trace_i("entry: %lu", entry->data); // 遍历全部元素 tb_trace_i("insert: %lu", tb_list_entry_size(&list)); tb_for_all_if(tb_demo_entry_t*, item0, tb_list_entry_itor(&list), item0) { tb_trace_i("%lu", item0->data); } // 替换头尾的元素 tb_list_entry_replace_head(&list, &entries[10].entry); tb_list_entry_replace_last(&list, &entries[11].entry); // 移除头尾的元素 tb_list_entry_remove_head(&list); tb_list_entry_remove_last(&list); // 移动元素位置,这里吧头尾的元素对调了下 tb_list_entry_ref_t head = tb_list_entry_head(&list); tb_list_entry_moveto_head(&list, tb_list_entry_last(&list)); tb_list_entry_moveto_tail(&list, head); // 退出列表 tb_list_entry_exit(&list);
怎么样,也不是很复杂吧,因为元素的内存都在外面本身维护,因此灵活性提高了很多,而且能够多个链表同时维护,而后共用一个内存池进行优化,效率和内存都能获得最大的提高,这种模式在linux内核里面很常见。内存
若是要作比喻的话,list就是傻瓜式操做,list_entry就是定制化操做。。。