前言
STL中list鏈表即雙向鏈表又是循環鏈表
正文
一, STL源碼之序列式容器list的節點和內置內存申請alloc節點的設計
1, 使用兩個指針 父節點指針和下一個節點的指針
template <class T>
struct __list_node {
typedef void* void_pointer;
void_pointer next;
void_pointer prev;
T data; //數據
};
2, 內置的內存分配器
是鏈表結構 使用需要一個節點的時候就申請內存節點內存大小
template <class T, __DFL_TYPE_PARAM(Alloc,alloc) >
class list {
typedef list<T, Alloc> self;
protected:
typedef void* void_pointer;
typedef __list_node<T> list_node;
typedef simple_alloc<list_node, Alloc> list_node_allocator; //內置內存分配器
link_type get_node() { return list_node_allocator::allocate(); }
void put_node(link_type p) { list_node_allocator::deallocate(p); }
/**
*
* @param __false_type : check is class traits 類型萃取
*/
link_type __create_node(const T& x, __false_type) {
link_type p = get_node();
# ifdef __STL_USE_EXCEPTIONS
try {
# endif /* __STL_USE_EXCEPTIONS */
construct(&p->data, x);
// return p;
# ifdef __STL_USE_EXCEPTIONS
}
catch(...) {
put_node(p);
throw;
}
# endif /* __STL_USE_EXCEPTIONS */
return p;
}
link_type __create_node(const T& x, __true_type) {
link_type p = get_node();
/**
// int , char , long 類型是 這邊爲也調用 construct函數 構造函數呢!!!!!!! 調用 new 賦值
int * ptr = (int*)malloc(sizeof(int));
new(ptr) int(5);
if (ptr)
{
printf("ptr = %d\n", *ptr);
}
*/
construct(&p->data, x);
return p;
}
link_type create_node(const T& x) {
typedef typename __type_traits<value_type>::is_POD_type is_POD_type;
return __create_node(x, is_POD_type());
}
void destroy_node(link_type p) {
destroy(&p->data);
put_node(p);
}
...
}
二, 雙向鏈表和循環鏈表
在鏈表初始化 循環鏈表了
void empty_initialize() {
node = get_node();
node->next = node; // 頭節點的下一個節點指針和上一個指針都指向自己了 就是一個循環鏈表結構哈
node->prev = node;
__stl_debug_do(iter_list.safe_init(node));
}
void fill_initialize(size_type n, const T& value) {
empty_initialize();
# ifdef __STL_USE_EXCEPTIONS
try {
# endif /* __STL_USE_EXCEPTIONS */
insert(begin(), n, value);
# ifdef __STL_USE_EXCEPTIONS
}
catch(...) {
clear();
put_node(node);
throw;
}
# endif /* __STL_USE_EXCEPTIONS */
}
explicit list(size_type n) { fill_initialize(n, T()); }
三, 插入和合並
插入的算法
/**
*指定位置的迭代器插入一個數據的節點 的操作
* 1. 創建節點
* 2. 第一步: 創建的新的節點下一個節點指針和父節點的指針改成position節點指針的指向(新的節點下一個節點的指針指向position迭代器的節點, 新的節點的父節點指向 position上一個節點的指針)
* 3. 第二步: 改position節點父節點的數據指針下一個節點的指針的指向 , 指向新的節點
* 4. 第三步: 改position節點父節點指針的指向, 指向新的節點
*
* [修改自己prev和next指針的指向, 二: 修改上一個節點的數據的下一個數據 ]
*
*
*/
iterator insert(iterator position, const T& x) {
__stl_debug_check(__check_if_owner(&iter_list,position));
link_type tmp = create_node(x);
tmp->next = position.node;
tmp->prev = position.node->prev;
(link_type(position.node->prev))->next = tmp;
position.node->prev = tmp;
# if defined ( __STL_DEBUG )
return iterator(&iter_list,tmp);
# else
return tmp;
# endif
}
}
有一個重要的算法 transfer是工具
/**
* 將[first, last) 轉移到position前面
*
*
* @param position
* @param first
* @param last
*/
void transfer(iterator position, iterator first, iterator last)
{
if (position.node != last.node)
{
(*(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;
}
}
/**
* 鏈表必須是有序的纔可以去重
*/
template <class T, class Alloc>
void list<T, Alloc>::unique() {
iterator first = begin();
iterator last = end();
if (first == last) return;
iterator next = first;
while (++next != last) {
if (*first == *next)
erase(next);
else
first = next;
next = first;
}
}
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();
// 需要合併的list是有序的
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);
}
__stl_debug_do(x.invalidate_all());
}
/**
* 鏈表 倒序
* 挺會玩的 始終在鏈表頭插入 鏈表就倒序了
*/
template <class T, class Alloc>
void list<T, Alloc>::reverse() {
if (node->next == node || link_type(node->next)->next == node) return;
iterator first = begin();
++first;
while (first != end())
{
iterator old = first;
++first;
transfer(begin(), old, first);
}
__stl_debug_do(invalidate_all());
}
/**
* 鏈表不支持rand 訪問 所以需要排序
* quick sort
*/
template <class T, class Alloc>
void list<T, Alloc>::sort() {
if (node->next == node || link_type(node->next)->next == node) return;
list<T, Alloc> carry;
list<T, Alloc> counter[64];
int fill = 0;
while (!empty())
{
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]);
__stl_debug_do(invalidate_all());
}
四, list迭代器
在list的迭代器中重要是++和–的操作
template<class T, class Ref, class Ptr>
# if defined ( __STL_DEBUG )
struct __list_iterator : public __safe_base {
# else
struct __list_iterator {
# endif
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;
# if defined ( __STL_DEBUG )
link_type get_iterator() const { return node; }
link_type owner_node() const {
const __safe_base* ptr = owner();
return ptr ? link_type(ptr->owner_) : link_type(0);
}
__list_iterator(const __safe_base* root, link_type x) : __safe_base(root), node(x) {}
__list_iterator() : __safe_base(0) {}
__list_iterator(const iterator& x) : __safe_base(x), node(x.node) {}
# else
__list_iterator(link_type x) : node(x) {}
__list_iterator() {}
__list_iterator(const iterator& x) : node(x.node) {}
# endif
bool operator==(const self& x) const {
__stl_debug_check(__check_same_owner(*this,x));
return node == x.node;
}
bool operator!=(const self& x) const {
__stl_debug_check(__check_same_owner(*this,x));
return node != x.node;
}
reference operator*() const {
__stl_verbose_assert(node!=owner_node(), __STL_MSG_NOT_DEREFERENCEABLE);
return (*node).data;
}
#ifndef __SGI_STL_NO_ARROW_OPERATOR
pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */
self& operator++() {
__stl_verbose_assert(node!=owner_node(), __STL_MSG_INVALID_ADVANCE);
node = (link_type)((*node).next);
return *this;
}
self operator++(int) {
self tmp = *this;
++*this;
return tmp;
}
self& operator--() {
node = (link_type)((*node).prev);
__stl_verbose_assert(node!=owner_node(), __STL_MSG_INVALID_ADVANCE);
return *this;
}
self operator--(int) {
self tmp = *this;
--*this;
return tmp;
}
};