`
oldrev
  • 浏览: 229721 次
  • 性别: Icon_minigender_1
  • 来自: 昆明
社区版块
存档分类
最新评论

双向链表模板类

阅读更多
参考 STL 实现的 Quick & Dirty 双向链表模板类,勉强看的过去。参考了 boost 的新概念迭代器,遵循D的命名风格,只实现了几个简单的成员函数。
迭代器使用 i.current属性或i()读取当前指向的元素,使用 i = x; 设置当前指向的元素

update:
添加了 ReverseIterator, rbegin, rend, insert, erase, popBack, popFront
D 的函数模板特化还是有问题(或者我不知道?)

D 代码
  1. // The STL-Like Template Class of Linked List
  2. // Author: Oldrev ( oldrev at gmail dot com)
  3. // License: BSD
  4. import std.stdio;
  5. // 越靠后的功能越多,后面的肯定包括前面的功能
  6. enum Traversal
  7. {
  8. // 支持的操作 ++i i++ *i++
  9. Incrementable,
  10. // ++i, a==b, a!=b
  11. SinglePass, //单遍,中途不能停
  12. // X u, ++i
  13. ForwardTraversal, //单向
  14. // --r, r--
  15. Bidirectional, //双向
  16. // r += n, a+n,n+a r-=n, a-n, b-a; a[n], a[n]=v, a
  17. RandomAccess //几乎就是数组
  18. }
  19. enum ValueAccess
  20. {
  21. Readable, // value = *a
  22. Writable, // *a = value
  23. Swappable, // swap(a, b)
  24. Lvalue
  25. // 返回引用? D没有显式引用,那就不支持吧
  26. }
  27. private void swap_(T)(inout T x, inout T y)
  28. {
  29. T t = x;
  30. x = y;
  31. y = t;
  32. }
  33. // 约定每个迭代器实现里需要有:
  34. // 一个 Traversal 型常量 TraversalCatalog 指示迭代器遍历方式类型
  35. // 一个 ValueAccess 型常量 ValueAccessCatalog 指示迭代器值访问类型
  36. // 这样算法可以通过 D 的 int 模板参数重载算法实现函数
  37. class List(EleType)
  38. {
  39. public alias EleType ValueType;
  40. public alias ValueType* PtrType;
  41. public alias List!(ValueType) SelfType;
  42. private struct Node
  43. {
  44. ValueType data;
  45. Node* prev;
  46. Node* next;
  47. static void join(Node* first, Node* second)
  48. {
  49. assert(first !is null);
  50. assert(second !is null);
  51. first.next = second;
  52. second.prev = first;
  53. }
  54. }
  55. // List 类的迭代器基模板
  56. private template IteratorBase(IterType)
  57. {
  58. public const Traversal TraversalCatalog = Traversal.Bidirectional;
  59. public const ValueAccess ValueAccessCatalog = ValueAccess.Swappable;
  60. private Node* m_node = null;
  61. private Node* node()
  62. {
  63. return m_node;
  64. }
  65. static IterType opCall(IterType i)
  66. {
  67. IterType ret;
  68. ret.m_node = i.m_node;
  69. return ret;
  70. }
  71. private static IterType opCall(Node* p)
  72. {
  73. IterType i;
  74. i.m_node = p;
  75. return i;
  76. }
  77. public ValueType opCall()
  78. {
  79. assert(m_node !is null);
  80. return m_node.data;
  81. }
  82. public PtrType ptr()
  83. {
  84. assert(m_node !is null);
  85. return &(m_node.data);
  86. }
  87. // 没办法,D 不能重载 *ptr
  88. public ValueType current()
  89. {
  90. assert(m_node !is null);
  91. return m_node.data;
  92. }
  93. public void current(ValueType v)
  94. {
  95. assert(m_node !is null);
  96. m_node.data = v;
  97. }
  98. void swap(inout IterType rhs)
  99. {
  100. IterType t = rhs;
  101. rhs = *this;
  102. *this = t;
  103. }
  104. IterType opPostInc() //i++
  105. {
  106. IterType i = *this;
  107. next();
  108. return i;
  109. }
  110. IterType opPostDec() // i--
  111. {
  112. IterType i = *this;
  113. back();
  114. return i;
  115. }
  116. bool opEquals(IterType rhs) // a == b
  117. {
  118. return rhs.m_node == this.m_node;
  119. }
  120. //D 不支持将=重载为两个同类型或可以隐式转换的类型之间的赋值
  121. ValueType opAssign(ValueType rhs) // *a = value
  122. {
  123. m_node.data = rhs;
  124. return m_node.data;
  125. }
  126. IterType opAddAssign(int n)
  127. {
  128. assert(n == 1);
  129. next();
  130. return *this;
  131. }
  132. IterType opSubAssign(int n)
  133. {
  134. assert(n == 1);
  135. back();
  136. return *this;
  137. }
  138. }
  139. public struct Iterator
  140. {
  141. mixin IteratorBase!(Iterator);
  142. public void next()
  143. {
  144. m_node = m_node.next;
  145. }
  146. public void back()
  147. {
  148. m_node = m_node.prev;
  149. }
  150. }
  151. public struct ReverseIterator
  152. {
  153. mixin IteratorBase!(ReverseIterator);
  154. public void next()
  155. {
  156. m_node = m_node.prev;
  157. }
  158. public void back()
  159. {
  160. m_node = m_node.next;
  161. }
  162. }
  163. //data members:
  164. private Node* m_head = null;
  165. private Node* m_tail = null;
  166. private uint m_length = 0;
  167. public this()
  168. {
  169. }
  170. public ~this()
  171. {
  172. clear();
  173. }
  174. public void clear()
  175. {
  176. if(empty)return;
  177. Iterator i = begin;
  178. while((i = erase(i)) != end){}
  179. m_head = null;
  180. m_tail = null;
  181. }
  182. public ValueType front()
  183. {
  184. assert(m_head !is null);
  185. return m_head.data;
  186. }
  187. public ValueType back()
  188. {
  189. assert(m_tail !is null);
  190. return m_tail.data;
  191. }
  192. public Iterator begin()
  193. {
  194. assert(!empty);
  195. return Iterator(m_head);
  196. }
  197. public Iterator end()
  198. {
  199. return Iterator(null);
  200. }
  201. public ReverseIterator rbegin()
  202. {
  203. return ReverseIterator(m_tail);
  204. }
  205. public ReverseIterator rend()
  206. {
  207. return ReverseIterator(null);
  208. }
  209. public bool empty()
  210. {
  211. return m_head == null;
  212. }
  213. public uint length()
  214. {
  215. return m_length;
  216. }
  217. public void pushFront(ValueType val)
  218. {
  219. Node* np = new Node;
  220. np.prev = null;
  221. np.data = val;
  222. if(m_head !is null)
  223. {
  224. m_head.prev = np;
  225. np.next = m_head;
  226. m_head = np;
  227. }
  228. else
  229. {
  230. np.next = null;
  231. m_head = np;
  232. m_tail = np;
  233. }
  234. m_length++;
  235. }
  236. public void pushBack(ValueType val)
  237. {
  238. Node* np = new Node;
  239. np.next = null;
  240. np.data = val;
  241. if(m_tail !is null)
  242. {
  243. m_tail.next = np;
  244. np.prev = m_tail;
  245. m_tail = np;
  246. }
  247. else
  248. {
  249. np.prev = null;
  250. m_head = np;
  251. m_tail = np;
  252. }
  253. m_length++;
  254. }
  255. // 删除第一个元素
  256. public void popFront()
  257. {
  258. assert(!empty);
  259. erase(Iterator(m_head));
  260. }
  261. public void popBack()
  262. {
  263. assert(!empty);
  264. erase(Iterator(m_tail));
  265. }
  266. //迭代器指向被删除的元素之后的下一个元素或 end,
  267. //注意删除之后 where 迭代器就无效鸟
  268. public Iterator erase(Iterator where)
  269. {
  270. assert(!empty);
  271. Node* i = where.m_node.next;
  272. Node* n = where.m_node;
  273. if(n.prev !is null) n.prev.next = n.next;
  274. if(n.next !is null) n.next.prev = n.prev;
  275. delete n;
  276. m_length--;
  277. return Iterator(i);
  278. }
  279. public Iterator erase(Iterator first, Iterator last)
  280. {
  281. assert(!empty);
  282. Iterator i = first;
  283. while(i != last) i = erase(i);
  284. return i;
  285. }
  286. //在给定的有效迭代器前面插入,返回新元素位置
  287. public Iterator insert(Iterator where, ValueType val)
  288. {
  289. assert(where.m_node !is null);
  290. Node* newNode = new Node;
  291. Node* oldPrev = where.m_node.prev;
  292. newNode.data = val;
  293. Node.join(newNode, where.m_node);
  294. if(oldPrev !is null)Node.join(oldPrev, newNode);
  295. return Iterator(newNode);
  296. }
  297. //在 where 前面连续插入 count 个相同的元素
  298. public void insert(Iterator where, uint count, ValueType val)
  299. {
  300. Iterator iter = where;
  301. for(uint i = 1; i < count; ++i)
  302. iter = insert(iter, val);
  303. return iter;
  304. }
  305. // 不能重载提领操作符就不能很好地使用,比如:
  306. // const int array[] = [1, 2, 3, 4];
  307. // auto list = List!(int);
  308. // list.pushBack(0);
  309. // list.insert(list.begin, array.ptr, array.ptr + array.length);
  310. // 看来只有专门为数组重载了
  311. // 在 where 前面插入一段元素,要求 InputIterator 定义了 ++i, i.current
  312. public void insertElements ( InputIterator ) // D 的函数模板还是有问题,为什么不能叫 insert
  313. (Iterator where, InputIterator first, InputIterator last)
  314. {
  315. InputIterator i = first;
  316. Iterator pos = where;
  317. while(i != last)
  318. {
  319. pos = insertBack(pos, i());
  320. ++i;
  321. }
  322. }
  323. // 在 where 后面插入,并返回新位置
  324. private Iterator insertBack(Iterator where, ValueType val)
  325. {
  326. Node* oldNext = where.m_node.next;
  327. Node* newNode = new Node;
  328. newNode.data = val;
  329. Node.join(where.m_node, newNode);
  330. if(oldNext !is null) Node.join(newNode, oldNext);
  331. return Iterator(newNode);
  332. }
  333. public void opCatAssign(SelfType rhs)
  334. {
  335. for(Iterator i = rhs.begin; i != rhs.end; ++i)
  336. {
  337. pushBack(i.current);
  338. }
  339. }
  340. public void swap(inout SelfType rhs)
  341. {
  342. assert(rhs !is null);
  343. swap_(rhs.m_tail, m_tail);
  344. swap_(rhs.m_head, m_head);
  345. swap_(rhs.m_length, m_length);
  346. }
  347. }
  348. // 最简单的 STL 算法, find
  349. // D不支持提领,我们只能约定 opCall 读取值,opAssign 设置值
  350. private IterType find(IterType, ValueType)(IterType first, IterType last, ValueType val)
  351. {
  352. IterType i = first;
  353. while(i != last && i() != val) ++i;
  354. return i;
  355. }
  356. void main()
  357. {
  358. alias List!(int) MyList;
  359. auto l = new MyList;
  360. l.pushBack(1);
  361. l.pushBack(2);
  362. l.pushBack(3);
  363. l.pushBack(4);
  364. l.pushBack(5);
  365. for(MyList.Iterator i = l.begin; i != l.end; i++)
  366. {
  367. writefln(i());
  368. }
  369. writefln("\nreversed:");
  370. MyList.Iterator i = l.begin;
  371. i++;
  372. i++;
  373. l.insert(i, 12);
  374. l.erase(i);
  375. for(MyList.ReverseIterator ri = l.rbegin; ri != l.rend; ri++)
  376. {
  377. writefln(ri());
  378. }
  379. }
分享到:
评论
3 楼 oldrev 2007-04-09  
由于GC的使用,链表也完全可以实现copy on write,因此我准备仔细设计之后为它添加一个存储 Policy,让用户可以在编译时决定时候启用 copy on write 特性。
2 楼 oldrev 2007-04-07  
引用
好!

不过Traversal和 ValueAccess 好像没用进去亚。

我把boost里面迭代器部分的PDF全下载了,还真不少,看完再说


Traversal 和 ValueAccess 是给算法重载用的
1 楼 qiezi 2007-04-07  
好!

不过Traversal和  ValueAccess  好像没用进去亚。

我把boost里面迭代器部分的PDF全下载了,还真不少,看完再说

相关推荐

Global site tag (gtag.js) - Google Analytics