# STL之list简要实现

STL 专栏收录该内容
3 篇文章 0 订阅

### （2） 源代码及简要注释

sort性能比较低，对100万条随机数据排序要140秒左右，原版list的sort算法仅要1.4秒

#ifndef TINY_LIST

#include <memory>

namespace tiny_stl
{
//注意：此tiny_list有四种insert版本
//其中
//template <typename Input>
//iterator insert(const iterator& pos, const Input &first, const Input &last)
//和
//iterator insert(const iterator& pos, size_type count, const value_type& value)
//可能会发生重载冲突，如果value_type = int
template <typename T>
struct list_node //将数据封装为结点
{
T *data;
list_node *next;
list_node *prev;

list_node(const T& value): data(new T(value)), next(NULL), prev(NULL) { }
list_node(): data(NULL), next(NULL), prev(NULL) { }
~list_node()
{
delete data;
}
T& operator*() const //重载*，便于取数据
{
return *data;
}
};
template <typename T>
class list_iterator //list专属迭代器
{
private:
using value_type = T;
using self = list_iterator;
public:
list_node<value_type> *node; //所指向的结点
public:
list_iterator(list_node<value_type> *_node): node(_node) { }
public:
self& operator++() //前置自增
{
node = node -> next;
return *this;
}
self operator++(int) //后置自增
{
self tmp = *this;
++*this;
return tmp;
}
self& operator--() //前置自减
{
node = node -> prev;
return *this;
}
self operator--(int)//后置自减
{
self tmp = *this;
--*this;
return tmp;
}
value_type& operator*() const
{
return *(*node);
}
bool operator==(const self &it) const
{
return node == it.node;
}
bool operator!=(const self &it) const
{
return node != it.node;
}
};

template <typename T>
bool less_cmp(const T &a, const T &b) //默认小于比较运算符
{
return a < b;
}
template <typename T>
bool equal_cmp(const T &a, const T &b) //默认等于比较运算符
{
return a == b;
}

template <typename T, typename U = std::allocator<T> >
class tiny_list
{
public:
using value_type = T;
using allocator_type = U;
using size_type = size_t;
using node_type = list_node<value_type>;
private:
node_type *node; //空结点
size_type elem_size; //记录大小
static allocator_type alloc; //内存分配器，虽然没用
using iterator = list_iterator<value_type>;
private:
template <typename Input>
node_type* insert_aux(node_type *pos, const Input &first, const Input &last)
//把first到last之间的所有对象插入到pos之前，使用头插法
{
node_type *first_insert;
Input cur = first;
while(cur != last)
{
node_type* new_node = new node_type(*cur);
pos -> prev -> next = new_node;
new_node -> prev = pos -> prev;
pos -> prev = new_node;
new_node -> next = pos;
if(cur == first)
{
first_insert = new_node; //记录第一个被插入的结点
}
cur++;
elem_size++;

}
return first_insert;
}
void free_space()
{
if(node) //移后源对象的node可能为空，所以需要检查一下
{
clear();
delete node;
node = NULL;
}
}
template <typename Compare>
void insert_sort(node_type *first, node_type *last, Compare comp)
//链表的插入排序，需要指定比较函数,a小于b当且仅当comp(a,b)为真
{
node_type *extern_cur = first -> next;
while(extern_cur != last -> next)
{
value_type *tmp = extern_cur -> data;
node_type *intern_cur = extern_cur -> prev;
while(intern_cur != first -> prev && comp(*tmp, *(*intern_cur)))
{
intern_cur -> next -> data = intern_cur -> data;
intern_cur = intern_cur -> prev;
}
intern_cur -> next -> data = tmp;
extern_cur = extern_cur -> next;
}
}
template <typename Compare>
void quick_sort(node_type *first, node_type *last, size_type count, Compare comp)
//非递归的快速排序
{
struct list_info
{
node_type *first;
node_type *last;
size_type count;
};
tiny_vector<list_info> info_stack; //记录待排序的链表头结点和尾结点，以及长度
info_stack.reserve(count); //提前开辟好空间
value_type *piviot; //每次划分时的依据
size_type left_count; //记录划分后左半部分的长度
do
{
if(!first) //从栈中取出一段待排序的链表
{
list_info tmp = info_stack.back();
info_stack.pop_back();
first = tmp.first;
last = tmp.last;
count = tmp.count;
}

if(count <= 100) //如果待排序的链表长度比较小，则调用插入排序
{
insert_sort(first, last, comp);
first = NULL;
continue;
}

node_type *left = first, *right = last;
//由于随机选取链表中的某个结点是不太方便的，划分依据永远是最左端的结点or最右端的结点
//以count的奇偶性来决定，增加一点随机性
if(count & 1)
{
piviot = left -> data;
}
else
{
piviot = right -> data;
right -> data = left -> data;
left -> data = piviot;
}

left_count = 0;
while(left != right) //根据piviot将链表划分为两部分
{
while(right != left && !comp(**right, *piviot))
{
right = right -> prev;
}
left -> data = right -> data;
left_count++;
while(left != right && comp(**left, *piviot))
{
left = left -> next;
left_count++;
}
right -> data = left -> data;
}
left -> data = piviot;

if(left != last && left -> next != last)
//划分后的右半部分链表还有1个以上的结点，则将这段链表的信息压入栈中
{
info_stack.push_back({left -> next, last, count - left_count});
}
if(left != first && left -> prev != first)
//划分后的左半部分链表还有1个以上的结点，则这段链表作为下一次迭代时的被排序链表
{
last = left -> prev;
count = left_count;
}
else //否则，下一次迭代时从栈中弹出链表，以作为被排序链表
{
first = NULL;
}

}while(!info_stack.empty() || first);
}
public: //五大拷贝控制成员
tiny_list(): node(new node_type), elem_size(0)
{
node->next = node->prev = node;
}
tiny_list(const tiny_list &_lt): tiny_list()
{
insert_aux(node, _lt.begin(), _lt.end());
}
tiny_list& operator=(const tiny_list &_lt)
{
if(this != &_lt)
{
clear();
insert_aux(node, _lt.begin(), _lt.end());
}
return *this;
}
tiny_list(tiny_list &&_lt): node (_lt.node), elem_size(_lt.elem_size) //移动构造，接管资源
{
_lt.node = NULL; //确保移后源对象销毁安全
}
tiny_list& operator=(tiny_list &&_lt)
{
if(this != &_lt)
{
free_space();
node = _lt.node;
elem_size = _lt.elem_size;
_lt.node = NULL;
_lt.elem_size = 0;
}
return *this;
}
~tiny_list()
{
free_space();
}
public: //常用接口
iterator begin() const
{
return iterator(node -> next);
}
iterator end() const
{
return iterator(node);
}
value_type& front() const
{
return *(*(node->next));
}
value_type& back() const
{
return *(*(node->prev));
}
bool empty() const
{
return node -> next == node;
}
size_type size() const
{
return elem_size;
}
void clear()
{
node_type *cur_node = node -> next;
while(cur_node != node)
{
cur_node = cur_node -> next;
delete cur_node -> prev;
}
node->next = node->prev = node;
elem_size = 0;
}
void swap(tiny_list &_lt)
{
if(this != &_lt)
{
std::swap(node, _lt.node);
std::swap(elem_size, _lt.elem_size);
}
}
void resize(size_type n, const value_type &value = value_type())
{
if(n < elem_size)
{
node_type *cur = node -> prev;
while(elem_size > n)
{
cur = cur -> prev;
delete cur -> next;
elem_size--;
}
cur -> next = node;
node -> prev = cur;
}
else if(n > elem_size)
{
insert(node, n - elem_size, value);
}
}
iterator insert(const iterator& pos, size_type count, const value_type &value)
{
node_type *first_insert, *pos_node = pos.node;
for(int i = 0; i < count; ++i)
{
node_type *new_node = new node_type(value);
pos_node -> prev -> next = new_node;
new_node -> prev = pos_node -> prev;
pos_node -> prev = new_node;
new_node -> next = pos_node;
if(!i)
{
first_insert = new_node;
}
}
elem_size += count;
return iterator(first_insert);
}
iterator insert(const iterator& pos, const value_type &value)
{
return insert(pos, size_type(1), value);
}
template <typename Input>
iterator insert(const iterator& pos, const Input &first, const Input &last)
{
return iterator(insert_aux(pos.node, first, last));
}
iterator insert(const iterator &pos, std::initializer_list<value_type> &_ilist)
{
return iterator(insert_aux(pos.node, _ilist.begin(), _ilist.end()));
}
iterator erase(const iterator& first, const iterator& last)
{
node_type *cur = first.node, *last_node = last.node;
node_type *tmp = cur -> prev;
while(cur != last_node)
{
cur = cur -> next;
delete cur -> prev;
elem_size--;
}
tmp -> next = last_node;
last_node -> prev = tmp;
return last;
}
iterator erase(const iterator &pos)
{
return erase(pos, iterator(pos.node -> next));
}
void push_back(const value_type &value)
{
insert(iterator(node), size_type(1), value);
}
void pop_back()
{
if(!elem_size)
{
return;
}
erase(iterator(node -> prev), iterator(node));
}
void push_front(const value_type &value)
{
insert(iterator(node->next), size_type(1), value);
}
void pop_front()
{
if(!elem_size)
{
return;
}
erase(iterator(node -> next), iterator(node -> next -> next));
}
void merge(tiny_list &_lt, bool (*comp)(const value_type&, const value_type&) = less_cmp)
//以升序排列
{
if(this == &_lt) //如果是同一个对象，则不做任何动作
{
return;
}
else if(!elem_size)
{
swap(_lt); //如果本对象无元素，则直接交换两对象即可
}
node_type *p = node -> next, *q = _lt.node -> next;
elem_size += _lt.elem_size;
while(q != _lt.node) //思路是将_lt中的元素一个个插入到本对象中
{
while(p != node && comp(*(p->data), *(q->data)))  //找到正确的位置，在此位置之前插入元素
{
p = p -> next;
}
node_type *q_next = q -> next;
p -> prev -> next = q;
q -> prev = p -> prev;
q -> next = p;
p -> prev = q;
q = q_next;
}
_lt.node -> next = _lt.node -> prev = _lt.node; //对链表q进行收尾工作
}
void splice(const iterator &pos, tiny_list &other, iterator it)
{
auto tmp = it;
splice(pos, other, it, ++tmp);
}
void splice(const iterator &pos, tiny_list &other)
{
splice(pos, other, other.begin(), other.end());
}
void splice(const iterator &pos, tiny_list &other, const iterator &first, const iterator &last)
//将链表other的从first到last之间的所有对象转移到本链表的pos之前
{
if(first == last)
{
return;
}
node_type *first_node = first.node, *last_node = last.node, *pos_node = pos.node;

size_type count = 0;
node_type *cur = first_node; //统计转移的对象数量
while(cur != last_node)
{
cur = cur -> next;
count++;
}

last_node = last_node -> prev; //将尾后结点改成尾结点
first_node -> prev -> next = last_node -> next;
last_node -> next -> prev = first_node -> prev;
other.elem_size -= count;

pos_node -> prev -> next = first_node;
first_node -> prev = pos_node -> prev;
last_node -> next = pos_node;
pos_node -> prev = last_node;
elem_size += count;
}
void reverse() //翻转链表
{
if(!elem_size || elem_size == 1)
{
return;
}
node_type *front = node ,*middle = node -> next, *rear = middle -> next;
do
{
front -> prev = middle;
middle -> next = front;
front = middle;
middle = rear;
rear = rear -> next;
}while(front != node);
}
size_type unique(bool (*comp)(const value_type&, const value_type&) = equal_cmp)
//对于连续出现的元素，将其数量缩减为1
{
if(!elem_size)
{
return 0;
}
node_type *first_appear = node -> next, *cur = first_appear -> next;
size_type count = 0;
while(first_appear != node)
{
if(cur != node && comp(*(*first_appear), *(*cur)))
{
cur = cur -> next;
delete cur->prev;
count++;
}
else
{
cur -> prev = first_appear;
first_appear -> next = cur;
first_appear = cur;
cur = cur -> next;
}
}
elem_size -= count;
return count;
}
void sort(bool (*comp)(const value_type&, const value_type&) = less_cmp)
//对链表排序
{
quick_sort(node -> next, node -> prev, elem_size, comp);
}
};
template <typename T, typename U>
U tiny_list<T, U>::alloc;
}

#endif

• 0
点赞
• 1
评论
• 0
收藏
• 一键三连
• 扫一扫，分享海报

08-24 5239

04-27 200
01-20 1101
04-27 83
06-04 988
06-03 129
01-20 1036
01-05 3638
04-03 310
08-04 1855
05-31 1243
12-27 7562

ForBestSelf

¥2 ¥4 ¥6 ¥10 ¥20

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