stack.monkey2 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795
  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 Resizes the stack.
  207. If `length` is greater than the current stack length, any extra elements are initialized to null.
  208. If `length` is less than the current stack length, the stack is truncated.
  209. @param length The new length of the stack.
  210. #end
  211. Method Resize( length:Int )
  212. DebugAssert( length>=0 )
  213. For Local i:=length Until _length
  214. _data[i]=Null
  215. Next
  216. Reserve( length )
  217. _length=length
  218. End
  219. #rem monkeydoc Reserves stack storage capacity.
  220. The capacity of a stack is the number of values it can contain before memory needs to be reallocated to store more values.
  221. 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.
  222. 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
  223. how many values a stack is likely to contain, in order to prevent the overhead of excessive memory allocation.
  224. @param capacity The new capacity.
  225. #end
  226. Method Reserve( capacity:Int )
  227. DebugAssert( capacity>=0 )
  228. If _data.Length>=capacity Return
  229. capacity=Max( _length*2+_length,capacity )
  230. Local data:=New T[capacity]
  231. _data.CopyTo( data,0,0,_length )
  232. _data=data
  233. End
  234. #rem monkeydoc Clears the stack.
  235. #end
  236. Method Clear()
  237. Resize( 0 )
  238. End
  239. #rem monkeydoc Erases an element at an index in the stack.
  240. In debug builds, a runtime error will occur if `index` is less than 0 or greater than the stack length.
  241. if `index` is equal to the stack length, the operation has no effect.
  242. @param index The index of the element to erase.
  243. #end
  244. Method Erase( index:Int )
  245. DebugAssert( index>=0 And index<=_length )
  246. If index=_length Return
  247. _data.CopyTo( _data,index+1,index,_length-index-1 )
  248. Resize( _length-1 )
  249. End
  250. #rem monkeydoc Erases a range of elements in the stack.
  251. 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.
  252. The number of elements actually erased is `index2`-`index1`.
  253. @param index1 The index of the first element to erase.
  254. @param index2 The index of the last+1 element to erase.
  255. #end
  256. Method Erase( index1:Int,index2:Int )
  257. DebugAssert( index1>=0 And index1<=_length And index2>=0 And index2<=_length And index1<=index2 )
  258. If index1=_length Return
  259. _data.CopyTo( _data,index2,index1,_length-index2 )
  260. Resize( _length-index2+index1 )
  261. End
  262. #rem monkeydoc Inserts a value at an index in the stack.
  263. In debug builds, a runtime error will occur if `index` is less than 0 or greater than the stack length.
  264. If `index` is equal to the stack length, the value is added to the end of the stack.
  265. @param index The index of the value to insert.
  266. @param value The value to insert.
  267. #end
  268. Method Insert( index:Int,value:T )
  269. DebugAssert( index>=0 And index<=_length )
  270. Reserve( _length+1 )
  271. _data.CopyTo( _data,index,index+1,_length-index )
  272. _data[index]=value
  273. _length+=1
  274. End
  275. #rem monkeydoc Gets the value of a stack element.
  276. 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.
  277. @param index The index of the element to get.
  278. #end
  279. Method Get:T( index:Int )
  280. DebugAssert( index>=0 And index<_length,"Stack index out of range" )
  281. Return _data[index]
  282. End
  283. #rem monkeydoc Sets the value of a stack element.
  284. 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.
  285. @param index The index of the element to set.
  286. @param value The value to set.
  287. #end
  288. Method Set( index:Int,value:T )
  289. DebugAssert( index>=0 And index<_length,"Stack index out of range" )
  290. _data[index]=value
  291. End
  292. #rem monkeydoc Gets the value of a stack element.
  293. 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.
  294. @param index The index of the element to get.
  295. #end
  296. Operator []:T( index:Int )
  297. DebugAssert( index>=0 And index<_length,"Stack index out of range" )
  298. Return _data[index]
  299. End
  300. #rem monkeydoc Sets the value of a stack element.
  301. 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.
  302. @param index The index of the element to set.
  303. @param value The value to set.
  304. #end
  305. Operator []=( index:Int,value:T )
  306. DebugAssert( index>=0 And index<_length,"Stack index out of range" )
  307. _data[index]=value
  308. End
  309. #rem monkeydoc Adds a value to the end of the stack.
  310. This method behaves identically to Push( value:T ).
  311. @param value The value to add.
  312. #end
  313. Method Add( value:T )
  314. Reserve( _length+1 )
  315. _data[_length]=value
  316. _length+=1
  317. End
  318. #rem monkeydoc Adds the values in an array or container to the end of the stack.
  319. @param values The values to add.
  320. #end
  321. Method AddAll( values:T[] )
  322. Reserve( _length+values.Length )
  323. values.CopyTo( _data,0,_length,values.Length )
  324. Resize( _length+values.Length )
  325. End
  326. Method AddAll<C>( values:C ) Where C Implements IContainer<T>
  327. For Local value:=Eachin values
  328. Add( value )
  329. Next
  330. End
  331. #rem monkeydoc @deprecated Use [[AddAll]].
  332. #End
  333. Method Append<C>( values:C ) Where C Implements IContainer<T>
  334. For Local value:=Eachin values
  335. Add( value )
  336. Next
  337. End
  338. #rem monkeydoc Finds the index of the first matching value in the stack.
  339. In debug builds, a runtime error will occur if `start` is less than 0 or greater than the length of the stack.
  340. @param value The value to find.
  341. @param start The starting index for the search.
  342. @return The index of the value in the stack, or -1 if the value was not found.
  343. #end
  344. Method FindIndex:Int( value:T,start:Int=0 )
  345. DebugAssert( start>=0 And start<=_length )
  346. Local i:=start
  347. While i<_length
  348. If _data[i]=value Return i
  349. i+=1
  350. Wend
  351. Return -1
  352. End
  353. #rem monkeydoc Finds the index of the last matching value in the stack.
  354. In debug builds, a runtime error will occur if `start` is less than 0 or greater than the length of the stack.
  355. @param value The value to find.
  356. @param start The starting index for the search.
  357. @return The index of the value in the stack, or -1 if the value was not found.
  358. #end
  359. Method FindLastIndex:Int( value:T,start:Int=0 )
  360. DebugAssert( start>=0 And start<=_length )
  361. Local i:=_length
  362. While i>start
  363. i-=1
  364. If _data[i]=value Return i
  365. Wend
  366. Return -1
  367. End
  368. #rem monkeydoc Checks if the stack contains a value.
  369. @param value The value to check for.
  370. @return True if the stack contains the value, else false.
  371. #end
  372. Method Contains:Bool( value:T )
  373. Return FindIndex( value )<>-1
  374. End
  375. #rem monkeydoc Finds and removes the first matching value from the stack.
  376. @param start The starting index for the search.
  377. @param value The value to remove.
  378. @return True if the value was removed.
  379. #end
  380. Method Remove:Bool( value:T,start:Int=0 )
  381. Local i:=FindIndex( value,start )
  382. If i=-1 Return False
  383. Erase( i )
  384. Return True
  385. End
  386. #rem monkeydoc Finds and removes the last matching value from the stack.
  387. @param start The starting index for the search.
  388. @param value The value to remove.
  389. @return True if the value was removed.
  390. #end
  391. Method RemoveLast:Bool( value:T,start:Int=0 )
  392. Local i:=FindLastIndex( value,start )
  393. If i=-1 Return False
  394. Erase( i )
  395. Return True
  396. End
  397. #rem monkeydoc Finds and removes each matching value from the stack.
  398. @param value The value to remove.
  399. @return The number of values removed.
  400. #end
  401. Method RemoveEach:Int( value:T )
  402. Local put:=0,n:=0
  403. For Local get:=0 Until _length
  404. If _data[get]=value
  405. n+=1
  406. Continue
  407. Endif
  408. _data[put]=_data[get]
  409. put+=1
  410. Next
  411. Resize( put )
  412. Return n
  413. End
  414. #rem monkeydoc Removes all values int the stack that fulfill a condition.
  415. @param condition The condition to test.
  416. @return The number of values removed.
  417. #end
  418. Method RemoveIf:Int( condition:Bool( value:T ) )
  419. Local put:=0,n:=0
  420. For Local get:=0 Until _length
  421. If condition( _data[get] )
  422. n+=1
  423. Continue
  424. Endif
  425. _data[put]=_data[get]
  426. put+=1
  427. Next
  428. Resize( put )
  429. Return n
  430. End
  431. #rem monkeydoc Returns a range of elements from the stack.
  432. Returns a slice of the stack consisting of all elements from `index1` until `index2` or the end of the stack.
  433. If either index is negative, then it represents an offset from the end of the stack.
  434. Indices are clamped to the length of the stack, so Slice will never cause a runtime error.
  435. @param index1 the index of the first element (inclusive).
  436. @param index2 the index of the last element (exclusive).
  437. @return A new stack.
  438. #end
  439. Method Slice:Stack( index:Int )
  440. Return Slice( index,_length )
  441. End
  442. Method Slice:Stack( index1:Int,index2:Int )
  443. If index1<0
  444. index1=Max( index1+_length,0 )
  445. Else If index1>_length
  446. index1=_length
  447. Endif
  448. If index2<0
  449. index2=Max( index2+_length,index1 )
  450. Else If index2>_length
  451. index2=_length
  452. Else If index2<index1
  453. index2=index1
  454. Endif
  455. Return New Stack( _data.Slice( index1,index2 ) )
  456. End
  457. #rem monkeydoc Swaps 2 elements in the stack.
  458. In debug builds, a runtime error will occur if `index1` or `index2` is out of range.
  459. @param index1 The index of the first element.
  460. @param index2 The index of the second element.
  461. #end
  462. Method Swap( index1:Int,index2:Int )
  463. DebugAssert( index1>=0 And index1<_length And index2>=0 And index2<_length,"Stack index out of range" )
  464. Local t:=_data[index1]
  465. _data[index1]=_data[index2]
  466. _data[index2]=t
  467. End
  468. #rem monkeydoc Sorts the stack.
  469. @param ascending True to sort the stack in ascending order, false to sort in descending order.
  470. @param compareFunc Function to be used to compare values when sorting.
  471. @param lo Index of first value to sort.
  472. @param hi Index of last value to sort.
  473. #end
  474. Method Sort( ascending:Int=True )
  475. If ascending
  476. Sort( Lambda:Int( x:T,y:T )
  477. Return x<=>y
  478. End )
  479. Else
  480. Sort( Lambda:Int( x:T,y:T )
  481. Return y<=>x
  482. End )
  483. Endif
  484. End
  485. Method Sort( compareFunc:Int( x:T,y:T ) )
  486. Sort( compareFunc,0,_length-1 )
  487. End
  488. Method Sort( compareFunc:Int( x:T,y:T ),lo:Int,hi:int )
  489. If hi<=lo Return
  490. If lo+1=hi
  491. If compareFunc( _data[hi],_data[lo] )<0 Swap( hi,lo )
  492. Return
  493. Endif
  494. Local i:=(lo+hi)/2
  495. If compareFunc( _data[i],_data[lo] )<0 Swap( i,lo )
  496. If compareFunc( _data[hi],_data[i] )<0
  497. Swap( hi,i )
  498. If compareFunc( _data[i],_data[lo] )<0 Swap( i,lo )
  499. Endif
  500. Local x:=lo+1
  501. Local y:=hi-1
  502. Repeat
  503. Local p:=_data[i]
  504. While compareFunc( _data[x],p )<0
  505. x+=1
  506. Wend
  507. While compareFunc( p,_data[y] )<0
  508. y-=1
  509. Wend
  510. If x>y Exit
  511. If x<y
  512. Swap( x,y )
  513. If i=x i=y Else If i=y i=x
  514. Endif
  515. x+=1
  516. y-=1
  517. Until x>y
  518. Sort( compareFunc,lo,y )
  519. Sort( compareFunc,x,hi )
  520. End
  521. #rem monkeydoc Gets the top element of the stack
  522. In debug builds, a runtime error will occur if the stack is empty.
  523. @return The top element of the stack.
  524. #end
  525. Property Top:T()
  526. DebugAssert( _length,"Stack is empty" )
  527. Return _data[_length-1]
  528. End
  529. #rem monkeydoc Pops the top element off the stack and returns it.
  530. In debug builds, a runtime error will occur if the stack is empty.
  531. @return The top element of the stack before it was popped.
  532. #end
  533. Method Pop:T()
  534. DebugAssert( _length,"Stack is empty" )
  535. _length-=1
  536. Local value:=_data[_length]
  537. _data[_length]=Null
  538. Return value
  539. End
  540. #rem monkeydoc Pushes a value on the stack.
  541. This method behaves identically to Add( value:T ).
  542. @param value The value to push.
  543. #end
  544. Method Push( value:T )
  545. Add( value )
  546. End
  547. #rem monkeydoc Joins the values in a string stack.
  548. @param sepeator The separator to be used when joining values.
  549. @return The joined values.
  550. #end
  551. Method Join:String( separator:String ) Where T=String
  552. Return separator.Join( ToArray() )
  553. End
  554. End