2
0

linkedlist.bmx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. Strict
  2. Rem
  3. bbdoc: Data structures/Linked lists
  4. End Rem
  5. Module BRL.LinkedList
  6. ModuleInfo "Version: 1.07"
  7. ModuleInfo "Author: Mark Sibly"
  8. ModuleInfo "License: zlib/libpng"
  9. ModuleInfo "Copyright: Blitz Research Ltd"
  10. ModuleInfo "Modserver: BRL"
  11. ModuleInfo "History: 1.07 Release"
  12. ModuleInfo "History: Changed Reverse to maintain TLink stability"
  13. ModuleInfo "History: 1.06 Release"
  14. ModuleInfo "History: Added optional CompareFunc parameter to Sort"
  15. ModuleInfo "History: 1.05 Release"
  16. ModuleInfo "History: Sort now swaps links instead of values"
  17. Function CompareObjects( o1:Object,o2:Object )
  18. Return o1.Compare( o2 )
  19. End Function
  20. Rem
  21. bbdoc: Link Object used by TList
  22. End Rem
  23. Type TLink
  24. Field _value:Object
  25. Field _succ:TLink,_pred:TLink
  26. Rem
  27. bbdoc: Returns the Object associated with this Link.
  28. End Rem
  29. Method Value:Object()
  30. Return _value
  31. End Method
  32. Rem
  33. bbdoc: Returns the next link in the List.
  34. End Rem
  35. Method NextLink:TLink()
  36. If _succ._value<>_succ Return _succ
  37. End Method
  38. Rem
  39. bbdoc: Returns the previous link in the List.
  40. End Rem
  41. Method PrevLink:TLink()
  42. If _pred._value<>_pred Return _pred
  43. End Method
  44. Rem
  45. bbdoc: Removes the link from the List.
  46. End Rem
  47. Method Remove()
  48. _value=Null
  49. _succ._pred=_pred
  50. _pred._succ=_succ
  51. End Method
  52. End Type
  53. Rem
  54. bbdoc: Enumerator Object use by TList in order to implement Eachin support.
  55. End Rem
  56. Type TListEnum
  57. Field _link:TLink
  58. Method HasNext()
  59. Return _link._value<>_link
  60. End Method
  61. Method NextObject:Object()
  62. Local value:Object=_link._value
  63. Assert value<>_link
  64. _link=_link._succ
  65. Return value
  66. End Method
  67. End Type
  68. Rem
  69. bbdoc: Linked List
  70. End Rem
  71. Type TList
  72. Field _head:TLink
  73. Method _pad()
  74. End Method
  75. Method New()
  76. _head=New TLink
  77. _head._succ=_head
  78. _head._pred=_head
  79. _head._value=_head
  80. End Method
  81. ?Not Threaded
  82. Method Delete()
  83. Clear
  84. _head._value=Null
  85. _head._succ=Null
  86. _head._pred=Null
  87. End Method
  88. ?
  89. Rem
  90. bbdoc: Clear a linked list
  91. about: Removes all objects from @list.
  92. End Rem
  93. Method Clear()
  94. While _head._succ<>_head
  95. _head._succ.Remove
  96. Wend
  97. End Method
  98. Rem
  99. bbdoc: Check if list is empty
  100. returns: True if list is empty, else false
  101. end rem
  102. Method IsEmpty()
  103. Return _head._succ=_head
  104. End Method
  105. Rem
  106. bbdoc: Check if list contains a value
  107. returns: True if list contains @value, else false
  108. end rem
  109. Method Contains( value:Object )
  110. Local link:TLink=_head._succ
  111. While link<>_head
  112. If link._value.Compare( value )=0 Return True
  113. link=link._succ
  114. Wend
  115. Return False
  116. End Method
  117. Rem
  118. bbdoc: Add an object to the start of the list
  119. returns: A link object
  120. End Rem
  121. Method AddFirst:TLink( value:Object )
  122. Assert value Else "Can't insert Null object into list"
  123. Return InsertAfterLink( value,_head )
  124. End Method
  125. Rem
  126. bbdoc: Add an object to the end of the list
  127. returns: A link object
  128. End Rem
  129. Method AddLast:TLink( value:Object )
  130. Assert value Else "Can't insert Null object into list"
  131. Return InsertBeforeLink( value,_head )
  132. End Method
  133. Rem
  134. bbdoc: Returns the first object in the list
  135. about: Returns Null if the list is empty.
  136. End Rem
  137. Method First:Object()
  138. If IsEmpty() Return
  139. Return _head._succ._value
  140. End Method
  141. Rem
  142. bbdoc: Returns the last object in the list
  143. about: Returns Null if the list is empty.
  144. End Rem
  145. Method Last:Object()
  146. If IsEmpty() Return
  147. Return _head._pred._value
  148. End Method
  149. Rem
  150. bbdoc: Removes and returns the first object in the list.
  151. about: Returns Null if the list is empty.
  152. End Rem
  153. Method RemoveFirst:Object()
  154. If IsEmpty() Return
  155. Local value:Object=_head._succ._value
  156. _head._succ.remove
  157. Return value
  158. End Method
  159. Rem
  160. bbdoc: Removes and returns the last object in the list.
  161. about: Returns Null if the list is empty.
  162. End Rem
  163. Method RemoveLast:Object()
  164. If IsEmpty() Return
  165. Local value:Object=_head._pred._value
  166. _head._pred.remove
  167. Return value
  168. End Method
  169. Rem
  170. bbdoc: Returns the first link the list or null if the list is empty.
  171. End Rem
  172. Method FirstLink:TLink()
  173. If _head._succ<>_head Return _head._succ
  174. End Method
  175. Rem
  176. bbdoc: Returns the last link the list or null if the list is empty.
  177. End Rem
  178. Method LastLink:TLink()
  179. If _head._pred<>_head Return _head._pred
  180. End Method
  181. Rem
  182. bbdoc: Inserts an object before the specified list link.
  183. End Rem
  184. Method InsertBeforeLink:TLink( value:Object,succ:TLink )
  185. Assert value Else "Can't insert Null object into list"
  186. Local link:TLink=New TLink
  187. link._value=value
  188. link._succ=succ
  189. link._pred=succ._pred
  190. link._pred._succ=link
  191. succ._pred=link
  192. Return link
  193. End Method
  194. Rem
  195. bbdoc: Inserts an object after the specified list link.
  196. End Rem
  197. Method InsertAfterLink:TLink( value:Object,pred:TLink )
  198. Assert value Else "Can't insert Null object into list"
  199. Local link:TLink=New TLink
  200. link._value=value
  201. link._pred=pred
  202. link._succ=pred._succ
  203. link._succ._pred=link
  204. pred._succ=link
  205. Return link
  206. End Method
  207. Rem
  208. bbdoc: Returns the first link in the list with the given value, or null if none found.
  209. End Rem
  210. Method FindLink:TLink( value:Object )
  211. Local link:TLink=_head._succ
  212. While link<>_head
  213. If link._value.Compare( value )=0 Return link
  214. link=link._succ
  215. Wend
  216. End Method
  217. Rem
  218. bbdoc: Returns the value of the link at the given index.
  219. about: Throws an exception if the index is out of range (must be 0..list.Count()-1 inclusive).
  220. End Rem
  221. Method ValueAtIndex:Object( index )
  222. Assert index>=0 Else "Object index must be positive"
  223. Local link:TLink=_head._succ
  224. While link<>_head
  225. If Not index Return link._value
  226. link=link._succ
  227. index:-1
  228. Wend
  229. RuntimeError "List index out of range"
  230. End Method
  231. Rem
  232. bbdoc: Count list length
  233. returns: The numbers of objects in @list.
  234. end rem
  235. Method Count()
  236. Local link:TLink=_head._succ,count
  237. While link<>_head
  238. count:+1
  239. link=link._succ
  240. Wend
  241. Return count
  242. End Method
  243. Rem
  244. bbdoc: Remove an object from a linked list
  245. about: Remove scans a list for the specified value and removes its link.
  246. End Rem
  247. Method Remove( value:Object )
  248. Local link:TLink=FindLink( value )
  249. If Not link Return False
  250. link.Remove
  251. Return True
  252. End Method
  253. Rem
  254. bbdoc: Swap contents with the list specified.
  255. End Rem
  256. Method Swap( list:TList )
  257. Local head:TLink=_head
  258. _head=list._head
  259. list._head=head
  260. End Method
  261. Rem
  262. bbdoc: Creates an identical copy of the list.
  263. End Rem
  264. Method Copy:TList()
  265. Local list:TList=New TList
  266. Local link:TLink=_head._succ
  267. While link<>_head
  268. list.AddLast link._value
  269. link=link._succ
  270. Wend
  271. Return list
  272. End Method
  273. Rem
  274. bbdoc: Reverse the order of the list.
  275. End Rem
  276. Method Reverse()
  277. Local pred:TLink=_head,succ:TLink=pred._succ
  278. Repeat
  279. Local link:TLink=succ._succ
  280. pred._pred=succ
  281. succ._succ=pred
  282. pred=succ
  283. succ=link
  284. Until pred=_head
  285. End Method
  286. Rem
  287. bbdoc: Creates a new list that is the reversed version of this list.
  288. End Rem
  289. Method Reversed:TList()
  290. Local list:TList=New TList
  291. Local link:TLink=_head._succ
  292. While link<>_head
  293. list.AddFirst link._value
  294. link=link._succ
  295. Wend
  296. Return list
  297. End Method
  298. Rem
  299. bbdoc: Sort a list in either ascending (default) or decending order.
  300. about: User types should implement a Compare method in order to be sorted.
  301. End Rem
  302. Method Sort( ascending=True,compareFunc( o1:Object,o2:Object )=CompareObjects )
  303. Local ccsgn=-1
  304. If ascending ccsgn=1
  305. Local insize=1
  306. Repeat
  307. Local merges
  308. Local tail:TLink=_head
  309. Local p:TLink=_head._succ
  310. While p<>_head
  311. merges:+1
  312. Local q:TLink=p._succ,qsize=insize,psize=1
  313. While psize<insize And q<>_head
  314. psize:+1
  315. q=q._succ
  316. Wend
  317. Repeat
  318. Local t:TLink
  319. If psize And qsize And q<>_head
  320. Local cc=CompareFunc( p._value,q._value ) * ccsgn
  321. If cc<=0
  322. t=p
  323. p=p._succ
  324. psize:-1
  325. Else
  326. t=q
  327. q=q._succ
  328. qsize:-1
  329. EndIf
  330. Else If psize
  331. t=p
  332. p=p._succ
  333. psize:-1
  334. Else If qsize And q<>_head
  335. t=q
  336. q=q._succ
  337. qsize:-1
  338. Else
  339. Exit
  340. EndIf
  341. t._pred=tail
  342. tail._succ=t
  343. tail=t
  344. Forever
  345. p=q
  346. Wend
  347. tail._succ=_head
  348. _head._pred=tail
  349. If merges<=1 Return
  350. insize:*2
  351. Forever
  352. End Method
  353. Method ObjectEnumerator:TListEnum()
  354. Local enum:TListEnum=New TListEnum
  355. enum._link=_head._succ
  356. Return enum
  357. End Method
  358. Rem
  359. bbdoc: convert a list to an array
  360. returns: An array of objects
  361. end rem
  362. Method ToArray:Object[]()
  363. Local arr:Object[Count()],i
  364. Local link:TLink=_head._succ
  365. While link<>_head
  366. arr[i]=link._value
  367. link=link._succ
  368. i:+1
  369. Wend
  370. Return arr
  371. End Method
  372. Rem
  373. bbdoc: Create a list from an array
  374. returns: A new linked list
  375. end rem
  376. Function FromArray:TList( arr:Object[] )
  377. Local list:TList=New TList
  378. For Local i=0 Until arr.length
  379. list.AddLast arr[i]
  380. Next
  381. Return list
  382. End Function
  383. End Type
  384. Rem
  385. bbdoc: Create a linked list
  386. returns: A new linked list object
  387. end rem
  388. Function CreateList:TList()
  389. Return New TList
  390. End Function
  391. Rem
  392. bbdoc: Clear a linked list
  393. about: Removes all objects from @list.
  394. end rem
  395. Function ClearList( list:TList )
  396. list.Clear
  397. End Function
  398. Rem
  399. bbdoc: Count list length
  400. returns: The numbers of objects in @list.
  401. end rem
  402. Function CountList( list:TList )
  403. Return list.Count()
  404. End Function
  405. Rem
  406. bbdoc: Check if list is empty
  407. returns: True if list is empty, else false
  408. end rem
  409. Function ListIsEmpty( list:TList )
  410. Return list.IsEmpty()
  411. End Function
  412. Rem
  413. bbdoc: Check if list contains a value
  414. returns: True if list contains @value, else false
  415. end rem
  416. Function ListContains( list:TList,value:Object )
  417. Return list.Contains( value )
  418. End Function
  419. Rem
  420. bbdoc: Sort a list
  421. end rem
  422. Function SortList( list:TList,ascending=True,compareFunc( o1:Object,o2:Object )=CompareObjects )
  423. list.Sort ascending,compareFunc
  424. End Function
  425. Rem
  426. bbdoc: Create a list from an array
  427. returns: A new linked list
  428. end rem
  429. Function ListFromArray:TList( arr:Object[] )
  430. Return TList.FromArray( arr )
  431. End Function
  432. Rem
  433. bbdoc: convert a list to an array
  434. returns: An array of objects
  435. end rem
  436. Function ListToArray:Object[]( list:TList )
  437. Return list.ToArray()
  438. End Function
  439. Rem
  440. bbdoc: Swap the contents of 2 lists
  441. end rem
  442. Function SwapLists( list_x:TList,list_y:TList )
  443. list_x.Swap list_y
  444. End Function
  445. Rem
  446. bbdoc: Reverse the order of elements of a list
  447. end rem
  448. Function ReverseList( list:TList )
  449. list.Reverse
  450. End Function
  451. Rem
  452. bbdoc: Find a link in a list
  453. returns: The link containting @value
  454. end rem
  455. Function ListFindLink:TLink( list:TList,value:Object )
  456. Return list.FindLink( value )
  457. End Function
  458. Rem
  459. bbdoc: Add an object to a linked list
  460. returns: A link object
  461. end rem
  462. Function ListAddLast:TLink( list:TList,value:Object )
  463. Return list.AddLast( value )
  464. End Function
  465. Rem
  466. bbdoc: Add an object to a linked list
  467. returns: A link object
  468. end rem
  469. Function ListAddFirst:TLink( list:TList,value:Object )
  470. Return list.AddFirst( value )
  471. End Function
  472. Rem
  473. bbdoc: Remove an object from a linked list
  474. about: #ListRemove scans a list for the specified value and removes its link.
  475. end rem
  476. Function ListRemove( list:TList,value:Object )
  477. list.Remove value
  478. End Function
  479. Rem
  480. bbdoc: Remove an object from a linked list
  481. about: #RemoveLink is more efficient than #ListRemove.
  482. end rem
  483. Function RemoveLink( link:TLink )
  484. link.Remove
  485. End Function