list.monkey2 15 KB

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