/src/lib/storage/internal/avl_tree.e

http://github.com/tybor/Liberty · Specman e · 552 lines · 483 code · 36 blank · 33 comment · 30 complexity · a2ba3fb5ea667d2af0675ee671738bf3 MD5 · raw file

  1. -- This file is part of a Liberty Eiffel library.
  2. -- See the full copyright at the end.
  3. --
  4. deferred class AVL_TREE[E_]
  5. --
  6. -- Definition of a mathematical set of comparable objects. All common
  7. -- operations on mathematical sets are available.
  8. --
  9. insert
  10. AVL_CONSTANTS
  11. feature {ANY}
  12. debug_string: STRING
  13. do
  14. if root = Void then
  15. Result := once "Void"
  16. else
  17. Result := tagged_out_memory
  18. Result.clear_count
  19. root.out_in_tagged_out_memory
  20. end
  21. end
  22. count: INTEGER
  23. feature {ANY} -- Adding and removing:
  24. remove (e: E_)
  25. do
  26. root := do_remove(root, e)
  27. end
  28. fast_remove (e: E_)
  29. do
  30. root := fast_do_remove(root, e)
  31. end
  32. feature {}
  33. root: like a_new_node
  34. rebalance: BOOLEAN
  35. item_memory: E_
  36. set_value_and_key (n: like a_new_node)
  37. deferred
  38. end
  39. set_value (n: like a_new_node)
  40. deferred
  41. end
  42. fast_do_insert (n: like a_new_node): like a_new_node
  43. do
  44. if n = Void then
  45. Result := new_node
  46. set_value_and_key(Result)
  47. count := count + 1
  48. map_dirty := True
  49. rebalance := True
  50. elseif item_memory = n.item then
  51. Result := n
  52. set_value(Result)
  53. rebalance := False
  54. elseif ordered(item_memory, n.item) then
  55. n.set_left(fast_do_insert(n.left))
  56. if rebalance then
  57. Result := left_grown(n)
  58. else
  59. Result := n
  60. end
  61. else
  62. check
  63. ordered(n.item, item_memory)
  64. end
  65. n.set_right(fast_do_insert(n.right))
  66. if rebalance then
  67. Result := right_grown(n)
  68. else
  69. Result := n
  70. end
  71. end
  72. ensure
  73. Result /= Void
  74. Result.balance = node_height(Result.right) - node_height(Result.left)
  75. rebalance = (node_height(Result) > old node_height(n))
  76. end
  77. do_insert (n: like a_new_node): like a_new_node
  78. do
  79. if n = Void then
  80. Result := new_node
  81. set_value_and_key(Result)
  82. count := count + 1
  83. map_dirty := True
  84. rebalance := True
  85. elseif ordered(item_memory, n.item) then
  86. n.set_left(do_insert(n.left))
  87. if rebalance then
  88. Result := left_grown(n)
  89. else
  90. Result := n
  91. end
  92. elseif ordered(n.item, item_memory) then
  93. n.set_right(do_insert(n.right))
  94. if rebalance then
  95. Result := right_grown(n)
  96. else
  97. Result := n
  98. end
  99. else
  100. check
  101. item_memory.is_equal(n.item)
  102. end
  103. Result := n
  104. set_value(Result)
  105. rebalance := False
  106. end
  107. ensure
  108. Result /= Void
  109. Result.balance = node_height(Result.right) - node_height(Result.left)
  110. rebalance = (node_height(Result) > old node_height(n))
  111. end
  112. left_grown (n: like a_new_node): like a_new_node
  113. require
  114. rebalance
  115. n /= Void
  116. node_height(n.right) - node_height(n.left) + 1 = n.balance
  117. do
  118. inspect
  119. n.balance
  120. when imbalanced_left then
  121. if n.left.balance = imbalanced_left then
  122. n.set_balance(balanced)
  123. n.left.set_balance(balanced)
  124. else
  125. inspect
  126. n.left.right.balance
  127. when imbalanced_left then
  128. n.set_balance(imbalanced_right)
  129. n.left.set_balance(balanced)
  130. when balanced then
  131. n.set_balance(balanced)
  132. n.left.set_balance(balanced)
  133. when imbalanced_right then
  134. n.set_balance(balanced)
  135. n.left.set_balance(imbalanced_left)
  136. end
  137. n.left.right.set_balance(balanced)
  138. n.set_left(n.left.rotate_left)
  139. end
  140. Result := n.rotate_right
  141. rebalance := False
  142. when balanced then
  143. n.set_balance(imbalanced_left)
  144. Result := n
  145. when imbalanced_right then
  146. n.set_balance(balanced)
  147. Result := n
  148. rebalance := False
  149. end
  150. ensure
  151. Result /= Void
  152. Result.balance = node_height(Result.right) - node_height(Result.left)
  153. rebalance = (node_height(Result) > 1 + old node_height(n.right).max(node_height(n.left) - 1))
  154. end
  155. right_grown (n: like a_new_node): like a_new_node
  156. require
  157. rebalance
  158. n /= Void
  159. node_height(n.right) - 1 - node_height(n.left) = n.balance
  160. do
  161. inspect
  162. n.balance
  163. when imbalanced_right then
  164. if n.right.balance = imbalanced_right then
  165. n.set_balance(balanced)
  166. n.right.set_balance(balanced)
  167. else
  168. inspect
  169. n.right.left.balance
  170. when imbalanced_right then
  171. n.set_balance(imbalanced_left)
  172. n.right.set_balance(balanced)
  173. when balanced then
  174. n.set_balance(balanced)
  175. n.right.set_balance(balanced)
  176. when imbalanced_left then
  177. n.set_balance(balanced)
  178. n.right.set_balance(imbalanced_right)
  179. end
  180. n.right.left.set_balance(balanced)
  181. n.set_right(n.right.rotate_right)
  182. end
  183. Result := n.rotate_left
  184. rebalance := False
  185. when balanced then
  186. n.set_balance(imbalanced_right)
  187. Result := n
  188. when imbalanced_left then
  189. n.set_balance(balanced)
  190. Result := n
  191. rebalance := False
  192. end
  193. ensure
  194. Result /= Void
  195. Result.balance = node_height(Result.right) - node_height(Result.left)
  196. rebalance = (node_height(Result) > 1 + old node_height(n.left).max(node_height(n.right) - 1))
  197. end
  198. fast_do_remove (n: like a_new_node; e: E_): like a_new_node
  199. do
  200. if n = Void then
  201. rebalance := False
  202. elseif e = n.item then
  203. if n.left = Void then
  204. Result := n.right
  205. exchange_and_discard(n, n)
  206. elseif n.right = Void then
  207. Result := n.left
  208. exchange_and_discard(n, n)
  209. else
  210. n.set_left(remove_right(n, n.left))
  211. if rebalance then
  212. Result := left_shrunk(n)
  213. else
  214. Result := n
  215. end
  216. end
  217. elseif ordered(e, n.item) then
  218. n.set_left(do_remove(n.left, e))
  219. if rebalance then
  220. Result := left_shrunk(n)
  221. else
  222. Result := n
  223. end
  224. else
  225. check
  226. ordered(n.item, e)
  227. end
  228. n.set_right(do_remove(n.right, e))
  229. if rebalance then
  230. Result := right_shrunk(n)
  231. else
  232. Result := n
  233. end
  234. end
  235. ensure
  236. Result = Void or else Result.balance = node_height(Result.right) - node_height(Result.left)
  237. rebalance = (node_height(Result) < old node_height(n))
  238. end
  239. do_remove (n: like a_new_node; e: E_): like a_new_node
  240. do
  241. if n = Void then
  242. rebalance := False
  243. elseif ordered(e, n.item) then
  244. n.set_left(do_remove(n.left, e))
  245. if rebalance then
  246. Result := left_shrunk(n)
  247. else
  248. Result := n
  249. end
  250. elseif ordered(n.item, e) then
  251. n.set_right(do_remove(n.right, e))
  252. if rebalance then
  253. Result := right_shrunk(n)
  254. else
  255. Result := n
  256. end
  257. elseif n.left = Void then
  258. Result := n.right
  259. exchange_and_discard(n, n)
  260. elseif n.right = Void then
  261. Result := n.left
  262. exchange_and_discard(n, n)
  263. else
  264. n.set_left(remove_right(n, n.left))
  265. if rebalance then
  266. Result := left_shrunk(n)
  267. else
  268. Result := n
  269. end
  270. end
  271. ensure
  272. Result = Void or else Result.balance = node_height(Result.right) - node_height(Result.left)
  273. rebalance = (node_height(Result) < old node_height(n))
  274. end
  275. remove_right (n1, n2: like a_new_node): like a_new_node
  276. require
  277. n1 /= Void
  278. n2 /= Void
  279. do
  280. if n2.right = Void then
  281. Result := n2.left
  282. exchange_and_discard(n1, n2)
  283. else
  284. n2.set_right(remove_right(n1, n2.right))
  285. if rebalance then
  286. Result := right_shrunk(n2)
  287. else
  288. Result := n2
  289. end
  290. end
  291. ensure
  292. Result = Void or else Result.balance = node_height(Result.right) - node_height(Result.left)
  293. rebalance = (node_height(Result) < old node_height(n2))
  294. end
  295. left_shrunk (n: like a_new_node): like a_new_node
  296. require
  297. rebalance
  298. n /= Void
  299. node_height(n.right) - node_height(n.left) - 1 = n.balance
  300. do
  301. inspect
  302. n.balance
  303. when imbalanced_left then
  304. n.set_balance(balanced)
  305. Result := n
  306. when balanced then
  307. n.set_balance(imbalanced_right)
  308. Result := n
  309. rebalance := False
  310. when imbalanced_right then
  311. inspect
  312. n.right.balance
  313. when imbalanced_left then
  314. inspect
  315. n.right.left.balance
  316. when imbalanced_left then
  317. n.set_balance(balanced)
  318. n.right.set_balance(imbalanced_right)
  319. when balanced then
  320. n.set_balance(balanced)
  321. n.right.set_balance(balanced)
  322. when imbalanced_right then
  323. n.set_balance(imbalanced_left)
  324. n.right.set_balance(balanced)
  325. end
  326. n.right.left.set_balance(balanced)
  327. n.set_right(n.right.rotate_right)
  328. when balanced then
  329. n.set_balance(imbalanced_right)
  330. n.right.set_balance(imbalanced_left)
  331. rebalance := False
  332. when imbalanced_right then
  333. n.set_balance(balanced)
  334. n.right.set_balance(balanced)
  335. end
  336. Result := n.rotate_left
  337. end
  338. ensure
  339. Result /= Void
  340. Result.balance = node_height(Result.right) - node_height(Result.left)
  341. rebalance = (node_height(Result) < 1 + old node_height(n.right).max(node_height(n.left) + 1))
  342. end
  343. right_shrunk (n: like a_new_node): like a_new_node
  344. require
  345. rebalance
  346. n /= Void
  347. node_height(n.right) + 1 - node_height(n.left) = n.balance
  348. do
  349. inspect
  350. n.balance
  351. when imbalanced_right then
  352. n.set_balance(balanced)
  353. Result := n
  354. when balanced then
  355. n.set_balance(imbalanced_left)
  356. Result := n
  357. rebalance := False
  358. when imbalanced_left then
  359. inspect
  360. n.left.balance
  361. when imbalanced_right then
  362. inspect
  363. n.left.right.balance
  364. when imbalanced_right then
  365. n.set_balance(balanced)
  366. n.left.set_balance(imbalanced_left)
  367. when balanced then
  368. n.set_balance(balanced)
  369. n.left.set_balance(balanced)
  370. when imbalanced_left then
  371. n.set_balance(imbalanced_right)
  372. n.left.set_balance(balanced)
  373. end
  374. n.left.right.set_balance(balanced)
  375. n.set_left(n.left.rotate_left)
  376. when balanced then
  377. n.set_balance(imbalanced_left)
  378. n.left.set_balance(imbalanced_right)
  379. rebalance := False
  380. when imbalanced_left then
  381. n.set_balance(balanced)
  382. n.left.set_balance(balanced)
  383. end
  384. Result := n.rotate_right
  385. end
  386. ensure
  387. Result /= Void
  388. Result.balance = node_height(Result.right) - node_height(Result.left)
  389. rebalance = (node_height(Result) < 1 + old node_height(n.left).max(node_height(n.right) + 1))
  390. end
  391. exchange_and_discard (n1, n2: like a_new_node)
  392. require
  393. n1 /= Void
  394. n2 /= Void
  395. deferred
  396. ensure
  397. map_dirty
  398. count = old count - 1
  399. rebalance
  400. end
  401. clear_nodes (node: like a_new_node)
  402. do
  403. if node.left /= Void then
  404. clear_nodes(node.left)
  405. end
  406. if node.right /= Void then
  407. clear_nodes(node.right)
  408. end
  409. discard_node(node)
  410. end
  411. node_height (node: like a_new_node): INTEGER
  412. do
  413. if node /= Void then
  414. Result := node.height
  415. end
  416. end
  417. feature {ANY} -- Looking and searching:
  418. has (e: E_): BOOLEAN
  419. -- Is element `e' in the set?
  420. do
  421. Result := root /= Void and then root.has(e)
  422. end
  423. fast_has (e: E_): BOOLEAN
  424. -- Is element `e' in the set?
  425. do
  426. Result := root /= Void and then root.fast_has(e)
  427. end
  428. feature {} -- Iterating internals:
  429. build_map
  430. require
  431. build_needed: map_dirty
  432. do
  433. map.clear_count
  434. if count > 0 then
  435. root.map_in(map)
  436. end
  437. map_dirty := False
  438. ensure
  439. build_done: not map_dirty
  440. end
  441. map: FAST_ARRAY[like a_new_node]
  442. -- Elements in a row for iteration. See `build_map'.
  443. map_dirty: BOOLEAN
  444. -- True when the map needs to be built again for the iterators. See
  445. -- `build_map'.
  446. feature {}
  447. new_node: like a_new_node
  448. do
  449. if lost_nodes.is_empty then
  450. Result := a_new_node
  451. else
  452. Result := lost_nodes.item
  453. end
  454. end
  455. a_new_node: AVL_TREE_NODE[E_]
  456. deferred
  457. end
  458. discard_node (n: like a_new_node)
  459. require
  460. n /= Void
  461. do
  462. lost_nodes.recycle(n)
  463. end
  464. lost_nodes: RECYCLING_POOL[like a_new_node]
  465. local
  466. key: FIXED_STRING
  467. do
  468. Result := lost_nodes_memory
  469. if Result = Void then
  470. key := generating_type.intern
  471. Result ::= lost_nodes_pool.fast_reference_at(key)
  472. if Result = Void then
  473. create Result.make
  474. lost_nodes_pool.add(Result, key)
  475. end
  476. lost_nodes_memory := Result
  477. end
  478. end
  479. lost_nodes_memory: like lost_nodes
  480. lost_nodes_pool: HASHED_DICTIONARY[RECYCLING_POOL[AVL_TREE_NODE_ANY], FIXED_STRING]
  481. once
  482. create Result.make
  483. end
  484. ordered (e1, e2: E_): BOOLEAN
  485. -- True if [e1, e2] is a correctly ordered sequence; usually, e1 < e2
  486. require
  487. e1 /= Void
  488. e2 /= Void
  489. deferred
  490. end
  491. invariant
  492. map /= Void
  493. not map_dirty implies map.count = count
  494. count > 0 implies root /= Void and then root.count = count
  495. lost_nodes /= Void
  496. end -- class AVL_TREE
  497. --
  498. -- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
  499. --
  500. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  501. -- of this software and associated documentation files (the "Software"), to deal
  502. -- in the Software without restriction, including without limitation the rights
  503. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  504. -- copies of the Software, and to permit persons to whom the Software is
  505. -- furnished to do so, subject to the following conditions:
  506. --
  507. -- The above copyright notice and this permission notice shall be included in
  508. -- all copies or substantial portions of the Software.
  509. --
  510. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  511. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  512. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  513. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  514. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  515. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  516. -- THE SOFTWARE.