2
0

list.monkey2 15 KB

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