stack.monkey2 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  1. Namespace std.collections
  2. #rem monkeydoc Convenience type alias for Stack\<Int\>.
  3. #end
  4. Alias IntStack:Stack<Int>
  5. #rem monkeydoc Convenience type alias for Stack\<Float\>.
  6. #end
  7. Alias FloatStack:Stack<Float>
  8. #rem monkeydoc Convenience type alias for Stack\<String\>.
  9. #end
  10. Alias StringStack:Stack<String>
  11. #rem monkeydoc The Stack class provides suport for dynamic arrays.
  12. A stack is an 'array like' container that grows dynamically as necessary.
  13. It is very cheap to add values to the end of a stack, but insertion or removal of values requires higher indexed values to be 'shifted' up or down so is slower.
  14. Stacks implement the [[IContainer]] interface so can be used with Eachin loops.
  15. #end
  16. Class Stack<T> Implements IContainer<T>
  17. #rem monkeydoc The Stack.Iterator struct.
  18. #end
  19. Struct Iterator 'Implements IIterator<T>
  20. Private
  21. Field _stack:Stack
  22. Field _index:Int
  23. Method AssertCurrent()
  24. DebugAssert( _index<_stack._length,"Invalid stack iterator" )
  25. End
  26. Method New( stack:Stack,index:Int )
  27. _stack=stack
  28. _index=index
  29. End
  30. Public
  31. #rem monkeydoc Checks if the iterator has reached the end of the stack.
  32. #end
  33. Property AtEnd:Bool()
  34. Return _index>=_stack._length
  35. End
  36. #rem monkeydoc The value currently pointed to by the iterator.
  37. #end
  38. Property Current:T()
  39. AssertCurrent()
  40. Return _stack._data[_index]
  41. Setter( current:T )
  42. AssertCurrent()
  43. _stack._data[_index]=current
  44. End
  45. #rem monkeydoc Bumps the iterator so it points to the next value in the stack.
  46. #end
  47. Method Bump()
  48. AssertCurrent()
  49. _index+=1
  50. End
  51. #rem monkeydoc Safely erases the value pointed to by the iterator.
  52. After calling this method, the iterator will point to the value after the removed value.
  53. Therefore, if you are manually iterating through a stack you should not call [[Bump]] after calling this method or you will end up skipping a value.
  54. #end
  55. Method Erase()
  56. AssertCurrent()
  57. _stack.Erase( _index )
  58. End
  59. #rem monkeydoc Safely inserts a value before the value pointed to by the iterator.
  60. After calling this method, the iterator will point to the newly added value.
  61. #end
  62. Method Insert( value:T )
  63. DebugAssert( _index<=_stack._length,"Invalid stack iterator" )
  64. _stack.Insert( _index,value )
  65. End
  66. End
  67. #rem monkeydoc The Stack.BackwardsIterator struct.
  68. #end
  69. Struct BackwardsIterator 'Implements IIterator<T>
  70. Private
  71. Field _stack:Stack
  72. Field _index:Int
  73. Method AssertCurrent()
  74. DebugAssert( _index>=0,"Invalid stack iterator" )
  75. End
  76. Method New( stack:Stack,index:Int )
  77. _stack=stack
  78. _index=index
  79. End
  80. Public
  81. #rem monkeydoc Checks if the iterator has reached the end of the stack.
  82. #end
  83. Property AtEnd:Bool()
  84. Return _index=-1
  85. End
  86. #rem monkeydoc The value currently pointed to by the iterator.
  87. #end
  88. Property Current:T()
  89. AssertCurrent()
  90. Return _stack._data[_index]
  91. Setter( current:T )
  92. AssertCurrent()
  93. _stack._data[_index]=current
  94. End
  95. #rem monkeydoc Bumps the iterator so it points to the next value in the stack.
  96. #end
  97. Method Bump()
  98. AssertCurrent()
  99. _index-=1
  100. End
  101. #rem monkeydoc Safely erases the value pointed to by the iterator.
  102. After calling this method, the iterator will point to the value after the removed value.
  103. Therefore, if you are manually iterating through a stack you should not call [[Bump]] after calling this method or you
  104. will end up skipping a value.
  105. #end
  106. Method Erase()
  107. AssertCurrent()
  108. _stack.Erase( _index )
  109. _index-=1
  110. End
  111. #rem monkeydoc Safely inserts a value before the value pointed to by the iterator.
  112. After calling this method, the iterator will point to the newly added value.
  113. #end
  114. Method Insert( value:T )
  115. DebugAssert( _index<_stack._length,"Invalid stack iterator" )
  116. _index+=1
  117. _stack.Insert( _index,value )
  118. End
  119. End
  120. Private
  121. Field _data:T[]
  122. Field _length:Int
  123. Public
  124. #rem monkeydoc Creates a new stack.
  125. New() creates an empty stack.
  126. New( length:Int ) creates a stack that initially contains `length` null values.
  127. New( values:T[] ) creates a stack with the contents of an array.
  128. New( values:List<T> ) creates a stack with the contents of a list.
  129. New( values:Deque<T> ) create a stack with the contents of a deque.
  130. New( values:Stack<T> ) create a stack with the contents of another stack.
  131. @param length The length of the stack.
  132. @param values An array, list or stack.
  133. #end
  134. Method New()
  135. _data=New T[10]
  136. End
  137. Method New( length:Int )
  138. _length=length
  139. _data=New T[_length]
  140. End
  141. Method New( values:T[] )
  142. AddAll( values )
  143. End
  144. Method New( values:List<T> )
  145. AddAll( values )
  146. End
  147. Method New( values:Deque<T> )
  148. _length=values.Length
  149. _data=New T[_length]
  150. values.Data.CopyTo( _data,0,0,_length )
  151. End
  152. Method New( values:Stack<T> )
  153. _length=values.Length
  154. _data=New T[_length]
  155. values.Data.CopyTo( _data,0,0,_length )
  156. End
  157. #rem monkeydoc Checks if the stack is empty.
  158. @return True if the stack is empty.
  159. #end
  160. Property Empty:Bool()
  161. Return _length=0
  162. End
  163. #rem monkeydoc Gets an iterator for visiting stack values.
  164. Returns an iterator suitable for use with Eachin, or for manual iteration.
  165. @return A stack iterator.
  166. #end
  167. Method All:Iterator()
  168. Return New Iterator( Self,0 )
  169. End
  170. #rem monkeydoc Gets an iterator for visiting stack values in reverse order.
  171. Returns an iterator suitable for use with Eachin, or for manual iteration.
  172. @return A backwards stack iterator.
  173. #end
  174. Method Backwards:BackwardsIterator()
  175. Return New BackwardsIterator( Self,_length-1 )
  176. End
  177. #rem monkeydoc Converts the stack to an array.
  178. @return An array containing each element of the stack.
  179. #end
  180. Method ToArray:T[]()
  181. Return _data.Slice( 0,_length )
  182. End
  183. #rem monkeydoc Gets the underlying array used by the stack.
  184. Note that the returned array may be longer than the stack length.
  185. @return The array used internally by the stack.
  186. #end
  187. Property Data:T[]()
  188. Return _data
  189. End
  190. #rem monkeydoc Gets the number of values in the stack.
  191. @return The number of values in the stack.
  192. #end
  193. Property Length:Int()
  194. Return _length
  195. End
  196. #rem monkeydoc Gets the storage capacity of the stack.
  197. The capacity of a stack is the number of values it can contain before memory needs to be reallocated to store more values.
  198. If a stack's length equals its capacity, then the next Add or Insert operation will need to allocate more memory to 'grow' the stack.
  199. You don't normally need to worry about stack capacity, but it can be useful to use [[Reserve]] to preallocate stack storage if you know in advance
  200. how many values a stack is likely to contain, in order to prevent the overhead of excessive memory allocation.
  201. @return The current stack capacity.
  202. #end
  203. Property Capacity:Int()
  204. Return _data.Length
  205. End
  206. #rem monkeydoc Compacts the stack
  207. #end
  208. Method Compact()
  209. If _length<>_data.Length _data=_data.Slice( 0,_length )
  210. End
  211. #rem monkeydoc Resizes the stack.
  212. If `length` is greater than the current stack length, any extra elements are initialized to null.
  213. If `length` is less than the current stack length, the stack is truncated.
  214. @param length The new length of the stack.
  215. #end
  216. Method Resize( length:Int )
  217. DebugAssert( length>=0 )
  218. For Local i:=length Until _length
  219. _data[i]=Null
  220. Next
  221. Reserve( length )
  222. _length=length
  223. End
  224. #rem monkeydoc Reserves stack storage capacity.
  225. The capacity of a stack is the number of values it can contain before memory needs to be reallocated to store more values.
  226. If a stack's length equals its capacity, then the next Add, Insert or Push operation will need to allocate more memory to 'grow' the stack.
  227. You don't normally need to worry about stack capacity, but it can be useful to use [[Reserve]] to preallocate stack storage if you know in advance
  228. how many values a stack is likely to contain, in order to prevent the overhead of excessive memory allocation.
  229. @param capacity The new capacity.
  230. #end
  231. Method Reserve( capacity:Int )
  232. DebugAssert( capacity>=0 )
  233. If _data.Length>=capacity Return
  234. capacity=Max( _length*2+_length,capacity )
  235. Local data:=New T[capacity]
  236. _data.CopyTo( data,0,0,_length )
  237. _data=data
  238. End
  239. #rem monkeydoc Clears the stack.
  240. #end
  241. Method Clear()
  242. Resize( 0 )
  243. End
  244. #rem monkeydoc Erases an element at an index in the stack.
  245. In debug builds, a runtime error will occur if `index` is less than 0 or greater than the stack length.
  246. if `index` is equal to the stack length, the operation has no effect.
  247. @param index The index of the element to erase.
  248. #end
  249. Method Erase( index:Int )
  250. DebugAssert( index>=0 And index<=_length )
  251. If index=_length Return
  252. _data.CopyTo( _data,index+1,index,_length-index-1 )
  253. Resize( _length-1 )
  254. End
  255. #rem monkeydoc Erases a range of elements in the stack.
  256. If debug builds, a runtime error will occur if either index is less than 0 or greater than the stack length, or if index2 is less than index1.
  257. The number of elements actually erased is `index2`-`index1`.
  258. @param index1 The index of the first element to erase.
  259. @param index2 The index of the last+1 element to erase.
  260. #end
  261. Method Erase( index1:Int,index2:Int )
  262. DebugAssert( index1>=0 And index1<=_length And index2>=0 And index2<=_length And index1<=index2 )
  263. If index1=_length Return
  264. _data.CopyTo( _data,index2,index1,_length-index2 )
  265. Resize( _length-index2+index1 )
  266. End
  267. #rem monkeydoc Inserts a value at an index in the stack.
  268. In debug builds, a runtime error will occur if `index` is less than 0 or greater than the stack length.
  269. If `index` is equal to the stack length, the value is added to the end of the stack.
  270. @param index The index of the value to insert.
  271. @param value The value to insert.
  272. #end
  273. Method Insert( index:Int,value:T )
  274. DebugAssert( index>=0 And index<=_length )
  275. Reserve( _length+1 )
  276. _data.CopyTo( _data,index,index+1,_length-index )
  277. _data[index]=value
  278. _length+=1
  279. End
  280. #rem monkeydoc Gets the value of a stack element.
  281. In debug builds, a runtime error will occur if `index` is less than 0, or greater than or equal to the length of the stack.
  282. @param index The index of the element to get.
  283. #end
  284. Method Get:T( index:Int )
  285. DebugAssert( index>=0 And index<_length,"Stack index out of range" )
  286. Return _data[index]
  287. End
  288. #rem monkeydoc Sets the value of a stack element.
  289. In debug builds, a runtime error will occur if `index` is less than 0, or greater than or equal to the length of the stack.
  290. @param index The index of the element to set.
  291. @param value The value to set.
  292. #end
  293. Method Set( index:Int,value:T )
  294. DebugAssert( index>=0 And index<_length,"Stack index out of range" )
  295. _data[index]=value
  296. End
  297. #rem monkeydoc Gets the value of a stack element.
  298. In debug builds, a runtime error will occur if `index` is less than 0, or greater than or equal to the length of the stack.
  299. @param index The index of the element to get.
  300. #end
  301. Operator []:T( index:Int )
  302. DebugAssert( index>=0 And index<_length,"Stack index out of range" )
  303. Return _data[index]
  304. End
  305. #rem monkeydoc Sets the value of a stack element.
  306. In debug builds, a runtime error will occur if `index` is less than 0, or greater than or equal to the length of the stack.
  307. @param index The index of the element to set.
  308. @param value The value to set.
  309. #end
  310. Operator []=( index:Int,value:T )
  311. DebugAssert( index>=0 And index<_length,"Stack index out of range" )
  312. _data[index]=value
  313. End
  314. #rem monkeydoc Adds a value to the end of the stack.
  315. This method behaves identically to Push( value:T ).
  316. @param value The value to add.
  317. #end
  318. Method Add( value:T )
  319. Reserve( _length+1 )
  320. _data[_length]=value
  321. _length+=1
  322. End
  323. #rem monkeydoc Adds the values in an array or container to the end of the stack.
  324. @param values The values to add.
  325. #end
  326. Method AddAll( values:T[] )
  327. Reserve( _length+values.Length )
  328. values.CopyTo( _data,0,_length,values.Length )
  329. Resize( _length+values.Length )
  330. End
  331. Method AddAll<C>( values:C ) Where C Implements IContainer<T>
  332. For Local value:=Eachin values
  333. Add( value )
  334. Next
  335. End
  336. #rem monkeydoc @deprecated Use [[AddAll]].
  337. #End
  338. Method Append<C>( values:C ) Where C Implements IContainer<T>
  339. For Local value:=Eachin values
  340. Add( value )
  341. Next
  342. End
  343. #rem monkeydoc Finds the index of the first matching value in the stack.
  344. In debug builds, a runtime error will occur if `start` is less than 0 or greater than the length of the stack.
  345. @param value The value to find.
  346. @param start The starting index for the search.
  347. @return The index of the value in the stack, or -1 if the value was not found.
  348. #end
  349. Method FindIndex:Int( value:T,start:Int=0 )
  350. DebugAssert( start>=0 And start<=_length )
  351. Local i:=start
  352. While i<_length
  353. If _data[i]=value Return i
  354. i+=1
  355. Wend
  356. Return -1
  357. End
  358. #rem monkeydoc Finds the index of the last matching value in the stack.
  359. In debug builds, a runtime error will occur if `start` is less than 0 or greater than the length of the stack.
  360. @param value The value to find.
  361. @param start The starting index for the search.
  362. @return The index of the value in the stack, or -1 if the value was not found.
  363. #end
  364. Method FindLastIndex:Int( value:T,start:Int=0 )
  365. DebugAssert( start>=0 And start<=_length )
  366. Local i:=_length
  367. While i>start
  368. i-=1
  369. If _data[i]=value Return i
  370. Wend
  371. Return -1
  372. End
  373. #rem monkeydoc Checks if the stack contains a value.
  374. @param value The value to check for.
  375. @return True if the stack contains the value, else false.
  376. #end
  377. Method Contains:Bool( value:T )
  378. Return FindIndex( value )<>-1
  379. End
  380. #rem monkeydoc Finds and removes the first matching value from the stack.
  381. @param start The starting index for the search.
  382. @param value The value to remove.
  383. @return True if the value was removed.
  384. #end
  385. Method Remove:Bool( value:T,start:Int=0 )
  386. Local i:=FindIndex( value,start )
  387. If i=-1 Return False
  388. Erase( i )
  389. Return True
  390. End
  391. #rem monkeydoc Finds and removes the last matching value from the stack.
  392. @param start The starting index for the search.
  393. @param value The value to remove.
  394. @return True if the value was removed.
  395. #end
  396. Method RemoveLast:Bool( value:T,start:Int=0 )
  397. Local i:=FindLastIndex( value,start )
  398. If i=-1 Return False
  399. Erase( i )
  400. Return True
  401. End
  402. #rem monkeydoc Finds and removes each matching value from the stack.
  403. @param value The value to remove.
  404. @return The number of values removed.
  405. #end
  406. Method RemoveEach:Int( value:T )
  407. Local put:=0,n:=0
  408. For Local get:=0 Until _length
  409. If _data[get]=value
  410. n+=1
  411. Continue
  412. Endif
  413. _data[put]=_data[get]
  414. put+=1
  415. Next
  416. Resize( put )
  417. Return n
  418. End
  419. #rem monkeydoc Removes all values int the stack that fulfill a condition.
  420. @param condition The condition to test.
  421. @return The number of values removed.
  422. #end
  423. Method RemoveIf:Int( condition:Bool( value:T ) )
  424. Local put:=0,n:=0
  425. For Local get:=0 Until _length
  426. If condition( _data[get] )
  427. n+=1
  428. Continue
  429. Endif
  430. _data[put]=_data[get]
  431. put+=1
  432. Next
  433. Resize( put )
  434. Return n
  435. End
  436. #rem monkeydoc Returns a range of elements from the stack.
  437. Returns a slice of the stack consisting of all elements from `index1` until `index2` or the end of the stack.
  438. If either index is negative, then it represents an offset from the end of the stack.
  439. Indices are clamped to the length of the stack, so Slice will never cause a runtime error.
  440. @param index1 the index of the first element (inclusive).
  441. @param index2 the index of the last element (exclusive).
  442. @return A new stack.
  443. #end
  444. Method Slice:Stack( index:Int )
  445. Return Slice( index,_length )
  446. End
  447. Method Slice:Stack( index1:Int,index2:Int )
  448. If index1<0
  449. index1=Max( index1+_length,0 )
  450. Else If index1>_length
  451. index1=_length
  452. Endif
  453. If index2<0
  454. index2=Max( index2+_length,index1 )
  455. Else If index2>_length
  456. index2=_length
  457. Else If index2<index1
  458. index2=index1
  459. Endif
  460. Return New Stack( _data.Slice( index1,index2 ) )
  461. End
  462. #rem monkeydoc Swaps 2 elements in the stack, or 2 stacks.
  463. This method can be used to either swap 2 elements in the stack, or 2 entire stacks.
  464. In debug builds, a runtime error will occur if `index1` or `index2` is out of range.
  465. Swapping entire stacks simply swaps the storage arrays and lengths of the 2 stacks, and is therefore very fast.
  466. @param index1 The index of the first element.
  467. @param index2 The index of the second element.
  468. @param stack The stack to swap with.
  469. #end
  470. Method Swap( index1:Int,index2:Int )
  471. DebugAssert( index1>=0 And index1<_length And index2>=0 And index2<_length,"Stack index out of range" )
  472. Local t:=_data[index1]
  473. _data[index1]=_data[index2]
  474. _data[index2]=t
  475. End
  476. Method Swap( stack:Stack )
  477. Local data:=_data,length:=_length
  478. _data=stack._data
  479. _length=stack._length
  480. stack._data=data
  481. stack._length=length
  482. End
  483. #rem monkeydoc Sorts the stack.
  484. @param ascending True to sort the stack in ascending order, false to sort in descending order.
  485. @param compareFunc Function to be used to compare values when sorting.
  486. @param lo Index of first value to sort.
  487. @param hi Index of last value to sort.
  488. #end
  489. Method Sort( ascending:Int=True )
  490. If ascending
  491. Sort( Lambda:Int( x:T,y:T )
  492. Return x<=>y
  493. End )
  494. Else
  495. Sort( Lambda:Int( x:T,y:T )
  496. Return y<=>x
  497. End )
  498. Endif
  499. End
  500. Method Sort( compareFunc:Int( x:T,y:T ) )
  501. Sort( compareFunc,0,_length-1 )
  502. End
  503. Method Sort( compareFunc:Int( x:T,y:T ),lo:Int,hi:int )
  504. If hi<=lo Return
  505. If lo+1=hi
  506. If compareFunc( _data[hi],_data[lo] )<0 Swap( hi,lo )
  507. Return
  508. Endif
  509. Local i:=(lo+hi)/2
  510. If compareFunc( _data[i],_data[lo] )<0 Swap( i,lo )
  511. If compareFunc( _data[hi],_data[i] )<0
  512. Swap( hi,i )
  513. If compareFunc( _data[i],_data[lo] )<0 Swap( i,lo )
  514. Endif
  515. Local x:=lo+1
  516. Local y:=hi-1
  517. Repeat
  518. Local p:=_data[i]
  519. While compareFunc( _data[x],p )<0
  520. x+=1
  521. Wend
  522. While compareFunc( p,_data[y] )<0
  523. y-=1
  524. Wend
  525. If x>y Exit
  526. If x<y
  527. Swap( x,y )
  528. If i=x i=y Else If i=y i=x
  529. Endif
  530. x+=1
  531. y-=1
  532. Until x>y
  533. Sort( compareFunc,lo,y )
  534. Sort( compareFunc,x,hi )
  535. End
  536. #rem monkeydoc Gets the top element of the stack
  537. In debug builds, a runtime error will occur if the stack is empty.
  538. @return The top element of the stack.
  539. #end
  540. Property Top:T()
  541. DebugAssert( _length,"Stack is empty" )
  542. Return _data[_length-1]
  543. End
  544. #rem monkeydoc Pops the top element off the stack and returns it.
  545. In debug builds, a runtime error will occur if the stack is empty.
  546. @return The top element of the stack before it was popped.
  547. #end
  548. Method Pop:T()
  549. DebugAssert( _length,"Stack is empty" )
  550. _length-=1
  551. Local value:=_data[_length]
  552. _data[_length]=Null
  553. Return value
  554. End
  555. #rem monkeydoc Pushes a value on the stack.
  556. This method behaves identically to Add( value:T ).
  557. @param value The value to push.
  558. #end
  559. Method Push( value:T )
  560. Add( value )
  561. End
  562. #rem monkeydoc Joins the values in a string stack.
  563. @param sepeator The separator to be used when joining values.
  564. @return The joined values.
  565. #end
  566. Method Join:String( separator:String ) Where T=String
  567. Return separator.Join( ToArray() )
  568. End
  569. End