2
0

list.monkey2 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
  1. Namespace std.collections
  2. #rem monkeydoc Convenience type alias for List\<Int\>.
  3. #end
  4. Alias IntList:List<Int>
  5. #rem monkeydoc Convenience type alias for List\<Float\>.
  6. #end
  7. Alias FloatList:List<Float>
  8. #rem monkeydoc Convenience type alias for List\<String\>.
  9. #end
  10. Alias StringList:List<String>
  11. #rem monkeydoc The List class provides support for linked lists.
  12. A linked list is a container style data structure that provides efficient support for the addition, removal and sequential traversal of objects.
  13. A linked list works by connecting elements together with 'next' and 'previous' references, making it very efficient to get from one element to the next, but not so efficient for accessing arbitrary elements.
  14. This connection between elements is achieved using separate Node objects (there is one per element) which contain references to the next and previous nodes in the list, as well as the actual object managed by the node.
  15. Lists implements the [[IContainer]] interface so can be used with [[Eachin]] loops.
  16. #end
  17. Class List<T> Implements IContainer<T>
  18. #rem monkeydoc The List.Node class.
  19. #end
  20. Class Node
  21. Private
  22. Field _succ:Node
  23. Field _pred:Node
  24. Field _value:T
  25. Public
  26. #rem monkeydoc Creates a new node not in any list.
  27. #end
  28. Method New( value:T )
  29. _value=value
  30. _succ=Self
  31. _pred=Self
  32. End
  33. #rem monkeydoc Creates a new node with the given successor node.
  34. Warning! No error checking is performed!
  35. This method should not be used while iterating over the list containing `succ`.
  36. #end
  37. Method New( value:T,succ:Node )
  38. _value=value
  39. _succ=succ
  40. _pred=succ._pred
  41. _pred._succ=Self
  42. succ._pred=Self
  43. End
  44. #rem monkeydoc Gets the node after this node.
  45. #end
  46. Property Succ:Node()
  47. Return _succ
  48. End
  49. #rem monkeydoc Gets the node before this node.
  50. #end
  51. Property Pred:Node()
  52. Return _pred
  53. End
  54. #rem monkeydoc Gets the value contained in this node.
  55. #end
  56. Property Value:T()
  57. Return _value
  58. Setter( value:T )
  59. _value=value
  60. End
  61. #rem monkeydoc Removes this node.
  62. Warning! No error checking is performed!
  63. This method should not be used while iterating over the list containing this node.
  64. #end
  65. Method Remove()
  66. If _succ._pred<>Self Or _pred._succ<>Self Return
  67. _succ._pred=_pred
  68. _pred._succ=_succ
  69. End
  70. #rem monkeydoc Inserts the node before another node.
  71. If the node is already in a list, it is removed before insertion.
  72. This method should not be used while iterating over the list containing this node or `node`.
  73. #end
  74. Method InsertBefore( node:Node )
  75. Remove()
  76. 'insert
  77. _succ=node
  78. _pred=node._pred
  79. _pred._succ=Self
  80. node._pred=Self
  81. End
  82. #rem monkeydoc Inserts the node after another node.
  83. If the node is already in a list, it is removed before insertion.
  84. This method should not be used while iterating over the list containing this node or `node`.
  85. #end
  86. Method InsertAfter( node:Node )
  87. Remove()
  88. 'insert
  89. _pred=node
  90. _succ=node._succ
  91. _succ._pred=Self
  92. node._succ=Self
  93. End
  94. End
  95. #rem monkeydoc The List.Iterator struct.
  96. #end
  97. Struct Iterator
  98. Private
  99. Field _list:List
  100. Field _node:Node
  101. Method AssertCurrent()
  102. DebugAssert( _node<>_list._head,"Invalid list iterator" )
  103. End
  104. Public
  105. #rem monkeydoc Creates a new iterator.
  106. #end
  107. Method New( list:List,node:Node )
  108. _list=list
  109. _node=node
  110. End
  111. #rem monkeydoc Checks whether the iterator has reached the end of the list.
  112. #end
  113. Property AtEnd:Bool()
  114. Return _node=_list._head
  115. End
  116. #rem monkeydoc The value contained in the node pointed to by the iterator.
  117. #end
  118. Property Current:T()
  119. AssertCurrent()
  120. Return _node._value
  121. Setter( current:T )
  122. AssertCurrent()
  123. _node._value=current
  124. End
  125. #rem monkeydoc Bumps the iterator so it points to the next node in the list.
  126. #end
  127. Method Bump()
  128. AssertCurrent()
  129. _node=_node._succ
  130. End
  131. #rem monkeydoc Safely erases the node referenced by the iterator.
  132. After calling this method, the iterator will point to the node after the removed node.
  133. Therefore, if you are manually iterating through a list you should not call [[Bump]] after calling this method or you
  134. will end up skipping a node.
  135. #end
  136. Method Erase()
  137. AssertCurrent()
  138. _node=_node._succ
  139. _node._pred.Remove()
  140. End
  141. #rem monkeydoc Safely insert a value before the iterator.
  142. After calling this method, the iterator will point to the newly added node.
  143. #end
  144. Method Insert( value:T )
  145. _node=New Node( value,_node )
  146. End
  147. End
  148. #rem monkeydoc The List.BackwardsIterator struct.
  149. #end
  150. Struct BackwardsIterator
  151. Private
  152. Field _list:List
  153. Field _node:Node
  154. Method AssertCurrent()
  155. DebugAssert( _node<>_list._head,"Invalid list iterator" )
  156. End
  157. Public
  158. #rem monkeydoc Creates a new iterator.
  159. #end
  160. Method New( list:List,node:Node )
  161. _list=list
  162. _node=node
  163. End
  164. #rem monkeydoc Checks whether the iterator has reached the end of the list.
  165. #end
  166. Property AtEnd:Bool()
  167. Return _node=_list._head
  168. End
  169. #rem monkeydoc The value contained in the node pointed to by the iterator.
  170. #end
  171. Property Current:T()
  172. AssertCurrent()
  173. Return _node._value
  174. Setter( current:T )
  175. AssertCurrent()
  176. _node._value=current
  177. End
  178. #rem monkeydoc Bumps the iterator so it points to the next node in the list.
  179. #end
  180. Method Bump()
  181. AssertCurrent()
  182. _node=_node._pred
  183. End
  184. #rem monkeydoc Safely erases the node referenced by the iterator.
  185. After calling this method, the iterator will point to the node after the removed node.
  186. Therefore, if you are manually iterating through a list you should not call [[Bump]] after calling this method or you
  187. will end up skipping a node.
  188. #end
  189. Method Erase()
  190. AssertCurrent()
  191. _node=_node._pred
  192. _node._succ.Remove()
  193. End
  194. #rem monkeydoc Safely insert a value before the iterator.
  195. After calling this method, the iterator will point to the newly added node.
  196. #end
  197. Method Insert( value:T )
  198. _node=New Node( value,_node._succ )
  199. End
  200. End
  201. Private
  202. Field _head:Node
  203. Public
  204. #rem monkeydoc Creates a new list.
  205. New() create a new empty list.
  206. New( T[] ) creates a new list with the elements of an array.
  207. New( List<T> ) creates a new list with the contents of another list.
  208. New( Stack<T> ) create a new list the contents of a stack.
  209. @param values An existing array, list or stack.
  210. #end
  211. Method New()
  212. _head=New Node( Null )
  213. End
  214. Method New( values:T[] )
  215. Self.New()
  216. AddAll( values )
  217. End
  218. Method New( values:Stack<T> )
  219. Self.New()
  220. AddAll( values )
  221. End
  222. Method New( values:List<T> )
  223. Self.New()
  224. AddAll( values )
  225. End
  226. #rem monkeydoc Gets an iterator for visiting list values.
  227. Returns an iterator suitable for use with [[Eachin]], or for manual iteration.
  228. @return A list iterator.
  229. #end
  230. Method All:Iterator()
  231. Return New Iterator( Self,_head._succ )
  232. End
  233. #rem monkeydoc Gets an iterator for visiting list values in reverse order.
  234. Returns an iterator suitable for use with [[Eachin]], or for manual iteration.
  235. @return A backwards list iterator.
  236. #end
  237. Method Backwards:BackwardsIterator()
  238. Return New BackwardsIterator( Self,_head._pred )
  239. End
  240. #rem monkeydoc Checks whether the list is empty.
  241. @return True if the list is empty.
  242. #end
  243. Property Empty:Bool()
  244. Return _head._succ=_head
  245. End
  246. #rem monkeydoc Counts the number of values in the list.
  247. Note: This method can be slow when used with large lists, as it must visit each value. If you just
  248. want to know whether a list is empty or not, use [[Empty]] instead.
  249. @return The number of values in the list.
  250. #end
  251. Method Count:Int()
  252. Local node:=_head._succ,n:=0
  253. While node<>_head
  254. node=node._succ
  255. n+=1
  256. Wend
  257. Return n
  258. End
  259. #rem monkeydoc Converts the list to an array.
  260. @return An array containing the items in the list.
  261. #end
  262. Method ToArray:T[]()
  263. Local n:=Count()
  264. Local data:=New T[n],node:=_head._succ
  265. For Local i:=0 Until n
  266. data[i]=node._value
  267. node=node._succ
  268. Next
  269. Return data
  270. End
  271. #rem monkeydoc Gets the first value in the list.
  272. In debug builds, a runtime error will occur if the list is empty.
  273. @return The first value in the list.
  274. #end
  275. Property First:T()
  276. DebugAssert( Not Empty )
  277. Return _head._succ._value
  278. End
  279. #rem monkeydoc Gets the last value in the list
  280. In debug builds, a runtime error will occur if the list is empty.
  281. @return The last value in the list.
  282. #end
  283. Property Last:T()
  284. DebugAssert( Not Empty )
  285. Return _head._pred._value
  286. End
  287. #rem monkeydoc Removes all values from the list.
  288. #end
  289. Method Clear()
  290. _head._succ=_head
  291. _head._pred=_head
  292. End
  293. #rem monkeydoc Adds a value to the start of the list.
  294. @param value The value to add to the list.
  295. @return A new node containing the value.
  296. #end
  297. Method AddFirst:Node( value:T )
  298. Local node:=New Node( value,_head._succ )
  299. Return node
  300. End
  301. #rem monkeydoc Adds a value to the end of the list.
  302. @param value The value to add to the list.
  303. @return A new node containing the value.
  304. #end
  305. Method AddLast:Node( value:T )
  306. Local node:=New Node( value,_head )
  307. Return node
  308. End
  309. #rem monkeydoc Removes the first value in the list equal to a given value.
  310. @param value The value to remove.
  311. @return True if a value was removed.
  312. #end
  313. Method Remove:Bool( value:T )
  314. Local node:=FindNode( value )
  315. If Not node Return False
  316. node.Remove()
  317. Return True
  318. End
  319. #rem monkeydoc Removes the last value in the list equal to a given value.
  320. @param value The value to remove.
  321. @return True if a value was removed.
  322. #end
  323. Method RemoveLast:Bool( value:T )
  324. Local node:=FindLastNode( value )
  325. If Not node Return False
  326. node.Remove()
  327. Return True
  328. End
  329. #rem monkeydoc Removes all values in the list equal to a given value.
  330. @param value The value to remove.
  331. @return The number of values removed.
  332. #end
  333. Method RemoveEach:Int( value:T )
  334. Local node:=_head._succ,n:=0
  335. While node<>_head
  336. If node._value=value
  337. node=node._succ
  338. node._pred.Remove()
  339. n+=1
  340. Else
  341. node=node._succ
  342. Endif
  343. Wend
  344. Return n
  345. End
  346. #rem monkeydoc Removes all values in the list that fulfill a condition.
  347. @param cond Condition to test.
  348. @return The number of values removed.
  349. #end
  350. Method RemoveIf:Int( condition:Bool( value:T ) )
  351. Local node:=_head._succ,n:=0
  352. While node<>_head
  353. If condition( node._value )
  354. node=node._succ
  355. node._pred.Remove()
  356. n+=1
  357. Else
  358. node=node._succ
  359. Endif
  360. Wend
  361. Return n
  362. End
  363. #rem monkeydoc Removes and returns the first value in the list.
  364. In debug builds, a runtime error will occur if the list is empty.
  365. @return The value removed from the list.
  366. #end
  367. Method RemoveFirst:T()
  368. DebugAssert( Not Empty )
  369. Local value:=_head._succ._value
  370. _head._succ.Remove()
  371. Return value
  372. End
  373. #rem monkeydoc Removes and returns the last value in the list.
  374. In debug builds, a runtime error will occur if the list is empty.
  375. @return The value removed from the list.
  376. #end
  377. Method RemoveLast:T()
  378. DebugAssert( Not Empty )
  379. Local value:=_head._pred._value
  380. _head._pred.Remove()
  381. Return value
  382. End
  383. #rem monkeydoc Adds a value to the end of the list.
  384. This method behaves identically to AddLast.
  385. @param value The value to add.
  386. #end
  387. Method Add( value:T )
  388. AddLast( value )
  389. End
  390. #rem monkeydoc Adds all values in an array or container to the end of the list.
  391. @param values The values to add.
  392. @param values The values to add.
  393. #end
  394. Method AddAll( values:T[] )
  395. For Local value:=Eachin values
  396. AddLast( value )
  397. Next
  398. End
  399. Method AddAll<C>( values:C ) Where C Implements IContainer<T>
  400. For Local value:=Eachin values
  401. AddLast( value )
  402. Next
  403. End
  404. #rem monkeydoc Sorts the list.
  405. @param ascending True to sort the stack in ascending order, false to sort in descending order.
  406. @param compareFunc Function to be used to compare values when sorting.
  407. #end
  408. Method Sort( ascending:Int=True )
  409. If ascending
  410. Sort( Lambda:Int( x:T,y:T )
  411. Return x<=>y
  412. End )
  413. Else
  414. Sort( Lambda:Int( x:T,y:T )
  415. Return -(x<=>y)
  416. End )
  417. Endif
  418. End
  419. Method Sort( compareFunc:Int( x:T,y:T ) )
  420. Local insize:=1
  421. Repeat
  422. Local merges:=0
  423. Local tail:=_head
  424. Local p:=_head._succ
  425. While p<>_head
  426. merges+=1
  427. Local q:=p._succ,qsize:=insize,psize:=1
  428. While psize<insize And q<>_head
  429. psize+=1
  430. q=q._succ
  431. Wend
  432. Repeat
  433. Local t:Node
  434. If psize And qsize And q<>_head
  435. Local cc:=compareFunc( p._value,q._value )
  436. If cc<=0
  437. t=p
  438. p=p._succ
  439. psize-=1
  440. Else
  441. t=q
  442. q=q._succ
  443. qsize-=1
  444. Endif
  445. Else If psize
  446. t=p
  447. p=p._succ
  448. psize-=1
  449. Else If qsize And q<>_head
  450. t=q
  451. q=q._succ
  452. qsize-=1
  453. Else
  454. Exit
  455. Endif
  456. t._pred=tail
  457. tail._succ=t
  458. tail=t
  459. Forever
  460. p=q
  461. Wend
  462. tail._succ=_head
  463. _head._pred=tail
  464. If merges<=1 Return
  465. insize*=2
  466. Forever
  467. End
  468. #rem monkeydoc Joins the values in the string list.
  469. @param sepeator The separator to be used when joining values.
  470. @return The joined values.
  471. #end
  472. Method Join:String( separator:String="" ) Where T=String
  473. Return separator.Join( ToArray() )
  474. End
  475. #rem monkeydoc Gets the head node of the list.
  476. #end
  477. Method HeadNode:Node()
  478. Return _head
  479. End
  480. #rem monkeydoc Gets the first node in the list.
  481. @return The first node in the list, or null if the list is empty.
  482. #end
  483. Method FirstNode:Node()
  484. If Not Empty Return _head._succ
  485. Return Null
  486. End
  487. #rem monkeydoc Gets the last node in the list.
  488. @return The last node in the list, or null if the list is empty.
  489. #end
  490. Method LastNode:Node()
  491. If Not Empty Return _head._pred
  492. Return Null
  493. End
  494. #rem monkeydoc Finds the first node in the list containing a value.
  495. @param value The value to find.
  496. @return The first node containing the value, or null if the value was not found.
  497. #end
  498. Method FindNode:Node( value:T )
  499. Local node:=_head._succ
  500. While node<>_head
  501. If node._value=value Return node
  502. node=node._succ
  503. Wend
  504. Return Null
  505. End
  506. #rem monkeydoc Finds the last node in the list containing a value.
  507. @param value The value to find.
  508. @return The last node containing the value, or null if the value was not found.
  509. #end
  510. Method FindLastNode:Node( value:T )
  511. Local node:=_head._pred
  512. While node<>_head
  513. If node._value=value Return node
  514. node=node._pred
  515. Wend
  516. Return Null
  517. End
  518. End