STL源碼之序列式容器list

前言

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;
  }
};

結語

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章