STL源码剖析之list
来源:互联网 发布:java webstart 编辑:程序博客网 时间:2024/05/17 06:47
相较于vector的连续线性空间,list就显得复杂的多,它的好处是每次插入或删除一个元素,就配置或释放一个元素空间。
因此,list对于空间的运用有绝对的精准,一点不浪费,且对于任何位置的元素插入或者删除,list永远是常数时间。
与之前接触的一样,list本身和list节点结构是分开设计的。
List节点结构如下:
template <class T>struct __list_node { typedef void* void_pointer; void_pointer next; void_pointer prev; T data;};
很清楚的看出是个双向链表,使得整个list的操作变得相对简单些
1、首先看一下list的迭代器设计
template<class T, class Ref, class Ptr>struct __list_iterator { typedef __list_iterator<T, T&, T*> iterator; typedef __list_iterator<T, const T&, const T*>const_iterator; typedef __list_iterator<T, Ref, Ptr> self; typedef bidirectional_iterator_tag iterator_category; typedef T value_type; typedef Ptr pointer; typedef Ref reference; typedef __list_node<T>* link_type; typedef size_t size_type; typedef ptrdiff_t difference_type;//以上,自定义完一些类型名称后: link_type node; //表明这个迭代器指向的list中的那个节点 //构造函数 __list_iterator(link_type x) : node(x) {} __list_iterator() {} __list_iterator(const iterator& x) :node(x.node) {} bool operator==(const self& x) const { return node == x.node; } bool operator!=(const self& x) const { return node != x.node; } //对迭代器取值操作 reference operator*() const { return (*node).data; }//另一种对成员取值的操作#ifndef__SGI_STL_NO_ARROW_OPERATOR pointer operator->() const { return &(operator*()); }#endif /*__SGI_STL_NO_ARROW_OPERATOR */ //迭代器++,向下移一个节点 self& operator++() { node = (link_type)((*node).next); return *this; } self operator++(int) { self tmp = *this; ++*this; return tmp; } self& operator- -() { node = (link_type)((*node).prev); return *this; } self operator- -(int) { self tmp = *this; --*this; return tmp; }};
2、List的数据结构
List的数据结构跟我们想象的差不多,在此基础上,只要在链表尾部后刻意增加一个空白节点,就可以让整个链表形成环形链表。
图中的node(end)节点,即为一个空白节点。
整个链表实现取头、取尾、判断为空都可以依据这个节点来做出判断,如下:
iterator begin() { return(link_type)((*node).next); } iterator end() { return node; } bool empty() const { return node->next == node; } size_type size() const { size_type result = 0; distance(begin(), end(), result); return result; } //更方便的是,当我们要交换两个list的内容时,我们只需要: void swap(list<T, Alloc>& x) { __STD::swap(node,x.node); }//交换这一个节点就可以了
要注意的是,list的插入操作规范标准是:
插入在…之前
3、list的构造与内存管理
List的内存管理在已有空间配置器的基础上作简单的调用
//配置一个节点的空间 link_type get_node() { returnlist_node_allocator::allocate(); }//释放/归还一个节点的空间 void put_node(link_type p) {list_node_allocator::deallocate(p); } //配置并构造一个节点 link_type create_node(const T& x) { link_type p = get_node(); __STL_TRY { construct(&p->data, x); } __STL_UNWIND(put_node(p)); return p; }//析构并释放一个节点 void destroy_node(link_type p) { destroy(&p->data); put_node(p); } protected: void empty_initialize() { node = get_node(); node->next = node; node->prev = node; } //链表的构造函数之一 list() { empty_initialize(); }
4、接着,看一下list中的几个简单算法:
Transfer:(这是几个算法的基础)
//算法目的在于将 [fast, last)内的元素移到 position 元素之前void transfer(iteratorposition, iterator first, iterator last) { if (position != last) { (*(link_type((*last.node).prev))).next =position.node; (*(link_type((*first.node).prev))).next =last.node; (*(link_type((*position.node).prev))).next= first.node; link_type tmp =link_type((*position.node).prev); (*position.node).prev =(*last.node).prev; (*last.node).prev = (*first.node).prev; (*first.node).prev = tmp; } }
Splice:(调用Transfer的简单操作)
//将链list中的元素全部移到position中,position所在list和x 必须是不同的 void splice(iterator position, list& x) { if (!x.empty()) transfer(position, x.begin(), x.end()); }//将某list中的元素i移到position前面 void splice(iterator position, list&, iterator i) { iterator j = i; ++j; if (position == i || position == j)return; transfer(position, i, j); }//将某list中的【first, last)移到 position 前面 void splice(iterator position, list&, iterator first,iterator last) { if (first != last) transfer(position, first, last); }
以下提供merge()和reverse() 、sort()算法
Merge():
//这个算法不多说,就跟普通的归并一样template <class T,class Alloc>void list<T,Alloc>::merge(list<T, Alloc>& x) { iterator first1 = begin(); iterator last1 = end(); iterator first2 = x.begin(); iterator last2 = x.end(); while (first1 != last1 && first2 != last2) if (*first2 < *first1) { iterator next = first2; transfer(first1, first2, ++next); first2 = next; } else ++first1; if (first2 != last2) transfer(last1, first2, last2);}
Reverse:
template <class T,class Alloc>void list<T,Alloc>::reverse() {//先判断是不是0个或1个节点 if (node->next == node ||link_type(node->next)->next == node)return;//主要思想是利用begin()和transfer()来实现//比如先指向第二个元素,利用transfer移到begin()前面,原先指向第二个元素的迭代器指向第三个,重复直到最后 iterator first = begin(); ++first; while (first != end()) { iterator old = first; ++first; transfer(begin(), old, first); }}
Sort有点看不懂,先放着
0 0
- STL之list源码剖析
- STL 之 list 源码剖析
- STL源码剖析之list
- STL之list源码剖析
- STL源码剖析之序列容器list
- STL源码剖析---list
- STL源码剖析---list
- STL源码剖析---list
- STL源码剖析---list
- STL源码剖析---list
- STL源码剖析----list
- STL源码剖析---list
- 【STL】list源码剖析
- STL源码剖析—list
- STL源码剖析-list transfer()
- 《STL源码剖析》中的List
- STL源码剖析之List容器【2013.11.18】
- STL源码剖析——序列容器之list
- 邢台治疗儿童自闭症好yiyuan
- ubuntu64位安装ARM-linux-gcc
- 邢台治疗儿童自闭症好的yiyuan
- Spring IOC 依赖注入的两种方式XML和注解
- 邢台治疗儿童自闭症的yiyuan
- STL源码剖析之list
- 邢台治疗自闭症最好yiyuan
- Cocoa 框架 For iOS(一) 框架的介绍,Objectivie-C运行时能力的解析等
- Call to undefined function ssh2_connect()
- 邢台治疗自闭症yiyuan哪家好
- ps -aux详细解释
- STOMP协议说明书-1.2版
- 邢台治疗自闭症yiyuan
- spring整合JMS(四)