/test/language/unclassified/aux_ph01_splay_dictionary.e

http://github.com/tybor/Liberty · Specman e · 568 lines · 474 code · 29 blank · 65 comment · 44 complexity · 3d74400e49a2c40b4e4b2354f95fb3b8 MD5 · raw file

  1. -- This file is part of SmartEiffel The GNU Eiffel Compiler Tools and Libraries.
  2. -- See the Copyright notice at the end of this file.
  3. --
  4. class AUX_PH01_SPLAY_DICTIONARY[E, I -> COMPARABLE]
  5. --
  6. -- An associative memory implemented as a splay tree.
  7. --
  8. -- Values of type E are stored using keys of type I (which must inherit from
  9. -- from COMPARABLE).
  10. --inherit
  11. -- ANY
  12. -- redefine
  13. -- is_equal,
  14. -- copy
  15. -- end
  16. create {ANY}
  17. make
  18. feature {ANY}
  19. make
  20. -- Initialises the tree
  21. do
  22. count := 0
  23. root := Void -- This will be the case initially
  24. end
  25. feature {ANY} -- Some queries.
  26. count: INTEGER
  27. -- The number of elements in the tree.
  28. is_empty: BOOLEAN
  29. -- Is the dictionary empty?
  30. do
  31. Result := root = Void
  32. end
  33. has (index: I): BOOLEAN
  34. -- Returns true if the passed index is contained within the tree.
  35. local
  36. tmp_node: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]
  37. do
  38. if not is_empty then
  39. from
  40. tmp_node := root
  41. until
  42. tmp_node = Void or else Result = True
  43. loop
  44. if index = tmp_node.index then
  45. -- Case 1. The indexes are the same. Therefore the Result
  46. -- is True and we bail.
  47. splay(tmp_node)
  48. Result := True
  49. elseif index < tmp_node.index then
  50. -- Case 2. The passed index is lower than the current
  51. -- node's index. We simply go left and, if we're
  52. -- not pointing at Void, splay the node to the
  53. -- top.
  54. if tmp_node.left /= Void then
  55. tmp_node := tmp_node.left
  56. else
  57. tmp_node := Void
  58. end
  59. else
  60. -- Case 3. The passed index is larger than the current
  61. -- node's index. We simply go right and, if we're
  62. -- not pointing at Void, splay the node to the
  63. -- top.
  64. if tmp_node.right /= Void then
  65. tmp_node := tmp_node.right
  66. else
  67. tmp_node := Void
  68. end
  69. end
  70. end
  71. end
  72. end
  73. lowest: I
  74. -- Returns the lowest index in the tree.
  75. require
  76. dictionary_not_empty: not is_empty
  77. local
  78. tmp_node: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]
  79. do
  80. from
  81. tmp_node := root
  82. until
  83. tmp_node.left = Void
  84. loop
  85. tmp_node := tmp_node.left
  86. end
  87. splay(tmp_node)
  88. Result := tmp_node.index
  89. end
  90. highest: I
  91. -- Returns the highest index in the tree.
  92. require
  93. dictionary_not_empty: not is_empty
  94. local
  95. tmp_node: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]
  96. do
  97. from
  98. tmp_node := root
  99. until
  100. tmp_node.right = Void
  101. loop
  102. tmp_node := tmp_node.right
  103. end
  104. splay(tmp_node)
  105. Result := tmp_node.index
  106. end
  107. feature {ANY}
  108. -- The following functions/procedures retrieve function point values or
  109. -- information concerning them.
  110. item, infix "@" (index: I): E
  111. -- Returns the value at the passed index.
  112. require
  113. has_index: has(index)
  114. local
  115. chk: BOOLEAN
  116. do
  117. -- I call `has' first even though it's in the precondition because
  118. -- there's not guarantee it'll be called (obviously). Calling this
  119. -- ensures that the required node is at the root.
  120. chk := has(index)
  121. Result := root.item
  122. end
  123. feature {ANY}
  124. new_iterator: AUX_PH01_SPLAY_DICTIONARY_ITERATOR[I]
  125. -- Returns a new iterator for the dictionary.
  126. require
  127. not_empty: not is_empty
  128. do
  129. create Result.make(Void)
  130. ensure
  131. result_not_void: Result /= Void
  132. end
  133. feature {ANY}
  134. put (value: E; index: I)
  135. require
  136. item_not_there: not has(index)
  137. local
  138. elem: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]; tmp: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]
  139. do
  140. create elem.make(value, index, Void, Void, Void)
  141. if is_empty then
  142. root := elem
  143. count := count + 1
  144. else
  145. from
  146. tmp := root
  147. until
  148. tmp = Void and then root /= Void
  149. loop
  150. check
  151. elem.index /= tmp.index
  152. end
  153. if elem.index < tmp.index then
  154. if tmp.left = Void then
  155. tmp.set_left(elem)
  156. elem.set_parent(tmp)
  157. splay(elem)
  158. count := count + 1
  159. tmp := Void
  160. else
  161. tmp := tmp.left
  162. end
  163. else
  164. if tmp.right = Void then
  165. tmp.set_right(elem)
  166. elem.set_parent(tmp)
  167. splay(elem)
  168. count := count + 1
  169. tmp := Void
  170. else
  171. tmp := tmp.right
  172. end
  173. end
  174. end
  175. end
  176. ensure
  177. count_has_incremented: count = old count + 1
  178. end
  179. replace (value: E; index: I)
  180. require
  181. has_index: has(index)
  182. do
  183. if has(index) then
  184. if index = root.index then
  185. root.set_item(value)
  186. end
  187. end
  188. end
  189. remove (index: I)
  190. require
  191. has_index: has(index)
  192. local
  193. left: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]; right: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]
  194. tmp: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]
  195. do
  196. if has(index) then
  197. if root.right /= Void and root.left /= Void then
  198. left := root.left
  199. right := root.right
  200. tmp := lowest_node_in_subtree(right)
  201. tmp.set_left(left)
  202. left.set_parent(tmp)
  203. right.set_parent(Void)
  204. root := right
  205. elseif root.right /= Void then
  206. right := root.right
  207. right.set_parent(Void)
  208. root := right
  209. elseif root.left /= Void then
  210. left := root.left
  211. left.set_parent(Void)
  212. root := left
  213. else
  214. root := Void
  215. end
  216. count := count - 1
  217. end
  218. ensure
  219. count_updated: count = old count - 1
  220. end
  221. remove_maximum
  222. require
  223. not_empty: not is_empty
  224. local
  225. tmp: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]; left: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]
  226. do
  227. tmp := highest_node_in_subtree(root)
  228. left := tmp.left
  229. if left /= Void then
  230. left.set_parent(Void)
  231. root := left
  232. else
  233. root := Void
  234. end
  235. count := count - 1
  236. ensure
  237. count_updated: count = old count - 1
  238. end
  239. remove_minimum
  240. require
  241. not_empty: not is_empty
  242. local
  243. tmp: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]; right: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]
  244. do
  245. tmp := lowest_node_in_subtree(root)
  246. right := tmp.right
  247. if right /= Void then
  248. right.set_parent(Void)
  249. root := right
  250. else
  251. root := Void
  252. end
  253. count := count - 1
  254. ensure
  255. count_updated: count = old count - 1
  256. end
  257. clear
  258. do
  259. from
  260. until
  261. root = Void
  262. loop
  263. remove_minimum
  264. end
  265. end
  266. feature {ANY}
  267. print_tree
  268. do
  269. if root /= Void then
  270. print_subtree(root.left)
  271. root.index.print_on(std_output)
  272. print(" ")
  273. root.item.print_on(std_output)
  274. print("%N")
  275. print_subtree(root.right)
  276. end
  277. end
  278. feature {AUX_PH01_SPLAY_DICTIONARY_ITERATOR}
  279. lowest_node: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]
  280. require
  281. not_empty: not is_empty
  282. do
  283. Result := lowest_node_in_subtree(root)
  284. splay(Result)
  285. ensure
  286. result_not_void: Result /= Void
  287. end
  288. highest_node: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]
  289. require
  290. not_empty: not is_empty
  291. do
  292. Result := highest_node_in_subtree(root)
  293. splay(Result)
  294. ensure
  295. result_not_void: Result /= Void
  296. end
  297. next_highest (node: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]): AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]
  298. require
  299. not_empty: not is_empty
  300. do
  301. splay(node)
  302. if root.right /= Void then
  303. Result := lowest_node_in_subtree(root.right)
  304. splay(Result)
  305. end
  306. end
  307. feature {INDEXED_LIST}
  308. lowest_node_in_subtree (node: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]): AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]
  309. require
  310. node_not_void: node /= Void
  311. local
  312. elem: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]
  313. do
  314. from
  315. elem := node
  316. until
  317. elem = Void
  318. loop
  319. if elem.left = Void then
  320. Result := elem
  321. elem := Void
  322. else
  323. elem := elem.left
  324. end
  325. end
  326. ensure
  327. result_not_void: Result /= Void
  328. end
  329. highest_node_in_subtree (node: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]): AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]
  330. require
  331. node_not_void: node /= Void
  332. local
  333. elem: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]
  334. do
  335. from
  336. elem := node
  337. until
  338. elem = Void
  339. loop
  340. if elem.right = Void then
  341. Result := elem
  342. elem := Void
  343. else
  344. elem := elem.right
  345. end
  346. end
  347. ensure
  348. result_not_void: Result /= Void
  349. end
  350. print_subtree (node: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I])
  351. do
  352. if node /= Void then
  353. if node.left /= Void then
  354. print_subtree(node.left)
  355. end
  356. node.index.print_on(std_output)
  357. print(" ")
  358. node.item.print_on(std_output)
  359. print("%N")
  360. if node.right /= Void then
  361. print_subtree(node.right)
  362. end
  363. end
  364. end
  365. feature {}
  366. has_tree_integrity: BOOLEAN
  367. local
  368. tmp_node: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]
  369. do
  370. if is_empty then
  371. Result := True
  372. else
  373. from
  374. tmp_node := lowest_node_in_subtree(root)
  375. Result := True
  376. until
  377. tmp_node = Void or else Result = False
  378. loop
  379. if (tmp_node.left = Void or else tmp_node.left.index < tmp_node.index) and then (tmp_node.right = Void or else tmp_node.right.index > tmp_node.index) then
  380. if tmp_node.parent = Void then
  381. if tmp_node /= root then
  382. Result := False
  383. else
  384. if tmp_node.right = Void then
  385. tmp_node := Void
  386. else
  387. tmp_node := lowest_node_in_subtree(tmp_node.right)
  388. splay(tmp_node)
  389. end
  390. end
  391. elseif tmp_node.parent.left = tmp_node then
  392. if tmp_node.right = Void then
  393. tmp_node := tmp_node.parent
  394. else
  395. tmp_node := lowest_node_in_subtree(tmp_node.right)
  396. splay(tmp_node)
  397. end
  398. elseif tmp_node.parent.right = tmp_node then
  399. if tmp_node.right /= Void then
  400. tmp_node := lowest_node_in_subtree(tmp_node.right)
  401. splay(tmp_node)
  402. else
  403. tmp_node := Void
  404. end
  405. else
  406. Result := False
  407. end
  408. else
  409. Result := False
  410. end
  411. end
  412. end
  413. end
  414. feature {INDEXED_LIST}
  415. splay (node: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I])
  416. require
  417. node_not_void: node /= Void
  418. local
  419. parent: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]
  420. do
  421. from
  422. until
  423. node = root
  424. loop
  425. if node.parent = root then
  426. -- In this case we only need to zig.
  427. parent := node.parent
  428. if node = parent.left then
  429. rotate_right(node)
  430. else
  431. rotate_left(node)
  432. end
  433. root := node -- Make sure root is update!
  434. elseif node = node.parent.left then
  435. if node.parent = node.parent.parent.right then
  436. rotate_right(node)
  437. rotate_left(node)
  438. else
  439. rotate_right(node.parent)
  440. rotate_right(node)
  441. end
  442. if node.parent = Void then
  443. -- Make sure to update the root if
  444. -- necessary.
  445. root := node
  446. end
  447. elseif node = node.parent.right then
  448. if node.parent = node.parent.parent.left then
  449. rotate_left(node)
  450. rotate_right(node)
  451. elseif node.parent = node.parent.parent.right then
  452. rotate_left(node.parent)
  453. rotate_left(node)
  454. end
  455. if node.parent = Void then
  456. -- Make sure to update the root if
  457. -- necessary.
  458. root := node
  459. end
  460. end
  461. end
  462. end
  463. rotate_right (node: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I])
  464. require
  465. node_not_null: node /= Void
  466. local
  467. parent: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]
  468. do
  469. parent := node.parent
  470. parent.set_left(node.right)
  471. if node.right /= Void then
  472. node.right.set_parent(parent)
  473. end
  474. if parent.parent = Void then
  475. node.set_parent(Void)
  476. else
  477. node.set_parent(parent.parent)
  478. if parent = parent.parent.left then
  479. parent.parent.set_left(node)
  480. else
  481. parent.parent.set_right(node)
  482. end
  483. end
  484. node.set_right(parent)
  485. parent.set_parent(node)
  486. end
  487. rotate_left (node: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I])
  488. require
  489. node_not_null: node /= Void
  490. local
  491. parent: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I]
  492. do
  493. parent := node.parent
  494. parent.set_right(node.left)
  495. if node.left /= Void then
  496. node.left.set_parent(parent)
  497. end
  498. if parent.parent = Void then
  499. node.set_parent(Void)
  500. else
  501. node.set_parent(parent.parent)
  502. if parent = parent.parent.left then
  503. parent.parent.set_left(node)
  504. else
  505. parent.parent.set_right(node)
  506. end
  507. end
  508. node.set_left(parent)
  509. parent.set_parent(node)
  510. end
  511. feature {AUX_PH01_SPLAY_DICTIONARY}
  512. root: AUX_PH01_SPLAY_DICTIONARY_ITEM[E, I] -- references the root of the tree.
  513. invariant
  514. root_null_no_count_integrity: root = Void implies count = 0 and root /= Void implies count /= 0
  515. count_valid: count >= 0
  516. -- The following invariant is very heavy-duty. I've already tried it
  517. -- and it seems to be ok so I'm commentint it out now. If I make any
  518. -- more serious changes to this class I'll uncomment this invariant
  519. -- and use it until I'm happy.
  520. -- dictionary_has_integrity : has_tree_integrity
  521. end -- class AUX_PH01_SPLAY_DICTIONARY
  522. --
  523. -- ------------------------------------------------------------------------------------------------------------------------------
  524. -- Copyright notice below. Please read.
  525. --
  526. -- SmartEiffel is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License,
  527. -- as published by the Free Software Foundation; either version 2, or (at your option) any later version.
  528. -- SmartEiffel is distributed in the hope that it will be useful but WITHOUT ANY WARRANTY; without even the implied warranty
  529. -- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have
  530. -- received a copy of the GNU General Public License along with SmartEiffel; see the file COPYING. If not, write to the Free
  531. -- Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
  532. --
  533. -- Copyright(C) 1994-2002: INRIA - LORIA (INRIA Lorraine) - ESIAL U.H.P. - University of Nancy 1 - FRANCE
  534. -- Copyright(C) 2003-2006: INRIA - LORIA (INRIA Lorraine) - I.U.T. Charlemagne - University of Nancy 2 - FRANCE
  535. --
  536. -- Authors: Dominique COLNET, Philippe RIBET, Cyril ADRIAN, Vincent CROIZIER, Frederic MERIZEN
  537. --
  538. -- http://SmartEiffel.loria.fr - SmartEiffel@loria.fr
  539. -- ------------------------------------------------------------------------------------------------------------------------------