PageRenderTime 23ms CodeModel.GetById 17ms app.highlight 2ms RepoModel.GetById 1ms app.codeStats 1ms

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