tree_nodes.sa


Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
 
------------------------->  GNU Sather - sourcefile  <-------------------------
-- Copyright (C) 2000 by K Hopper, University of Waikato, New Zealand        --
-- This file is part of the GNU Sather library. It is free software; you may --
-- redistribute  and/or modify it under the terms of the GNU Library General --
-- Public  License (LGPL)  as published  by the  Free  Software  Foundation; --
-- either version 2 of the license, or (at your option) any later version.   --
-- This  library  is distributed  in the  hope that it will  be  useful, but --
-- WITHOUT ANY WARRANTY without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See Doc/LGPL for more details.       --
-- The license text is also available from:  Free Software Foundation, Inc., --
-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                     --
-------------->  Please email comments to <bug-sather@gnu.org>  <--------------


abstract class $BT_NODE{ KEY < $IS_LT{KEY}, ETP,

abstract class $BT_NODE{ KEY < $IS_LT{KEY}, ETP, NODE < $BT_NODE{KEY,ETP,NODE} } is -- This abstraction is for a standard balanced tree node. It provides -- all of the expected operations. -- Version 1.1 Mar 97. Copright K Hopper, U of Waikato -- Development History -- ------------------- -- Date Who By Detail -- ---- ------ ------ -- 22 Mar 95 hk Original -- 13 Mar 97 kh Changed to CARD from INT create : SAME ; -- This routine creates an empty tree node. create( pair : TUP{KEY,ETP} ) : SAME ; -- This creates a new node with the given key and data element. is_eq( other : NODE ) : BOOL ; -- This predicate returns true if and only if self and other are equal, -- otherwise false. aget( key : CARD ) : BT_NELEM{KEY,ETP,NODE} ; -- This routine returns the node element 'indexed' by the key provided. size : CARD ; Min_Size : CARD ; Max_Size : CARD ; -- These three merely return properties of the node itself set_item( pos : CARD, pair : TUP{KEY,ETP} ) ; -- This routine sets the node in the given position to have the value -- of pair. set_node( pos : CARD, node : NODE ) ; -- This routine sets the node in the given position to have the value -- of node. -- The following pairs of routines are used in testing node properties and insertion and deletion on the left (respectively right) node elements. -- -- Free tests if the siblings have unused 'slots' -- -- Spare tests if the siblings have spare (ie void) 'slots' -- -- Push inserts space for a node into the balanced tree. -- -- Pull deletes a node space from the tree. -- -- Join attaches a sub-tree to the current node. left_free( stack : A_STACK{TUP{CARD,NODE}} ) : BOOL ; right_free( stack : A_STACK{TUP{CARD,NODE}} ) : BOOL ; left_spare( stack : A_STACK{TUP{CARD,NODE}} ) : BOOL ; right_spare( stack : A_STACK{TUP{CARD,NODE}} ) : BOOL ; push_left( elem : NODE, pos : CARD, stack:A_STACK{TUP{CARD,NODE}} ) ; push_right( elem : NODE, pos : CARD, stack : A_STACK{TUP{CARD,NODE}} ) ; pull_left( pos : CARD, stack : A_STACK{TUP{CARD,NODE}} ) ; pull_right( pos : CARD, stack : A_STACK{TUP{CARD,NODE}} ) ; join_left( pos : CARD, stack : A_STACK{TUP{CARD,NODE}} ) ; join_right( pos : CARD, stack : A_STACK{TUP{CARD,NODE}} ) ; split( elem : NODE, pos : CARD ) : NODE ; -- This routine splits self into two sub-trees, building a sub-tree -- on the given element, which is then returned. node_insert( node : NODE, pos : CARD ) ; -- This routine carries out an actual insertion of the given node at the -- position indicated. node_delete( pos : CARD ) ; -- This routine deletes the node at the indicated position, rebalancing -- the tree as necessary. find_pred( stack : A_STACK{TUP{CARD,NODE}} ) ; -- This routine alters the stack so that the predecssor of the stack top -- is at the top of the stack on exit. find( key : KEY, stack :A_STACK{TUP{CARD,NODE}} ) : BOOL ; -- This routine attempts to find the element with the given key. If it -- is found it is on the top of the stack and true is returned, otherwise -- false is returned. ind! : KEY ; -- This iter yields a sequence of the keys in the tree in order. elt! : ETP ; -- This iter yields a sequence of the node values on the tree in order. pair! : TUP{KEY,ETP} ; -- This iter yields the key/value pairs on the tree in order. end ; -- $BT_NODE

immutable class BT_NELEM{KEY<$IS_LT{KEY}, ELT,

immutable class BT_NELEM{KEY<$IS_LT{KEY}, ELT, NODE < $BT_NODE{ KEY, ELT, NODE } } is -- This class is defined for internal use in BT_NODE to store nodes -- and items efficiently. -- Version 1.1 Mar 97. Copright K Hopper, U of Waikato -- Development History -- ------------------- -- Date Who By Detail -- ---- ------ ------ -- 22 Mar 95 hk Original -- 13 Mar 97 kh Changed for style attr node : NODE ; attr item : TUP{ KEY, ELT } ; create( nod : NODE, obj : TUP{KEY,ELT} ) : SAME is -- This routine creates a new node element. return node(nod).item(obj) end ; end ; -- BT_NELEM

class BT_NODE{ KEY < $IS_LT{KEY}, ELT } <

class BT_NODE{ KEY < $IS_LT{KEY}, ELT } < $BT_NODE{KEY,ELT,BT_NODE{KEY,ELT}} is -- This class is defined for internal use within the balanced tree -- implementation. It is used to represent both the root and all other -- internal nodes. The general structure of a node is -- -- [0].node [0].item [1].node [1].item ... [k].node [k].item [k+1].node -- ([k+1].item is always unused) -- Version 1.2 Nov 98. Copyright K Hopper, U of Waikato -- Development History -- ------------------- -- Date Who By Detail -- ---- ------ ------ -- 22 Mar 95 hk Original -- 13 Jan 97 kh Changed to CARD from INT -- 12 Nov 98 kh Revised for 1.2, added pre/post conditions. include AREF{BT_NELEM{KEY,ELT,SAME}} aset->private aset ; -- The array of items and nodes. attr size : CARD ; -- This attribute gives the current 'fill ratio' of the node. const Max_Size : CARD := 4 ; -- This constant gives the maximum number of element tuples at a node. -- It must be EVEN and greater than 2! const Min_Size : CARD := Max_Size / 2 ; create : SAME is -- This routine creates a new node with one more elements than Max_Size! return new(Max_Size + 1) end ; create( tuple : TUP{KEY,ELT} ) : SAME is -- This routine creates a new node which contains the given key/element -- tuple. me : SAME := new(Max_Size + 1) ; me.set_item(0, tuple) ; me.size := 1 ; return me end ; is_eq( other : SAME ) : BOOL is -- This predicate returns true if and only if self and same are -- identical. return SYS::ob_eq(self,other) end ; set_item( pos : CARD, tuple : TUP{KEY,ELT} ) pre ~void(self) and (pos <= Max_Size) post true is -- This routine sets the indicated element of the array to have the -- given node key/value pair. [pos] := [pos].item(tuple) end ; set_node( pos : CARD, node : SAME ) pre ~void(self) and (pos <= Max_Size) post true is -- This routine sets the indicated node to be node. [pos] := [pos].node(node) end ; left_free( stack : A_STACK{TUP{CARD,SAME}} ) : BOOL pre ~void(stack.top) and (stack.top.t2 /= self) post true is -- This predicate returns true if and only if there is space for -- additional nodes to the left. parent : TUP{CARD,SAME} := stack.top ; return (parent.t1 > 0) and (parent.t2[parent.t1 - 1].node.size < Max_Size) end ; right_free( stack : A_STACK{TUP{CARD,SAME}} ) : BOOL pre ~void(stack.top) and (stack.top.t2 /= self) post true is -- This predicate returns true if and only if there is space for -- additional nodes to the right. parent : TUP{CARD,SAME} := stack.top ; return (parent.t1 < parent.t2.size) and (parent.t2[parent.t1 + 1].node.size < Max_Size) end ; left_spare( stack : A_STACK{TUP{CARD,SAME}} ) : BOOL pre ~void(stack.top) and (stack.top.t2 /= self) post true is -- This predicate returns true if and only if the left sibling has spare -- space. parent : TUP{CARD,SAME} := stack.top ; return (parent.t1 > 0) and (parent.t2[parent.t1-1].node.size > Min_Size) end ; right_spare( stack : A_STACK{TUP{CARD,SAME}} ) : BOOL pre ~void(stack.top) and (stack.top.t2 /= self) post true is -- This predicate returns true if and only if the right sibling has spare -- space. parent : TUP{CARD,SAME} := stack.top ; return (parent.t1 < parent.t2.size) and (parent.t2[parent.t1 + 1].node.size > Min_Size) end ; push_left( elem : SAME, pos : CARD, stack : A_STACK{TUP{CARD,SAME}} ) pre ~void(self) and (size = Max_Size) post true --- ????????? is -- This routine inserts the given element at the indicated position in -- stack. parent, left : SAME ; index, ppos : CARD ; parent := stack.top.t2 ; ppos := stack.top.t1 ; left := parent[ppos - 1].node ; left.set_item(left.size,parent[ppos - 1].item ) ; if pos = 0 then -- item goes up left.set_node(left.size + 1,elem[0].node) ; parent.set_item(ppos - 1,elem[0].item) ; set_node(0,elem[1].node) else -- item[0] goes up, insert item parent.set_item(ppos - 1,[0].item) ; left.set_node(left.size + 1,[0].node) ; loop -- Move the rest down one index := 0.upto!(pos - 2) ; [index] := [index + 1] end ; [pos - 1] := elem[0] ; -- attach the given element set_node(pos,elem[1].node) end ; left.size := left.size + 1 -- adjust tree size. end ; push_right( elem : SAME, pos : CARD, stack : A_STACK{TUP{CARD,SAME}} ) pre ~void(self) and (size = Max_Size) post true -- ?????????? is -- This routine inserts the given element at the indicated position in -- stack. parent, right : SAME ; index, ppos : CARD ; parent := stack.top.t2 ; ppos := stack.top.t1 ; right := parent[ppos + 1].node ; loop -- move up, creating needed space index := right.size.downto!(0) ; right[index + 1] := right[index] end ; right.set_item(0,parent[ppos].item ) ; -- Put it in! if pos = size then -- item goes up parent.set_item(ppos,elem[0].item) ; set_node(size,elem[0].node) ; right.set_node(0,elem[1].node) else -- last goes up, item inserted. parent.set_item(ppos,[size - 1].item) ; right.set_node(0,[size].node) ; set_node(size,[size - 1].node) ; loop -- move up index := (size - 2).downto!(pos) ; [index + 1] := [index] end ; [pos] := elem[0] ; set_node(pos + 1,elem[1].node) end ; right.size := right.size + 1 -- adjust size end ; split( elem : SAME, pos : CARD ) : SAME pre ~void(self) and (size = Max_Size) post true ---????????????? is -- This routine splits the array at the indicated position, attaching -- the portion split off to elem, which is then returned. index : CARD ; newNode : SAME := create ; if pos <= Min_Size then -- item does not go right loop -- to move sub-tree to newNode index := Min_Size.upto!(size) ; newNode[index - Min_Size] := [index] ; [index] := void end ; if pos = Min_Size then -- item goes up newNode.set_node(0,elem[1].node) ; set_node(Min_Size,elem[0].node) else -- item stays left loop -- so move self up the array. index := Min_Size.downto!(pos + 1) ; [index] := [index - 1] end ; [pos] := elem[0] ; -- put it into place in self set_node(pos + 1,elem[1].node) ; elem.set_item(0,[Min_Size].item) ; set_item(Min_Size,void) -- clear links in self end else -- item goes right loop -- to fill elem index := size.downto!(pos) ; newNode[index - Min_Size] := [index] ; [index] := void -- discard from self! end ; newNode.set_node(pos - Min_Size,elem[1].node) ; newNode[pos - Min_Size - 1] := elem[0] ; loop -- insert remainder in newNode index := (pos - 1).downto!(Min_Size + 1) ; newNode[index - Min_Size - 1] := [index] ; [index] := void -- and clear from self! end ; elem.set_item(0,[Min_Size].item) ; -- establish 'root' set_item(Min_Size,void) end ; size := Min_Size ; newNode.size := Min_Size ; elem.set_node(0,self) ; -- generate new node to insert elem.set_node(1,newNode) ; assert elem.size = 1 ; return elem end ; node_insert( node : SAME, pos : CARD ) pre ~void(self) and (pos <= Max_Size) and (size < Max_Size) post true -- ?????????????? is -- This routine inserts the given node at the indicated position. index : CARD ; loop index := size.downto!(pos) ; [index + 1] := [index] end ; [pos] := node[0] ; set_node(pos + 1, node[1].node) ; size := size + 1 end ; pull_left( pos : CARD, stack : A_STACK{TUP{CARD,SAME}} ) pre ~void(stack) and ~void(self) post true -- ???????????????? is -- This routine pulls the indicated element out of the stack LHS. parent, left : SAME ; index, ppos : CARD ; parent := stack.top.t2 ; ppos := stack.top.t1 ; left := parent[ppos - 1].node ; loop -- Move hole to LH end index := pos.downto!(1) ; [index] := [index - 1] end ; set_item(0,parent[ppos - 1].item) ; -- get from parent set_node(0, left[size].node) ; parent.set_item(ppos - 1,left[left.size - 1].item) ; -- refill parent left[left.size] := void ; -- leave to garbage collector left.set_item(left.size - 1,void) ; left.size := left.size - 1 end ; pull_right( pos : CARD, stack : A_STACK{TUP{CARD,SAME}} ) pre ~void(stack) and ~void(self) post true -- ??????????????? is -- This routine pulls the indicated element out of the stack RHS. parent, right : SAME ; index, ppos : CARD ; parent := stack.top.t2 ; ppos := stack.top.t1 ; right := parent[ppos + 1].node ; loop index := pos.upto!(size - 1) ; -- Close hole. [index] := [index + 1] end ; set_item(size - 1,parent[ppos].item) ; -- Get right end from parent. set_node(size,right[0].node) ; parent.set_item(ppos,right[0].item) ; loop index := 1.upto!(right.size) ; right[index - 1] := right[index] end ; right[right.size] := void ; -- for garbage collector right.size := right.size - 1 end ; join_left( pos : CARD, stack : A_STACK{TUP{CARD,SAME}} ) pre ~void(stack) and ~void(self) and (size = Min_Size) post true -- ???????????????? is -- This routine makes a hole for the insertion of the left sibling. parent, left : SAME ; index, ppos : CARD ; parent := stack.top.t2 ; ppos := stack.top.t1 ; left := parent[ppos - 1].node ; assert left.size = Min_Size ; loop -- Move hole to the left. index := pos.downto!(1) ; [index] := [index - 1] end ; set_node(0,left[left.size].node) ; -- Get from parent. set_item(0,parent[ppos - 1].item) ; loop -- Make BIG hole for left sibling index := size.downto!( 0 ) ; [index + Min_Size] := [index] -- [index + left.size] := [index] end ; loop -- put it in index := 0.upto!(Min_Size - 1) ; [index] := left[index] end ; parent.set_node(ppos - 1,self) ; parent.set_item(ppos - 1,parent[ppos].item) ; size := Max_Size end ; join_right( pos : CARD, stack : A_STACK{TUP{CARD,SAME}} ) pre ~void(stack) and ~void(self) and (size = Min_Size) post true -- ???????????????? is -- This routine makes a hole for the insertion of the right sibling. parent, right : SAME ; index, ppos : CARD ; parent := stack.top.t2 ; ppos := stack.top.t1 ; right := parent[ppos + 1].node ; assert right.size = Min_Size ; loop -- Close hole index := (pos + 1).upto!(size) ; [index - 1] := [index] end ; set_item(size - 1,parent[ppos].item) ; -- Get from parent loop -- Do joining index := 0.upto!(right.size) ; [size + index] := right[index] end ; parent.set_node(ppos + 1,self) ; size := Max_Size end ; node_delete( pos : CARD ) pre ~void(self) and (pos <= Max_Size) post (size = initial(size - 1)) is -- This routine is the one which actually deletes (removes) a node, -- leaving the space for reclamation by the garbage collector. index : CARD ; loop index := pos.upto!(size - 1) ; [index] := [index + 1] end ; [size] := void ; size := size - 1 end ; find_pred( stack : A_STACK{TUP{CARD,SAME}} ) pre ~void(stack) and ~void(self) post true -- ??????????? is -- This routine follows the link to the predecessor, which it then -- leaves on the top of the stack. node : SAME := stack.top.t2[stack.top.t1].node ; loop until!(void(node)) ; stack.push(TUP{CARD,SAME}::create(node.size,node)) ; node := node[node.size].node end end ; find( key : KEY, stack : A_STACK{TUP{CARD,SAME}} ) : BOOL pre ~void(stack) and ~void(self) post true is -- This predicate returns true if and only if a node with the given key -- is present in the stack, otherwise false. If the node is present then it -- is at the top of the stack. if void(self) then return false end ; loop index : CARD := 0.upto!(size - 1) ; if [index].item.t1 = key then stack.push(TUP{CARD,SAME}::create(index,self)) ; return true elsif key < [index].item.t1 then stack.push(TUP{CARD,SAME}::create(index,self)) ; return ~void([index].node) and [index].node.find(key,stack) end end ; stack.push(TUP{CARD,SAME}::create(size,self)) ; return ~void([size].node) and [size].node.find(key,stack) end ; ind! : KEY pre true post true is -- This iter yields all of the individual key values in sequence. if ~void(self) then loop index : CARD := 0.upto!(size) ; loop yield [index].node.ind! end ; if ~void([index].item) then yield [index].item.t1 end end end end ; elt! : ELT pre true post true is -- This iter yields successive values of the node values in the tree. if ~void(self) then loop index : CARD := 0.upto!(size) ; loop yield [index].node.elt! end ; if ~void([index].item) then yield [index].item.t2 end end end end ; pair! : TUP{KEY,ELT} pre true post true is -- This iter yields successive values of the node key/value pairs in -- the tree. if ~void(self) then loop index : CARD := 0.upto!(size) ; loop yield [index].node.pair! end ; if ~void([index].item) then yield [index].item end end end end ; end ; -- BT_NODE