map.bmx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. Strict
  2. Rem
  3. bbdoc: Data structures/Maps
  4. End Rem
  5. Module BRL.Map
  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: Fixed MapKeys/MapValues functions to return enumerators"
  13. ModuleInfo "History: 1.06 Release"
  14. ModuleInfo "History: Restored KeyValue enumerator"
  15. ModuleInfo "History: 1.05 Release"
  16. ModuleInfo "History: Added Copy method"
  17. ModuleInfo "History: 1.04 Release"
  18. ModuleInfo "History: Fixed Clear memleak"
  19. ModuleInfo "History: 1.03 Release"
  20. ModuleInfo "History: Finally changed to red/back tree!"
  21. ModuleInfo "History: Added procedural interface"
  22. ModuleInfo "History: 1.02 Release"
  23. ModuleInfo "History: Fixed TMap.Remove:TNode not returning node"
  24. Private
  25. Global nil:TNode=New TNode
  26. nil._color=TMap.BLACK
  27. nil._parent=nil
  28. nil._left=nil
  29. nil._right=nil
  30. Public
  31. Type TKeyValue
  32. Method Key:Object()
  33. Return _key
  34. End Method
  35. Method Value:Object()
  36. Return _value
  37. End Method
  38. '***** PRIVATE *****
  39. Field _key:Object,_value:Object
  40. End Type
  41. Type TNode Extends TKeyValue
  42. Method NextNode:TNode()
  43. Local node:TNode=Self
  44. If node._right<>nil
  45. node=_right
  46. While node._left<>nil
  47. node=node._left
  48. Wend
  49. Return node
  50. EndIf
  51. Local parent:TNode=_parent
  52. While node=parent._right
  53. node=parent
  54. parent=parent._parent
  55. Wend
  56. Return parent
  57. End Method
  58. Method PrevNode:TNode()
  59. Local node:TNode=Self
  60. If node._left<>nil
  61. node=node._left
  62. While node._right<>nil
  63. node=node._right
  64. Wend
  65. Return node
  66. EndIf
  67. Local parent:TNode=node._parent
  68. While node=parent._left
  69. node=parent
  70. parent=node._parent
  71. Wend
  72. Return parent
  73. End Method
  74. Method Clear()
  75. _parent=Null
  76. If _left<>nil _left.Clear
  77. If _right<>nil _right.Clear
  78. End Method
  79. Method Copy:TNode( parent:TNode )
  80. Local t:TNode=New TNode
  81. t._key=_key
  82. t._value=_value
  83. t._color=_color
  84. t._parent=parent
  85. If _left<>nil t._left=_left.Copy( t )
  86. If _right<>nil t._right=_right.Copy( t )
  87. Return t
  88. End Method
  89. Method Key:Object()
  90. Return _key
  91. End Method
  92. Method Value:Object()
  93. Return _value
  94. End Method
  95. '***** PRIVATE *****
  96. Field _color,_parent:TNode=nil,_left:TNode=nil,_right:TNode=nil
  97. End Type
  98. Type TNodeEnumerator
  99. Method HasNext()
  100. Return _node<>nil
  101. End Method
  102. Method NextObject:Object()
  103. Local node:TNode=_node
  104. _node=_node.NextNode()
  105. Return node
  106. End Method
  107. '***** PRIVATE *****
  108. Field _node:TNode
  109. End Type
  110. Type TKeyEnumerator Extends TNodeEnumerator
  111. Method NextObject:Object()
  112. Local node:TNode=_node
  113. _node=_node.NextNode()
  114. Return node._key
  115. End Method
  116. End Type
  117. Type TValueEnumerator Extends TNodeEnumerator
  118. Method NextObject:Object()
  119. Local node:TNode=_node
  120. _node=_node.NextNode()
  121. Return node._value
  122. End Method
  123. End Type
  124. Type TMapEnumerator
  125. Method ObjectEnumerator:TNodeEnumerator()
  126. Return _enumerator
  127. End Method
  128. Field _enumerator:TNodeEnumerator
  129. End Type
  130. '***** PUBLIC *****
  131. Type TMap
  132. ?Not Threaded
  133. Method Delete()
  134. Clear
  135. End Method
  136. ?
  137. Method Clear()
  138. If _root=nil Return
  139. _root.Clear
  140. _root=nil
  141. End Method
  142. Method IsEmpty()
  143. Return _root=nil
  144. End Method
  145. Method Insert( key:Object,value:Object )
  146. Assert key Else "Can't insert Null key into map"
  147. Local node:TNode=_root,parent:TNode=nil,cmp
  148. While node<>nil
  149. parent=node
  150. cmp=key.Compare( node._key )
  151. If cmp>0
  152. node=node._right
  153. Else If cmp<0
  154. node=node._left
  155. Else
  156. node._value=value
  157. Return
  158. EndIf
  159. Wend
  160. node=New TNode
  161. node._key=key
  162. node._value=value
  163. node._color=RED
  164. node._parent=parent
  165. If parent=nil
  166. _root=node
  167. Return
  168. EndIf
  169. If cmp>0
  170. parent._right=node
  171. Else
  172. parent._left=node
  173. EndIf
  174. _InsertFixup node
  175. End Method
  176. Method Contains( key:Object )
  177. Return _FindNode( key )<>nil
  178. End Method
  179. Method ValueForKey:Object( key:Object )
  180. Local node:TNode=_FindNode( key )
  181. If node<>nil Return node._value
  182. End Method
  183. Method Remove( key:Object )
  184. Local node:TNode=_FindNode( key )
  185. If node=nil Return 0
  186. _RemoveNode node
  187. Return 1
  188. End Method
  189. Method Keys:TMapEnumerator()
  190. Local nodeenum:TNodeEnumerator=New TKeyEnumerator
  191. nodeenum._node=_FirstNode()
  192. Local mapenum:TMapEnumerator=New TMapEnumerator
  193. mapenum._enumerator=nodeenum
  194. Return mapenum
  195. End Method
  196. Method Values:TMapEnumerator()
  197. Local nodeenum:TNodeEnumerator=New TValueEnumerator
  198. nodeenum._node=_FirstNode()
  199. Local mapenum:TMapEnumerator=New TMapEnumerator
  200. mapenum._enumerator=nodeenum
  201. Return mapenum
  202. End Method
  203. Method Copy:TMap()
  204. Local map:TMap=New TMap
  205. map._root=_root.Copy( nil )
  206. Return map
  207. End Method
  208. Method ObjectEnumerator:TNodeEnumerator()
  209. Local nodeenum:TNodeEnumerator=New TNodeEnumerator
  210. nodeenum._node=_FirstNode()
  211. Return nodeenum
  212. End Method
  213. '***** PRIVATE *****
  214. Method _FirstNode:TNode()
  215. Local node:TNode=_root
  216. While node._left<>nil
  217. node=node._left
  218. Wend
  219. Return node
  220. End Method
  221. Method _LastNode:TNode()
  222. Local node:TNode=_root
  223. While node._right<>nil
  224. node=node._right
  225. Wend
  226. Return node
  227. End Method
  228. Method _FindNode:TNode( key:Object )
  229. Local node:TNode=_root
  230. While node<>nil
  231. Local cmp=key.Compare( node._key )
  232. If cmp>0
  233. node=node._right
  234. Else If cmp<0
  235. node=node._left
  236. Else
  237. Return node
  238. EndIf
  239. Wend
  240. Return node
  241. End Method
  242. Method _RemoveNode( node:TNode )
  243. Local splice:TNode,child:TNode
  244. If node._left=nil
  245. splice=node
  246. child=node._right
  247. Else If node._right=nil
  248. splice=node
  249. child=node._left
  250. Else
  251. splice=node._left
  252. While splice._right<>nil
  253. splice=splice._right
  254. Wend
  255. child=splice._left
  256. node._key=splice._key
  257. node._value=splice._value
  258. EndIf
  259. Local parent:TNode=splice._parent
  260. If child<>nil
  261. child._parent=parent
  262. EndIf
  263. If parent=nil
  264. _root=child
  265. Return
  266. EndIf
  267. If splice=parent._left
  268. parent._left=child
  269. Else
  270. parent._right=child
  271. EndIf
  272. If splice._color=BLACK _DeleteFixup child,parent
  273. End Method
  274. Method _InsertFixup( node:TNode )
  275. While node._parent._color=RED And node._parent._parent<>nil
  276. If node._parent=node._parent._parent._left
  277. Local uncle:TNode=node._parent._parent._right
  278. If uncle._color=RED
  279. node._parent._color=BLACK
  280. uncle._color=BLACK
  281. uncle._parent._color=RED
  282. node=uncle._parent
  283. Else
  284. If node=node._parent._right
  285. node=node._parent
  286. _RotateLeft node
  287. EndIf
  288. node._parent._color=BLACK
  289. node._parent._parent._color=RED
  290. _RotateRight node._parent._parent
  291. EndIf
  292. Else
  293. Local uncle:TNode=node._parent._parent._left
  294. If uncle._color=RED
  295. node._parent._color=BLACK
  296. uncle._color=BLACK
  297. uncle._parent._color=RED
  298. node=uncle._parent
  299. Else
  300. If node=node._parent._left
  301. node=node._parent
  302. _RotateRight node
  303. EndIf
  304. node._parent._color=BLACK
  305. node._parent._parent._color=RED
  306. _RotateLeft node._parent._parent
  307. EndIf
  308. EndIf
  309. Wend
  310. _root._color=BLACK
  311. End Method
  312. Method _RotateLeft( node:TNode )
  313. Local child:TNode=node._right
  314. node._right=child._left
  315. If child._left<>nil
  316. child._left._parent=node
  317. EndIf
  318. child._parent=node._parent
  319. If node._parent<>nil
  320. If node=node._parent._left
  321. node._parent._left=child
  322. Else
  323. node._parent._right=child
  324. EndIf
  325. Else
  326. _root=child
  327. EndIf
  328. child._left=node
  329. node._parent=child
  330. End Method
  331. Method _RotateRight( node:TNode )
  332. Local child:TNode=node._left
  333. node._left=child._right
  334. If child._right<>nil
  335. child._right._parent=node
  336. EndIf
  337. child._parent=node._parent
  338. If node._parent<>nil
  339. If node=node._parent._right
  340. node._parent._right=child
  341. Else
  342. node._parent._left=child
  343. EndIf
  344. Else
  345. _root=child
  346. EndIf
  347. child._right=node
  348. node._parent=child
  349. End Method
  350. Method _DeleteFixup( node:TNode,parent:TNode )
  351. While node<>_root And node._color=BLACK
  352. If node=parent._left
  353. Local sib:TNode=parent._right
  354. If sib._color=RED
  355. sib._color=BLACK
  356. parent._color=RED
  357. _RotateLeft parent
  358. sib=parent._right
  359. EndIf
  360. If sib._left._color=BLACK And sib._right._color=BLACK
  361. sib._color=RED
  362. node=parent
  363. parent=parent._parent
  364. Else
  365. If sib._right._color=BLACK
  366. sib._left._color=BLACK
  367. sib._color=RED
  368. _RotateRight sib
  369. sib=parent._right
  370. EndIf
  371. sib._color=parent._color
  372. parent._color=BLACK
  373. sib._right._color=BLACK
  374. _RotateLeft parent
  375. node=_root
  376. EndIf
  377. Else
  378. Local sib:TNode=parent._left
  379. If sib._color=RED
  380. sib._color=BLACK
  381. parent._color=RED
  382. _RotateRight parent
  383. sib=parent._left
  384. EndIf
  385. If sib._right._color=BLACK And sib._left._color=BLACK
  386. sib._color=RED
  387. node=parent
  388. parent=parent._parent
  389. Else
  390. If sib._left._color=BLACK
  391. sib._right._color=BLACK
  392. sib._color=RED
  393. _RotateLeft sib
  394. sib=parent._left
  395. EndIf
  396. sib._color=parent._color
  397. parent._color=BLACK
  398. sib._left._color=BLACK
  399. _RotateRight parent
  400. node=_root
  401. EndIf
  402. EndIf
  403. Wend
  404. node._color=BLACK
  405. End Method
  406. Const RED=-1,BLACK=1
  407. Field _root:TNode=nil
  408. End Type
  409. Rem
  410. bbdoc: Create a map
  411. returns: A new map object
  412. End Rem
  413. Function CreateMap:TMap()
  414. Return New TMap
  415. End Function
  416. Rem
  417. bbdoc: Clear a map
  418. about:
  419. #ClearMap removes all keys and values from @map
  420. End Rem
  421. Function ClearMap( map:TMap )
  422. map.Clear
  423. End Function
  424. Rem
  425. bbdoc: Check if a map is empty
  426. returns: True if @map is empty, otherwise false
  427. End Rem
  428. Function MapIsEmpty( map:TMap )
  429. Return map.IsEmpty()
  430. End Function
  431. Rem
  432. bbdoc: Insert a key/value pair into a map
  433. about:
  434. If @map already contained @key, it's value is overwritten with @value.
  435. End Rem
  436. Function MapInsert( map:TMap,key:Object,value:Object )
  437. map.Insert key,value
  438. End Function
  439. Rem
  440. bbdoc: Find a value given a key
  441. returns: The value associated with @key
  442. about:
  443. If @map does not contain @key, a #Null object is returned.
  444. End Rem
  445. Function MapValueForKey:Object( map:TMap,key:Object )
  446. Return map.ValueForKey( key )
  447. End Function
  448. Rem
  449. bbdoc: Check if a map contains a key
  450. returns: True if @map contains @key
  451. End Rem
  452. Function MapContains( map:TMap,key:Object )
  453. Return map.Contains( key )
  454. End Function
  455. Rem
  456. bbdoc: Remove a key/value pair from a map
  457. End Rem
  458. Function MapRemove( map:TMap,key:Object )
  459. map.Remove key
  460. End Function
  461. Rem
  462. bbdoc: Get map keys
  463. returns: An iterator object
  464. about:
  465. The object returned by #MapKeys can be used with #EachIn to iterate through
  466. the keys in @map.
  467. End Rem
  468. Function MapKeys:TMapEnumerator( map:TMap )
  469. Return map.Keys()
  470. End Function
  471. Rem
  472. bbdoc: Get map values
  473. returns: An iterator object
  474. about:
  475. The object returned by #MapValues can be used with #EachIn to iterate through
  476. the values in @map.
  477. End Rem
  478. Function MapValues:TMapEnumerator( map:TMap )
  479. Return map.Values()
  480. End Function
  481. Rem
  482. bbdoc: Copy a map
  483. returns: A copy of @map
  484. End Rem
  485. Function CopyMap:TMap( map:TMap )
  486. Return map.Copy()
  487. End Function