DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Rational R1000/400

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦3e99c0668⟧ TextFile

    Length: 11948 (0x2eac)
    Types: TextFile
    Notes: R1k Text-file segment

Derivation

└─⟦8527c1e9b⟧ Bits:30000544 8mm tape, Rational 1000, Arrival backup of disks in PAM's R1000
    └─ ⟦cfc2e13cd⟧ »Space Info Vol 2« 
        └─⟦830a7ee75⟧ 
            └─⟦this⟧ 

TextFile

with unchecked_deallocation;

Package body Binary_Trees_Pkg is
--| Efficient implementation of binary trees.


----------------------------------------------------------------------------
			-- Local Operations --
----------------------------------------------------------------------------

procedure Free_Node is 
	new unchecked_deallocation(Node, Node_Ptr);

procedure Free_Tree is 
	new unchecked_deallocation(Tree_Header, Tree);

procedure Free_Iterator is 
	new unchecked_deallocation(Iterator_Record, Iterator);

----------------------------------------------------------------------------
			-- Visible Operations --
----------------------------------------------------------------------------

Function Create		--| Return an empty tree.
    return Tree is

begin
    return new Tree_Header'(0, Null);

end Create;

----------------------------------------------------------------------------

Procedure Insert_Node(
    V: Value_Type;
    N: in out Node_Ptr;
    Found: out boolean;
    Duplicate: out Value_Type
    ) 
is
    D: integer;

begin
    Found := False;
    if N = null then
       N := new Node'(V, Null, Null);
    else
      D := Difference(V, N.Value);
      if D < 0 then
        Insert_Node(V, N.Less, Found, Duplicate);
      elsif D > 0 then
        Insert_Node(V, N.More, Found, Duplicate);
      else
	Found := True;
	Duplicate := N.Value;
      end if;
    end if;
end Insert_Node;

Procedure Replace_Node(
    V: Value_Type;
    N: in out Node_Ptr;
    Found: out boolean;
    Duplicate: out Value_Type
    ) 
is
    D: integer;

begin
    Found := False;
    if N = null then
       N := new Node'(V, Null, Null);
    else
      D := Difference(V, N.Value);
      if D < 0 then
        Replace_Node(V, N.Less, Found, Duplicate);
      elsif D > 0 then
        Replace_Node(V, N.More, Found, Duplicate);
      else
	Found := True;
	Duplicate := N.Value;
	N.Value := V;
      end if;
    end if;
end Replace_Node;


Procedure Insert(	--| Insert a value into a tree.
    V: Value_Type;	--| Value to be inserted
    T: Tree		--| Tree to contain the new value
    ) --| Raises: Duplicate_Value, Invalid_Tree.
is
    Found: boolean;
    Duplicate: Value_Type;

begin
    if T = null then
	raise Invalid_Tree;
    end if;
    Insert_Node(V, T.Root, Found, Duplicate);
    if Found then
        raise Duplicate_Value;
    end if;
    T.Count := T.Count + 1;
end Insert;


Procedure Insert_if_not_Found(
--| Insert a value into a tree, provided a duplicate value is not already there
    V: Value_Type;	--| Value to be inserted
    T: Tree;		--| Tree to contain the new value
    Found: out boolean;
    Duplicate: out Value_Type
    ) --| Raises: Invalid_Tree.
is
    was_Found: boolean;

begin
    if T = null then
	raise Invalid_Tree;
    end if;
    Insert_Node(V, T.Root, was_Found, Duplicate);
    Found := was_Found;
    if not was_Found then
	T.Count := T.Count + 1;
    end if;

end Insert_if_Not_Found;

procedure Replace_if_Found(
--| Replace a value if label exists, otherwise insert it.
    V: Value_Type;	--| Value to be inserted
    T: Tree;		--| Tree to contain the new value
    Found: out boolean;	--| Becomes True iff L already in tree
    Old_Value: out Value_Type	--| the duplicate value, if there is one
    ) --| Raises: Invalid_Tree.

is
    was_Found: boolean;
    Duplicate: Value_Type;

begin
    if T = null then
	raise Invalid_Tree;
    end if;
    Replace_Node(V, T.Root, was_Found, Duplicate);
    Found := was_Found;
    if was_Found then
	Old_Value := Duplicate;
    else
	T.Count := T.Count + 1;
    end if;

end Replace_if_Found;

----------------------------------------------------------------------------

procedure Destroy_Nodes(
    N: in out Node_Ptr
    ) is
begin
    if N /= null then
        Destroy_Nodes(N.Less);
        Destroy_Nodes(N.More);
        Free_Node(N);
    end if;
end Destroy_Nodes;

procedure Destroy(	--| Free space allocated to a tree.
    T: in out Tree	--| The tree to be reclaimed.
    ) is

begin
    if T /= Null then
      Destroy_Nodes(T.Root);
      Free_Tree(T);
    end if;

end Destroy;

----------------------------------------------------------------------------

procedure Destroy_Deep(	--| Free all space allocated to a tree.
    T: in out Tree	--| The tree to be reclaimed.
    )
is
    procedure Destroy_Nodes(
	N: in out node_Ptr
	) is
    begin
	if N /= null then
	    Free_Value(N.Value);
            Destroy_Nodes(N.Less);
	    Destroy_Nodes(N.More);
	    Free_Node(N);
	end if;
    end Destroy_Nodes;

begin
    if T /= Null then
      Destroy_Nodes(T.Root);
      Free_Tree(T);
    end if;

end Destroy_Deep;

----------------------------------------------------------------------------

Function Balanced_Tree(	
    Count: natural
    ) return Tree

is
    new_Tree: Tree := Create;

    procedure subtree(Count: natural; N: in out Node_Ptr)
    is
	new_Node: Node_Ptr;

    begin
	if Count = 1 then
	  new_Node := new Node'(next_Value, Null, Null);
	elsif Count > 1 then
	  new_node := new Node;
	  subtree(Count/2, new_Node.Less);		-- Half are less
	  new_Node.Value := next_Value;			-- Median value
	  subtree(Count - Count/2 - 1, new_Node.More);	-- Other half are more
	end if;
	N := new_Node;
    end subtree;

begin
    new_Tree.Count := Count;
    subtree(Count, new_Tree.Root);
    return new_Tree;

end Balanced_Tree;

----------------------------------------------------------------------------

Function Copy_Tree(
    T: Tree
    ) return Tree
is
    I: Iterator;

    function next_Val return Value_type 
    is
	V: Value_Type;

    begin
	Next(I, V);
	return copy_Value(V);
    end next_Val;

    function copy_Balanced is new Balanced_Tree(next_Val);

begin
    I := Make_Iter(T);	-- Will raise Invalid_Tree if necessary
    return copy_Balanced(Size(T));

end Copy_Tree;

----------------------------------------------------------------------------

Function Is_Empty(	--| Check for an empty tree.
    T: Tree
    ) return boolean is
begin
    return T = Null or else T.Root = Null;

end Is_Empty;

----------------------------------------------------------------------------

procedure Find_Node(
    V: Value_Type;		--| Value to be located
    N: Node_Ptr;		--| subtree to be searched
    Match: out Value_Type;	--| Matching value found in the tree
    Found: out Boolean		--| TRUE iff a match was found
    )
is
    D: integer;

begin
    if N = null then
        Found := False;
	return;
    end if;
    D := Difference(V, N.Value);
    if D < 0 then
        Find_Node(V, N.Less, Match, Found);
    elsif D > 0 then
        Find_Node(V, N.More, Match, Found);
    else
        Match := N.Value;
	Found := TRUE;
    end if;
end Find_Node;

Function Find(		--| Search a tree for a value.
    V: Value_Type;	--| Value to be located
    T: Tree		--| Tree to be searched
    ) return Value_Type --| Raises: Not_Found.
is
    Found: Boolean;
    Match: Value_Type;

begin
    if T = Null then
	raise Invalid_Tree;
    end if;
    Find_Node(V, T.Root, Match, Found);
    if Found then
	return Match;
    else
	raise Not_Found;
    end if;
end Find;

Procedure Find(			--| Search a tree for a value.
    V: Value_Type;		--| Value to be located
    T: Tree;			--| Tree to be searched
    Found: out Boolean;		--| TRUE iff a match was found
    Match: out Value_Type	--| Matching value found in the tree
    ) is
begin
    if T = Null then
	raise Invalid_Tree;
    end if;
    Find_Node(V, T.Root, Match, Found);
end Find;

----------------------------------------------------------------------------

function is_Found(	--| Check a tree for a value.
    V: Value_Type;	--| Value to be located
    T: Tree		--| Tree to be searched
    ) return Boolean
is
    Found: Boolean;
    Match: Value_Type;

begin
    if T = Null then
	raise Invalid_Tree;
    end if;
    Find_Node(V, T.Root, Match, Found);
    return Found;

end is_Found;

----------------------------------------------------------------------------

function Size(		--| Return the count of values in T.
    T: Tree		--| a tree
    ) return natural is

begin
    if T = Null then
	Return 0;
    else
        Return T.Count;
    end if;

end Size;

----------------------------------------------------------------------------

procedure Visit(
    T: Tree;
    Order: Scan_Kind
    ) is

    procedure visit_Inorder(N: Node_Ptr) is
    begin
	if N.Less /= null then
	  visit_Inorder(N.Less);
	end if;
	Process(N.Value);
	if N.More /= null then
	  visit_Inorder(N.More);
	end if;
    end visit_Inorder;
 
    procedure visit_preorder(N: Node_Ptr) is
    begin
	Process(N.Value);
	if N.Less /= null then
	  visit_preorder(N.Less);
	end if;
	if N.More /= null then
	  visit_preorder(N.More);
	end if;
    end visit_preorder;
 
    procedure visit_postorder(N: Node_Ptr) is
    begin
	if N.Less /= null then
	  visit_postorder(N.Less);
	end if;
	if N.More /= null then
	  visit_postorder(N.More);
	end if;
	Process(N.Value);
    end visit_postorder;
 
begin
    if T = Null then
	raise Invalid_Tree;
    else
      case Order is
	when inorder =>
	  Visit_Inorder(T.Root);
	when preorder =>
	  Visit_preorder(T.Root);
	when postorder =>
	  Visit_postorder(T.Root);
      end case;
    end if;
end Visit;

----------------------------------------------------------------------------

function subtree_Iter(	--| Create an iterator over a subtree
    N: Node_Ptr;
    P: Iterator
    ) return Iterator is

begin
    if N = Null then
      return new Iterator_Record'(State => Done, Parent => P, subtree => N);
    elsif N.Less = Null then
      return new Iterator_Record'(State => Middle, Parent => P, subtree => N);
    else
      return new Iterator_Record'(State => Left, Parent => P, subtree => N);
    end if;

end subtree_Iter;

function Make_Iter(	--| Create an iterator over a tree
    T: Tree
    ) return Iterator is

begin
    if T = Null then
	raise Invalid_Tree;
    end if;
    return subtree_Iter(T.Root, Null);

end Make_Iter;

----------------------------------------------------------------------------

function More(		--| Test for exhausted iterator
    I: Iterator		--| The iterator to be tested
    ) return boolean is

begin
    if I = Null then
	return False;
    elsif I.Parent = Null then
	return I.State /= Done and I.subtree /= Null;
    elsif I.State = Done then
	return More(I.Parent);
    else 
	return True;
    end if;

end More;

----------------------------------------------------------------------------

procedure pop_Iterator(
    I: in out Iterator
    ) 
is
    NI: Iterator;
begin
    loop
      NI := I;
      I := I.Parent;
      Free_Iterator(NI);
      exit when I = Null;
      exit when I.State /= Done;
    end loop;
end pop_Iterator;

procedure Next(		--| Scan the next value in I
    I: in out Iterator;	--| an active iterator
    V: out Value_Type	--| Next value scanned
    ) --| Raises: No_More.
is
    NI: Iterator;

begin
    if I = Null or I.State = Done then
	raise No_More;
    end if;
    case I.State is
      when Left =>	-- Return the leftmost value
	while I.subtree.Less /= Null loop	-- Find leftmost subtree
	  I.State := Middle;	-- Middle is next at this level
	  I := subtree_Iter(I.subtree.Less, I);
	end loop;
	V := I.subtree.Value;
	if I.subtree.More /= Null then	-- There will be more...
	  I.State := Right;		-- ... coming from the right
	else				-- Nothing else here
	  pop_Iterator(I);		-- Pop up to parent iterator
	end if;
      when Middle =>
	V := I.subtree.Value;
	if I.subtree.More /= Null then	-- There will be more...
	  I.State := Right;		-- ... coming from the right
	else				-- Nothing else here so...
	  pop_Iterator(I);		-- ... Pop up to parent iterator
	end if;
      when Right =>	-- Return the value on the right
	I.State := Done;	-- No more at this level
	I := subtree_Iter(I.subtree.More, I);
	Next(I, V);
      when Done =>
	pop_Iterator(I);
	Next(I, V);
    end case;

end Next;

----------------------------------------------------------------------------


end binary_trees_pkg