第三十三课 双向循环链表的实现
Posted wanmeishenghuo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第三十三课 双向循环链表的实现相关的知识,希望对你有一定的参考价值。
头结点不位于链表里面,只是用于定位,和内核链表不同。
将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函数要跳过头结点。
测试程序如下:
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 }
运行结果如下:
使用以下程序访问会得到死循环:
因为当前是一个双向循环链表。
小结:
思考题:
以上是关于第三十三课 双向循环链表的实现的主要内容,如果未能解决你的问题,请参考以下文章