This site contains older material on Eiffel. For the main Eiffel page, see http://www.eiffel.com.

EiffelBase class
(HTML page generated by ISE Eiffel 4.2)

Eiffel Class
indexing
	description: "Binary search trees; left child item is less than current item, right child item is greater";
	status: "See notice at end of class";
	names: binary_search_tree, tree;
	representation: recursive, array;
	access: cursor, membership;
	contents: generic;
	date: "$Date: 2007-03-30 11:10:11 -0800 (Fri, 30 Mar 2007) $";
	revision: "$Revision: 95354 $"

class BINARY_SEARCH_TREE [G -> COMPARABLE]

inherit
	BINARY_TREE [G]
		rename
			make as bt_make,
			put as bt_put
		export
			{BINARY_SEARCH_TREE} put_left_child, put_right_child, remove_left_child, remove_right_child
		redefine
			parent, has
		end

creation
	make

feature -- Initialization

	make (v: like item) is
			-- Create single node with item v.
		do
			bt_make (v)
		ensure
			node_item: item = v;
			no_child: (left_child = void) and (right_child = void)
		end;

feature -- Access

	parent: BINARY_SEARCH_TREE [G];
			-- Parent of current node

	has (v: like item): BOOLEAN is
			-- Does tree contain a node whose item
			-- is equal to v (object comparison)?
		require
			argument_not_void: v /= void
		do
			if v.is_equal (item) then
				Result := true
			elseif v < item then
				Result := (left_child /= void) and then left_child.has (v)
			else
				Result := (right_child /= void) and then right_child.has (v)
			end
		end;

feature -- Measurement

	min: like item is
			-- Minimum item in tree
		do
			if has_left then
				Result := left_child.min
			else
				Result := item
			end
		ensure
			minimum_present: has (Result)
		end;

	max: like item is
			-- Maximum item in tree
		do
			if has_right then
				Result := right_child.max
			else
				Result := item
			end
		ensure
			maximum_present: has (Result)
		end;

feature -- Status report

	sorted: BOOLEAN is
			-- Is tree sorted?
		do
			Result := true;
			if (has_left and then left_item > item) or (has_right and then right_item < item) then
				Result := false
			else
				if has_left then
					Result := left_child.sorted_and_less (item)
				end;
				if has_right and Result then
					Result := right_child.sorted
				end
			end
		end;

	sorted_and_less (i: like item): BOOLEAN is
			-- Is tree sorted and all its elements less then i
		do
			Result := true;
			if (has_left and then left_item > item) or (has_right and then right_item < item) then
				Result := false
			else
				if has_left then
					Result := left_child.sorted_and_less (item)
				end;
				if has_right and Result then
					Result := right_child.sorted_and_less (i)
				end
			end
		end;

feature -- Cursor movement

	node_action (v: like item) is
			-- Operation on node item,
			-- to be defined by descendant classes.
			-- Here it is defined as an empty operation.
			-- Redefine this procedure in descendant classes if useful
			-- operations are to be performed during traversals.
		do
		end;

	preorder is
			-- Apply node_action to every node's item
			-- in tree, using pre-order.
		do
			node_action (item);
			if left_child /= void then
				left_child.preorder
			end;
			if right_child /= void then
				right_child.preorder
			end
		end;

	i_infix is
			-- Apply node_action to every node's item
			-- in tree, using infix order.
		do
			if left_child /= void then
				left_child.i_infix
			end;
			node_action (item);
			if right_child /= void then
				right_child.i_infix
			end
		end;

	postorder is
			-- Apply node_action to every node's item
			-- in tree, using post-order.
		do
			if left_child /= void then
				left_child.postorder
			end;
			if right_child /= void then
				right_child.postorder
			end;
			node_action (item)
		end;

feature -- Element change

	put (v: like item) is
			-- Put v at proper position in tree
			-- (unless v exists already).
			-- (Reference or object equality,
			-- based on object_comparison.)
			-- Was declared in BINARY_SEARCH_TREE as synonym of put and extend.
		require
			new_item_exists: v /= void
		do
			if v /= item then
				if v < item then
					if left_child = void then
						put_left_child (new_tree);
						left_child.replace (v)
					else
						left_child.put (v)
					end
				else
					if right_child = void then
						put_right_child (new_tree);
						right_child.replace (v)
					else
						right_child.put (v)
					end
				end
			end
		ensure
			item_inserted: has (v)
		end;

	extend (v: like item) is
			-- Put v at proper position in tree
			-- (unless v exists already).
			-- (Reference or object equality,
			-- based on object_comparison.)
			-- Was declared in BINARY_SEARCH_TREE as synonym of put and extend.
		require
			new_item_exists: v /= void
		do
			if v /= item then
				if v < item then
					if left_child = void then
						put_left_child (new_tree);
						left_child.replace (v)
					else
						left_child.put (v)
					end
				else
					if right_child = void then
						put_right_child (new_tree);
						right_child.replace (v)
					else
						right_child.put (v)
					end
				end
			end
		ensure
			item_inserted: has (v)
		end;

feature -- Transformation

	sort is
			-- Sort tree.
		local
			seq: LINEAR [G];
			temp: ARRAY [G];
			heap: HEAP_PRIORITY_QUEUE [G];
			i: INTEGER
		do
			seq := linear_representation;
			i := count;
			remove_left_child;
			remove_right_child;
			from
				seq.start;
				create heap.make (i)
			until
				seq.off
			loop
				heap.put (seq.item);
				seq.forth
			end;
			from
				create temp.make (1, heap.count);
				i := 1
			until
				heap.empty
			loop
				temp.put (heap.item, i);
				heap.remove;
				i := i + 1
			end;
			replace (temp.item ((temp.count) // 2 + 1));
			fill_from_sorted_special (temp.area, 0, temp.count - 1)
		ensure
			is_sorted: sorted
		end;

feature {BINARY_SEARCH_TREE, BINARY_SEARCH_TREE_SET} -- Implementation

	is_subset (other: like Current): BOOLEAN is
			-- Is Current a subset of other
		do
			Result := other.has (item);
			if Result and left_child /= void then
				Result := left_child.is_subset (other)
			end;
			if Result and right_child /= void then
				Result := right_child.is_subset (other)
			end
		end;

	intersect (other: BINARY_SEARCH_TREE [G]) is
			-- Remove all items not in other.
		do
			if right_child /= void then
				right_child.intersect (other)
			end;
			if left_child /= void then
				left_child.intersect (other)
			end;
			if notother.has (item) then
				remove_node
			end
		end;

	subtract (other: BINARY_SEARCH_TREE [G]) is
			-- Remove all items also in other.
		require
			set_exists: other /= void
		do
			if right_child /= void then
				right_child.subtract (other)
			end;
			if left_child /= void then
				left_child.subtract (other)
			end;
			if other.has (item) then
				remove_node
			end
		end;

	merge (other: like Current) is
			-- Add all items of other.
		do
			if other.right_child /= void then
				merge (other.right_child)
			end;
			if other.left_child /= void then
				merge (other.left_child)
			end;
			extend (other.item)
		end;

	remove_node is
			-- Remove current node from the tree.
		require
			is_not_root: notis_root
		local
			is_left_child: BOOLEAN;
			m: like Current
		do
			is_left_child := Current = parent.left_child;
			if nothas_right then
				if left_child /= void then
					left_child.attach_to_parent (void)
				end;
				if is_left_child then
					parent.put_left_child (left_child)
				else
					parent.put_right_child (left_child)
				end;
				parent := void
			elseif nothas_left then
				if right_child /= void then
					right_child.attach_to_parent (void)
				end;
				if is_left_child then
					parent.put_left_child (right_child)
				else
					parent.put_right_child (right_child)
				end;
				parent := void
			else
				m := right_child.min_node;
				m.remove_node;
				item := m.item
			end
		end;

	pruned (v: like item): like Current is
		local
			m: like Current
		do
			if item = v then
				if has_none then
				elseif nothas_right then
					Result := left_child
				elseif nothas_left then
					Result := right_child
				else
					m := right_child.min_node;
					m.remove_node;
					item := m.item;
					Result := Current
				end
			else
				Result := Current;
				if v < item then
					if left_child /= void then
						left_child := left_child.pruned (v)
					end
				else
					if right_child /= void then
						right_child := right_child.pruned (v)
					end
				end
			end
		end;

	min_node: like Current is
			-- node containing min
		do
			if has_left then
				Result := left_child.min_node
			else
				Result := Current
			end
		end;

	max_node: like Current is
			-- node containing max
		do
			if has_right then
				Result := right_child.min_node
			else
				Result := Current
			end
		end;

feature {NONE} -- Implementation

	fill_from_sorted_special (t: SPECIAL [G]; s, e: INTEGER) is
			-- Put values from t into tree in such an order that
			-- the tree will be balanced if t is sorted.
		local
			m: INTEGER
		do
			m := (s + e) // 2;
			put (t.item (m));
			if m - 1 >= s then
				fill_from_sorted_special (t, s, m - 1)
			end;
			if m + 1 <= e then
				fill_from_sorted_special (t, m + 1, e)
			end
		end;

end -- class BINARY_SEARCH_TREE