1. 序:

本文参考了侯捷的 《STL 源码分析》一书,出于兴趣,自行实现了简单的 list 容器。

学习了 STL 的 list 容器的源代码,确实能够提高写链表代码的能力。其中的 sort 函数,可谓是非常神奇。。。

2. 实现的细节

STL 的 list 容器采用了一个带有尾节点的环状双向链表。 如下图所示:

// Last Update:2014-04-20 18:39:47
/**
* @file my_list.h
* @brief a simple list
* @author shoulinjun@126.com
* @version 0.1.00
* @date 2014-04-18
*/ #ifndef MY_LIST_H
#define MY_LIST_H #include <iostream>
#include <cstddef>
#include <cassert> /**
* list node
*/
template<class T>
struct list_node
{
typedef list_node<T>* pointer;
pointer prev;
pointer next;
T data;
}; /**
* list's iterator
* users can use it to iteratate over this list container
*/
template<class T>
struct list_iterator
{
typedef T value_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef list_iterator iterator; list_iterator(list_node<T> *p = NULL) : node(p) {} reference operator*() { return node->data; }
iterator& operator++(){
node = node->next;
return *this;
}
iterator operator++(int){
iterator tmp = *this;
++*this;
return tmp;
}
iterator& operator--(){
node = node->prev;
return *this;
}
iterator operator--(int){
iterator tmp = *this;
--*this;
return tmp;
}
bool operator==(const iterator &rhs){
return node == rhs.node;
}
bool operator!=(const iterator &rhs){
return node != rhs.node; } list_node<T> *node;
}; /**
* a simple list container
*/
template<class T>
class MyList
{
public:
typedef T value_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef list_iterator<T> iterator;
typedef const list_iterator<T> const_iterator;
typedef T& reference;
typedef const T& const_reference;
typedef list_node<T>* link_type; MyList();
MyList(size_type n, T value = T());
//template<class InputIterator>
//MyList(InputIterator first, InputIterator last); // copy control
MyList(const MyList&);
MyList& operator=(const MyList&);
~MyList(); bool empty() const { return node->next == node;}
difference_type size() const; iterator begin() {return iterator(node->next);}
iterator end() {return iterator(node);}
iterator begin() const {return iterator(node->next);}
iterator end() const {return iterator(node);}
iterator rbegin() {return iterator(node->prev);}
iterator rbegin() const {return iterator(node->prev);} iterator insert(iterator position, const T& x); void swap(MyList& );
void push_back(const T& x);
void pop_back() {
iterator tmp = end();
erase(--tmp);
} void push_front(const T& x);
void pop_front() {erase(begin());} void reverse();
void merge(MyList &);
void sort(); void remove(const T&x);
iterator erase(iterator position);
void clear(); void splice(iterator position, MyList& x) {
if(!x.empty()){
transfer(x.begin(), x.end());
}
} void splice(iterator position, MyList&, iterator i){
iterator j = i;
++ j;
if (position == i || position == j) return;
transfer(position, i, j);
} void splice(iterator position, MyList&, iterator first, iterator last) {
if(first != last){
transfer(position, first, last);
}
} void print();
protected:
list_node<T> *node;
static std::allocator<list_node<T> > alloc; link_type get_node(){
link_type p = alloc.allocate(1);
return p;
} void put_node(link_type p){
alloc.deallocate(p, 1);
} link_type create_node(const T& x){
link_type p = get_node();
new (&p->data) T(x);
return p;
} void destroy_node(link_type p){
(&p->data)->~T();
put_node(p);
} void empty_initialize(){
node = get_node();
node->prev = node;
node->next = node;
} void transfer(iterator position, iterator first, iterator last);
}; template<class T>
std::allocator<list_node<T> > MyList<T>::alloc; template<class T>
MyList<T>::MyList()
{
empty_initialize();
} template<class T>
MyList<T>::MyList(size_type n, T value)
{
empty_initialize();
for(size_type i(0); i!=n; ++i)
insert(begin(), value);
} template<class T>
void MyList<T>::clear()
{
link_type p = node->next;
link_type next(NULL); while(p != node){
next = p->next;
destroy_node(p);
p = next;
}
node->prev = node;
node->next = node;
} template<class T>
MyList<T>::~MyList()
{
clear();
destroy_node(node);
node = NULL;
} //copy control
template<class T>
MyList<T>::MyList(const MyList &rhs)
{
empty_initialize();
for(iterator it = rhs.begin(); it != rhs.end(); ++it)
insert(end(), *it);
} template<class T>
MyList<T>& MyList<T>::operator=(const MyList &rhs)
{
clear();
for(iterator it = rhs.begin(); it != rhs.end(); ++it)
insert(end(), *it);
return *this;
} template<class T>
typename MyList<T>::difference_type MyList<T>::size() const
{
difference_type len(0);
link_type p = node->next;
for(; p != node; p = p->next, ++len);
return len;
} template<class T>
typename MyList<T>::iterator MyList<T>::insert(iterator position, const T& x)
{
link_type new_node = create_node(x); new_node->next = position.node;
new_node->prev = position.node->prev;
position.node->prev->next = new_node;
position.node->prev = new_node; return iterator(new_node);
} template<class T>
inline void MyList<T>::push_back(const T& x)
{
insert(end(), x);
} template<class T>
inline void MyList<T>::push_front(const T& x)
{
insert(begin(), x);
} template<class T>
typename MyList<T>::iterator MyList<T>::erase(iterator position)
{
link_type next_node = link_type(position.node->next);
link_type prev_node = link_type(position.node->prev); prev_node->next = next_node;
next_node->prev = prev_node;
destroy_node(position.node); return iterator(next_node);
} // remove all nodes equal to x
template<class T>
void MyList<T>::remove(const T& x)
{
link_type prev_node(node);
link_type cur(node->next);
link_type next_node(NULL); while(cur != node)
{
if(cur->data == x){
/* delete node */
next_node = cur->next;
prev_node->next = next_node;
next_node->prev = prev_node; destroy_node(cur);
cur = next_node;
}
else{
prev_node = cur;
cur = cur->next;
}
}
} /**
* move [first, last) ahead of position
* an auxillary function
*/
template<class T>
void MyList<T>::transfer(iterator position, iterator first, iterator last)
{
if(position != last)
{
link_type first_node = first.node;
link_type rear_node = last.node->prev; //separate [first, last) from their list
first_node->prev->next = last.node;
last.node->prev = first_node->prev; //add [first, last)
first_node->prev = position.node->prev;
rear_node->next = position.node;
position.node->prev->next = first_node;
position.node->prev = rear_node;
}
} template<class T>
void MyList<T>::swap(MyList &rhs)
{
if(this->node != rhs.node){
link_type tmp = node;
node = rhs.node;
rhs.node = tmp;
}
} template<class T>
void MyList<T>::reverse()
{
/* length == 0 || length == 1*/
if(node->next == node || node->next->next == node)
return;
iterator first = begin(), old(NULL);
++ first;
while(first != end()){
old = first;
++ first;
transfer(begin(), old, first);
}
} template<class T>
void MyList<T>::merge(MyList &x)
{
iterator first1 = this->begin();
iterator last1 = this->end();
iterator first2 = x.begin();
iterator last2 = x.end(); // *this and x are sorted incrementally
while(first1 != last1 && first2 != last2)
{
if(*first2 < *first1) {
iterator next = first2;
transfer(first1, first2, ++next);
first2 = next;
}
else
++first1;
}
if(first2 != last2) {
transfer(end(), first2, last2);
}
assert(x.empty());
} template<class T>
void MyList<T>::print()
{
iterator cur = begin();
while(cur != end())
{
std::cout << *cur << " ";
++ cur;
}
std::cout << std::endl;
} /**
* interesting sort function for list
* std::sort is not fit for list
* which requires random iterator
*/
template<class T>
void MyList<T>::sort()
{
/* length == 0 || length == 1*/
if(node->next == node || node->next->next == node)
return; MyList<T> carry;
MyList<T> counter[64];
int fill = 0;
while(!empty())
{
/* carry get the first node */
carry.splice(carry.begin(), *this, begin()); int i = 0;
while(i < fill && !counter[i].empty())
{
counter[i].merge(carry);
carry.swap(counter[i++]);
}
carry.swap(counter[i]);
if(i == fill) ++fill;
} for(int i=1; i<fill; ++i)
counter[i].merge(counter[i-1]);
swap(counter[fill-1]);
} #endif /*MY_LIST_H*/

动手实现自己的 STL 容器《2》---- list的更多相关文章

  1. 动手实现自己的 STL 容器 《1》---- vector

    本文参考了侯捷的 <STL 源码分析>一书,出于兴趣,自行实现了简单的 vector 容器. 之后会陆续上传 list, deque 等容器的代码,若有错误,欢迎留言指出. vector ...

  2. STL容器

    啦啦啦,今天听啦高年级学长讲的STL容器啦,发现有好多东西还是有必要记载的,毕竟学长是身经百战的,他在参加各种比赛的时候积累的经验可不是一天两天就能学来的,那个可是炒鸡有价值的啊,啊啊啊啊啊 #inc ...

  3. c++ stl容器set成员函数介绍及set集合插入,遍历等用法举例

    c++ stl集合set介绍 c++ stl集合(Set)是一种包含已排序对象的关联容器.set/multiset会根据待定的排序准则,自动将元素排序.两者不同在于前者不允许元素重复,而后者允许. 1 ...

  4. STL容器删除元素的陷阱

    今天看Scott Meyers大师的stl的用法,看到了我前段时间犯的一个错误,发现我写的代码和他提到错误代码几乎一模一样,有关stl容器删除元素的问题,错误的代码如下:std::vector< ...

  5. 【转】c++中Vector等STL容器的自定义排序

    如果要自己定义STL容器的元素类最好满足STL容器对元素的要求    必须要求:     1.Copy构造函数     2.赋值=操作符     3.能够销毁对象的析构函数    另外:     1. ...

  6. GDB打印STL容器内容

    GDB调试不能打印stl容器内容,下载此文件,将之保存为~/.gdbinit就可以使用打印命令了. 打印list用plist命令,打印vector用pvector,依此类推. (gdb) pvecto ...

  7. STL容器迭代器失效分析

    连续内存序列容器(vector, string, deque) 对于连续内存序列STL容器,例如vector,string,deque,删除当前iterator会使得后面所有的iterator都失效, ...

  8. STL容器的适用情况

     转自http://hsw625728.blog.163.com/blog/static/3957072820091116114655254/ ly; mso-default-props:yes; m ...

  9. STL容器的遍历删除

    STL容器的遍历删除 今天在对截包程序的HashTable中加入计时机制时,碰到这个问题.对hash_map中的每个项加入时间后,用查询函数遍历hash_map,以删除掉那些在表存留时间比某个阈值长的 ...

随机推荐

  1. wf(三)

    前言: 到现在我们可以看到,WF4包含一个.xmal 文件的设计器和一个调用活动的runtime.当你创建自己的工作流的时候,你是同时也创建了一个活动, 因为活动是一个继承System.Activit ...

  2. [问题2014A03] 复旦高等代数 I(14级)每周一题(第五教学周)

    [问题2014A03]  设 \(A=(a_{ij})\) 为 \(n\,(n\geq 3)\) 阶方阵,\(A_{ij}\) 为第 \((i,j)\) 元素 \(a_{ij}\) 在 \(|A|\) ...

  3. Open source packages on self-driving car

    Autoware https://github.com/CPFL/Autoware.git Open-source software for urban autonomous driving &quo ...

  4. http知识

    http请求的过程:客户端发起请求,创建端口:http服务器在端口监听客户端请求:http服务器向客户端返回状态和内容. 浏览器搜索自身的DNS缓存-->搜索操作系统自身的DNS缓存(浏览器没有 ...

  5. 使用 InstallShield 制作 Delphi 软件安装包

    软件版本: InstallShield 12 Delphi 5/7 SQL Server 2005 一.配置软件信息 二.软件安装的需求配置 三.安装架构 四.安装需要的文件 软件的安装路径.可执行文 ...

  6. Deep Learning 5_深度学习UFLDL教程:PCA and Whitening_Exercise(斯坦福大学深度学习教程)

    前言 本文是基于Exercise:PCA and Whitening的练习. 理论知识见:UFLDL教程. 实验内容:从10张512*512自然图像中随机选取10000个12*12的图像块(patch ...

  7. Android之源码之模块编译和调试

    Android之源码之模块编译调试 (一) 进行源码模块修改进行编译的调试 1.首先是从git或者svn上拉一套完整的工程下来,然后全编一下,一般这个时间比较长,大概会得2,3个小时左右, 2,编译成 ...

  8. django template

    一.模板基本元素 1.例子程序 1)urls.py中新增部分 from django.conf.urls import patterns, url, include urlpatterns = pat ...

  9. C语言->实验室->指针数组

    一 分析 讨论指针数组要从三个层面来考虑: 1)指针数组本身是什么 2)指针数组作为参数时的表现 3)指针数组作为返回值时的表现 二 指针数组是什么 1)指针数组--指针的集合 数组是若干元素的集合, ...

  10. 计算机上没有找到was服务

    控制面板->程序->打开或关闭windows功能,勾选Microsoft .net framework下的两项.