菜鸟笔记
提升您的技术认知

自己动手实现list容器-ag真人游戏

1. 序:

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

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

2. 实现的细节

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

/**
 * @file my_list.h
 * @brief a simple list
 */
#ifndef my_list_h
#define my_list_h
#include 
#include 
#include 
/**
 * list node
 */
template
struct list_node
{
  typedef list_node* pointer;
  pointer prev;
  pointer next;
  t data;
};
/**
 * list's iterator
 * users can use it to iteratate over this list container
 */
template
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 *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 *node;
};
/**
 * a simple list container
 */
template
class mylist
{
public:
  typedef t value_type;
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;
  typedef list_iterator iterator;
  typedef const list_iterator const_iterator;
  typedef t& reference;
  typedef const t& const_reference;
  typedef list_node* link_type;
  mylist();
  mylist(size_type n, t value = t());
  //template
  //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 *node;
  static std::allocator > 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
std::allocator > mylist::alloc;
template
mylist::mylist()
{
  empty_initialize();
}
template
mylist::mylist(size_type n, t value)
{
  empty_initialize();
  for(size_type i(0); i!=n;   i)
    insert(begin(), value);
}
template
void mylist::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
mylist::~mylist()
{
  clear();
  destroy_node(node);
  node = null;
}
//copy control
template
mylist::mylist(const mylist &rhs)
{
  empty_initialize();
  for(iterator it = rhs.begin(); it != rhs.end();   it)
    insert(end(), *it);
}
template
mylist& mylist::operator=(const mylist &rhs)
{
  clear();
  for(iterator it = rhs.begin(); it != rhs.end();   it)
    insert(end(), *it);
  return *this;
}
template
typename mylist::difference_type mylist::size() const
{
  difference_type len(0);
  link_type p = node->next;
  for(; p != node; p = p->next,   len);
  return len;
}
template
typename mylist::iterator mylist::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
inline void mylist::push_back(const t& x)
{
  insert(end(), x);
}
template
inline void mylist::push_front(const t& x)
{
  insert(begin(), x);
}
template
typename mylist::iterator mylist::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
void mylist::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
void mylist::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
void mylist::swap(mylist &rhs)
{
  if(this->node != rhs.node){
    link_type tmp = node; 
    node = rhs.node;
    rhs.node = tmp;
  }
}
template
void mylist::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
void mylist::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
void mylist::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
void mylist::sort()
{ 
  /* length == 0 || length == 1*/
  if(node->next == node || node->next->next == node)
    return;
  mylist carry;
  mylist 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

自己动手实现vector容器

网站地图