zoukankan      html  css  js  c++  java
  • 第三十三课 双向循环链表的实现

    头结点不位于链表里面,只是用于定位,和内核链表不同。

     

    将LinuxList.h添加到我们的工程中。

    再添加一个DualCircleList.h文件:

      1 #ifndef DUALCIRCLELIST_H
      2 #define DUALCIRCLELIST_H
      3 
      4 #include "LinuxList.h"
      5 #include "DualLinkList.h"
      6 
      7 namespace DTLib
      8 {
      9 
     10 template < typename T >
     11 class DualCircleList : public DualLinkList<T>
     12 {
     13 protected:
     14     struct Node : public Object
     15     {
     16         list_head head;
     17         T value;
     18     };
     19 
     20     list_head m_header;
     21     list_head* m_current;
     22 
     23     list_head* position(int i) const
     24     {
     25         list_head* ret = const_cast<list_head*>(&m_header); //这里需要进行const_cast转换,否则无法在const函数里面取m_header的地址
     26 
     27         for(int p=0; p<i; p++)
     28         {
     29             ret = ret->next;
     30         }
     31 
     32         return ret;
     33     }
     34 
     35     int mod(int i) const
     36     {
     37         return (this->m_length == 0) ? 0 : (i % this->m_length);;
     38     }
     39 
     40 public:
     41     DualCircleList()
     42     {
     43         this->m_length = 0;
     44         this->m_step = 1;
     45 
     46         m_current = NULL;
     47 
     48         INIT_LIST_HEAD(&m_header);
     49     }
     50 
     51     bool insert(const T& e)
     52     {
     53         return insert(this->m_length, e);
     54     }
     55 
     56     bool insert(int i, const T& e)
     57     {
     58         bool ret = true;
     59         Node* node = new Node();
     60 
     61         i = i % (this->m_length + 1);
     62 
     63         if(node != NULL)
     64         {
     65             node->value = e;
     66 
     67             list_add_tail(&node->head, position(i)->next);
     68 
     69             this->m_length++;
     70         }
     71         else
     72         {
     73             THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create Node object ...");
     74         }
     75 
     76         return ret;
     77     }
     78 
     79     bool remove(int i)
     80     {
     81         bool ret = true;
     82 
     83         i = mod(i);
     84 
     85         ret = ((0 <= i) &&(i<this->m_length));
     86 
     87         if( ret )
     88         {
     89             list_head* toDel = position(i)->next;
     90 
     91             if( m_current == toDel )
     92             {
     93                 m_current = toDel->next;
     94             }
     95 
     96             list_del(toDel);
     97 
     98             this->m_length--;
     99 
    100             delete list_entry(toDel, Node, head);
    101         }
    102 
    103         return ret;
    104     }
    105 
    106     bool set(int i, const T& e)   //  O(n)
    107     {
    108         bool ret = true;
    109         i = mod(i);
    110         ret = ((0 <= i) && (i < this->m_length));
    111 
    112         if( ret )
    113         {
    114             list_entry(position(i)->next, Node, head)->value = e;
    115         }
    116 
    117         return ret;
    118     }
    119 
    120     virtual T get(int i) const   // O(n)
    121     {
    122         T ret;
    123 
    124         if( get(i, ret) )
    125         {
    126             return ret;
    127         }
    128         else
    129         {
    130             THROW_EXCEPTION(IndexOutOfBoundsException, "Invalid parameter i to get element ...");
    131         }
    132 
    133         return ret;
    134     }
    135 
    136     bool get(int i, T& e) const    // O(n)
    137     {
    138         bool ret = true;
    139 
    140         i = mod(i);
    141 
    142         ret = ((0 <= i) && (i < this->m_length));
    143 
    144         if( ret )
    145         {
    146             e = list_entry(position(i)->next, Node, head)->value;
    147         }
    148 
    149         return ret;
    150     }
    151 
    152     int find(const T& e) const
    153     {
    154         int ret = -1;
    155 
    156         int i = 0;
    157 
    158         list_head* slider = NULL;
    159 
    160         list_for_each(slider, &m_header)
    161         {
    162             if( list_entry(slider, Node, head )->value == e)
    163             {
    164                 ret = i;
    165                 break;
    166             }
    167 
    168             i++;
    169         }
    170 
    171         return ret;
    172     }
    173 
    174     int length() const
    175     {
    176         return this->m_length;
    177     }
    178 
    179     void clear()
    180     {
    181         while( this->m_length > 0 )
    182         {
    183             remove(0);
    184         }
    185     }
    186 
    187     bool move(int i, int step = 1)
    188     {
    189         bool ret = (step > 0);
    190 
    191         i = mod(i);
    192 
    193         ret = ret && ((0 <= i) && (i < this->m_length));
    194 
    195         if( ret )
    196         {
    197             m_current = position(i)->next;
    198 
    199             this->m_step = step;
    200         }
    201 
    202         return ret;
    203     }
    204 
    205     bool end()
    206     {
    207         return (m_current == NULL) || (this->m_length == 0);
    208     }
    209 
    210     T current()
    211     {
    212         if( !end() )
    213         {
    214             return list_entry(m_current, Node, head)->value;
    215         }
    216         else
    217         {
    218             THROW_EXCEPTION(InvalidOperationException, "No value at current position ...");
    219         }
    220     }
    221 
    222     bool next()
    223     {
    224         int i = 0;
    225 
    226         while((i < this->m_step) && !end())
    227         {
    228             if( m_current != &m_header )
    229             {
    230                 m_current = m_current->next;
    231                 i++;
    232             }
    233             else
    234             {
    235                 m_current = m_current->next;
    236             }
    237         }
    238 
    239         if( m_current == &m_header )
    240         {
    241             m_current = m_current->next;
    242         }
    243 
    244         return (i == this->m_step);
    245     }
    246 
    247     bool pre()
    248     {
    249         int i = 0;
    250 
    251         while((i < this->m_step) && !end())
    252         {
    253             if( m_current != &m_header )
    254             {
    255                 m_current = m_current->prev;
    256                 i++;
    257             }
    258             else
    259             {
    260                 m_current = m_current->prev;
    261             }
    262         }
    263 
    264         if( m_current == &m_header )
    265         {
    266             m_current = m_current->prev;
    267         }
    268 
    269         return (i == this->m_step);
    270     }
    271 
    272     ~DualCircleList()
    273     {
    274         clear();
    275     }
    276 };
    277 
    278 }
    279 
    280 #endif // DUALCIRCLELIST_H

     我们的实现中,头结点只为了做定位用,不属于链表中的一个元素,因此,next和pre函数要跳过头结点。

    单向循环链表CircleList是继承的LinkList的next函数,只向一个方向移动,而且不会越过头结点。

    测试程序如下:

     1 #include <iostream>
     2 #include "DualCircleList.h"
     3 
     4 using namespace std;
     5 using namespace DTLib;
     6 
     7 
     8 int main()
     9 {
    10     DualCircleList<int> dl;
    11 
    12     for(int i = 0; i < 5; i++)
    13     {
    14         dl.insert(0, i);
    15         dl.insert(0, 5);
    16     }
    17 
    18     cout << "begin" << endl;
    19 
    20     dl.move(dl.length() - 1);
    21 
    22     while(dl.find(5) != -1)   //所有的5全部被删除后停止循环
    23     {
    24         if( dl.current() == 5 )
    25         {
    26             cout << dl.current() << endl;
    27 
    28             dl.remove(dl.find(dl.current()));
    29         }
    30         else
    31         {
    32             dl.pre();
    33         }
    34     }
    35 
    36     cout << "end" << endl;
    37 
    38     for(int i = 0; i < dl.length(); i++)
    39     {
    40         cout << dl.get(i) << endl;
    41     }
    42 
    43     return 0;
    44 }

    运行结果如下:

    使用以下程序访问会得到死循环:

     因为当前是一个双向循环链表。

    小结:

    思考题:

  • 相关阅读:
    数据库的视图概念作用
    常见的反爬虫和应对方法
    referrer policy
    JSON
    异步消息处理机制
    Acitivity(活动)
    springboot @Autowired 空指针异常问题处理
    CentOS7 宝塔 ThinkPHP SQLServer 2000 安装FreeTDS
    PHP THINKPHP 函数 dump var_dump var_export
    ThinkPHP5 WHERE AND OR 实现多条件查询
  • 原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9656853.html
Copyright © 2011-2022 走看看