• [C++11][数据结构]自己的双链表实现


    这个双链表,是我模仿stl的list制作的,只实现了一些基本功能,像merge,transfer这些就没有实现,用户可以用基本操作来自己做外部实现。

    我没有选用stl的[begin,end)迭代器模式,而是使用传统的[head,tail]。不过,为了配合stl算法,我还是加了两个begin(),end()方法,模拟了一下stl容器。模拟的还算及格,至少我可以做类似for (; begin != end; ++begin)这样的事,也可以让我的容器搭配一些stl算法,这在之后的demo里可以看到。不过,我的iterator很朴素,所以不能用于std::sort。

    至于模拟的实现,我的方法是让所有越界的迭代器都指向一个预先设定好的内存地址。然后用户调用end()方法的时候,就返回指向这个内存地址的迭代器。这样,当我的迭代器越界的时候,就和end()指向的内存地址一样了。

    代码采用C++11实现,在Win7 Mingw32 Gcc4.7的环境下,demo运行正常。如果发现写的不对的地方,还请回复一下。

    以下是类的实现:

      1 #pragma once
      2 
      3 #include <cstddef>
      4 #include <stdexcept>
      5 
      6 namespace jt {
      7 
      8 template <class value_t>
      9 class list {
     10   friend class list<value_t>;
     11 
     12 private:
     13   struct node {
     14     value_t val;
     15     node *next, *prev;
     16   } *_head = nullptr,
     17     *_tail = nullptr;
     18 
     19   size_t _siz;
     20 
     21   enum { endpointer = 1 };
     22 
     23 public:
     24   class iterator {
     25     friend class iterator;
     26     friend class list<value_t>;
     27 
     28   public:
     29     iterator(node *nn = nullptr) { _init(nn); }
     30     iterator(const iterator &i)  { _init(i.n); }
     31 
     32     value_t& operator*() const { return n->val; }
     33     value_t* operator->() const { return &(operator*()); }
     34     iterator operator++() { _inc(); return *this; }
     35     iterator operator++(int) { iterator tmp = *this; _inc(); return tmp; }
     36     iterator operator--() { _dec(); return *this; }
     37     iterator operator--(int) { iterator tmp = *this; _dec(); return tmp; }
     38     bool operator==(iterator& i) const { return i.n == n; }
     39     bool operator!=(iterator& i) const { return i.n != n; }
     40 
     41   private:
     42     node *n;
     43 
     44     void _init(node *nn) {
     45       if (nn) {
     46         n = nn;
     47       } else {
     48         n = (node*)endpointer;
     49       }
     50     }
     51 
     52     void _inc() { n = (n->next) ? n->next : (node*)endpointer; } // increment
     53     void _dec() { n = (n->prev) ? n->prev : (node*)endpointer; } // decrement
     54   };
     55 
     56   list() { clear(); }
     57   list(const list<value_t> &l) { if (&l != this) _init(l.begin(), l.end()); }
     58   ~list() { clear(); }
     59 
     60   bool empty() const { return !_head; }
     61 
     62   void clear() {
     63     if (!empty()) {
     64       node *tmp;
     65       for (node *n = _head; n; n = tmp) {
     66         tmp = n->next;
     67         delete n;
     68       }
     69 
     70       _head = nullptr;
     71       _tail = nullptr;
     72       _siz = 0;
     73     }
     74   }
     75 
     76   void insert(const iterator &pos, const value_t &val) {
     77     if (pos.n == _head) {
     78       push_front(val);
     79     } else {
     80       node *n = new node;
     81       n->val = val;
     82       n->next = pos.n;
     83       n->prev = pos.n->prev;
     84 
     85       pos.n->prev->next = pos.n->prev = n;
     86       ++_siz;
     87     }
     88   }
     89 
     90   void erase(const iterator &pos) {
     91     if (pos.n == _head) {
     92       pop_front();
     93     } else if (pos.n == _tail) {
     94       pop_back();
     95     } else {
     96       pos.n->prev->next = pos.n->next;
     97       pos.n->next->prev = pos.n->prev;
     98       delete pos.n;
     99       --_siz;
    100     }
    101   }
    102 
    103   iterator head() const { return iterator(_head); }
    104   iterator tail() const { return iterator(_tail); }
    105 
    106   iterator begin() const { return iterator(_head); }
    107   iterator end() const { return iterator((node*)endpointer); }
    108 
    109   void push_front(const value_t &val) {
    110     node *n = new node;
    111     n->val = val;
    112     n->next = _head;
    113     n->prev = nullptr;
    114 
    115     if (empty()) _tail = n;
    116     else _head->prev = n;
    117     _head = n;
    118 
    119     ++_siz;
    120   }
    121 
    122   void push_back(const value_t &val) {
    123     node *n = new node;
    124     n->val = val;
    125     n->next = nullptr;
    126     n->prev = _tail;
    127 
    128     if (empty()) _head = n;
    129     else _tail->next = n;
    130     _tail = n;
    131 
    132     ++_siz;
    133   }
    134 
    135   void pop_front() {
    136     if (_siz == 0) {
    137       throw std::logic_error("Empty List");
    138     } else if (_siz == 1) {
    139       clear();
    140     } else {
    141       node *tmp = _head->next;
    142       delete _head;
    143       _head = tmp;
    144       _head->prev = nullptr;
    145     }
    146 
    147     --_siz;
    148   }
    149 
    150   void pop_back() {
    151     if (_siz == 0) {
    152       throw std::logic_error("Empty List");
    153     } else if (_siz == 1) {
    154       clear();
    155     } else {
    156       node *tmp = _tail->prev;
    157       delete _tail;
    158       _tail = tmp;
    159       _tail->next = nullptr;
    160     }
    161 
    162     --_siz;
    163   }
    164 
    165   value_t front() const { return *head(); }
    166   value_t back()  const { return *tail(); }
    167 
    168   size_t size() const { return _siz; }
    169 
    170 private:
    171   template <class iter>
    172   void _init(iter head, iter tail) {
    173     clear();
    174 
    175     // copy
    176     if (head && tail) {
    177       for (; head != tail; ++head) {
    178         push_back(*head);
    179       }
    180       push_back(*tail);
    181     }
    182   }
    183 };
    184 
    185 }

    我没有做测试,而是直接做了一个demo。

    这个demo是一个正整数的统计计算器。可以插入,删除,求和,求平均数,等等。

    以下是demo的代码,同样是C++11:

     1 #include "list.h"
     2 #include <iostream>
     3 #include <string>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <numeric>
     7 #include <algorithm>
     8 #include <map>
     9 #include <functional>
    10 
    11 int main() {
    12   jt::list<unsigned> cont;
    13   std::string buf;
    14   std::string helpmsg =
    15     "h for HELP\n"
    16     "s for SUM\n"
    17     "a for AVERAGE\n"
    18     "z for SIZE\n"
    19     "i,n,p for INSERT n AT p\n"
    20     "e,n for ERASE AT p\n"
    21     "p,n for PUSH_BACK n\n"
    22     "q for QUIT";
    23 
    24   int n = -1;
    25   int p = -1;
    26 
    27   // create func
    28   std::map<char, std::function<void()>> func;
    29   func['h'] = [&]() { std::cout << helpmsg << std::endl; };
    30   func['s'] = [&]() { std::cout << "sum: " << std::accumulate(cont.begin(), cont.end(), 0) << std::endl; };
    31   func['a'] = [&]() { std::cout << "average: " << double(std::accumulate(cont.begin(), cont.end(), 0)) / cont.size() << std::endl; };
    32   func['z'] = [&]() { std::cout << "size: " << cont.size() << std::endl; };
    33   func['i'] = [&]() {
    34     auto i = cont.begin();
    35     while (--p) ++i;
    36     cont.insert(i, n);
    37   };
    38   func['e'] = [&]() {
    39     auto i = cont.begin();
    40     while (--n) { ++i; }
    41     cont.erase(i);
    42   };
    43   func['p'] = [&]() { cont.push_back(n); };
    44   func['q'] = [](){};
    45 
    46   char *optargs = "hsaziepq";
    47 
    48   while (buf != "q") {
    49     // display
    50     std::cout << "\n[ ";
    51     std::for_each(cont.head(), cont.end(), [&](const unsigned &n) { std::cout << n << " "; });
    52     std::cout << "]" << std::endl;
    53 
    54     // read in args
    55     std::cout << optargs << "> ";
    56     std::cin >> buf;
    57 
    58     if (!strchr(optargs, buf[0])) {
    59       std::cout << "Wrong Argument" << std::endl;
    60     } else {
    61       sscanf(buf.c_str(), "%*c,%d,%d", &n, &p);
    62       func[buf[0]]();
    63     }
    64   }
    65 
    66   return 0;
    67 }

    下面我使用demo的记录,看了可能会比较好理解代码一点:

    [ ]
    hsaziepq> h
    h for HELP
    s for SUM
    a for AVERAGE
    z for SIZE
    i,n,p for INSERT n AT p
    e,n for ERASE AT p
    p,n for PUSH_BACK n
    q for QUIT
    
    [ ]
    hsaziepq> s
    sum: 0
    
    [ ]
    hsaziepq> z
    size: 0
    
    [ ]
    hsaziepq> p,1
    
    [ 1 ]
    hsaziepq> p,5
    
    [ 1 5 ]
    hsaziepq> p,9
    
    [ 1 5 9 ]
    hsaziepq> a
    average: 5
    
    [ 1 5 9 ]
    hsaziepq> s
    sum: 15
    
    [ 1 5 9 ]
    hsaziepq> z
    size: 3
    
    [ 1 5 9 ]
    hsaziepq> i,2,3
    
    [ 1 5 2 9 ]
    hsaziepq> e,3
    
    [ 1 5 9 ]
    hsaziepq> i,3,2
    
    [ 1 3 5 9 ]
    hsaziepq> i,2,2
    
    [ 1 2 3 5 9 ]
    hsaziepq> i,4,4
    
    [ 1 2 3 4 5 9 ]
    hsaziepq> e,6
    
    [ 1 2 3 4 5 ]
    hsaziepq> s
    sum: 15
    
    [ 1 2 3 4 5 ]
    hsaziepq> a
    average: 3
    
    [ 1 2 3 4 5 ]
    hsaziepq> z
    size: 5
    
    [ 1 2 3 4 5 ]
    hsaziepq> q
  • 相关阅读:
    CodeForces 670E Correct Bracket Sequence Editor
    CodeForces 670F Restore a Number
    HDU 5895 Mathematician QSC
    HDU 5880 Family View
    HDU 5886 Tower Defence
    CSS3.16
    CSS页面定制代码+动漫人物设计
    TSP变形(三进制状压)
    三进制状压(涂抹果酱)
    最小点覆盖(König定理)
  • 原文地址:https://www.cnblogs.com/jt2001/p/cpplist20150819.html
Copyright © 2020-2023  润新知