list.monkey2 15 KB

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