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: "Sorted sets implemented as binary search trees";
	status: "See notice at end of class";
	names: binary_search_tree_set, set, binary_search_tree;
	representation: recursive, array;
	access: membership, min, max;
	contents: generic;
	date: "$Date: 2007-03-30 19:10:11 +0000 (Fri, 30 Mar 2007) $";
	revision: "$Revision: 95354 $"

class BINARY_SEARCH_TREE_SET [G -> COMPARABLE]

inherit
	COMPARABLE_SET [G]
		redefine
			min, max, has
		end

creation
	make

feature -- Initialization

	make is
		do
			before := true
		end;

feature -- Access

	has (v: like item): BOOLEAN is
			-- Is there a node with item v in tree?
			-- (Reference or object equality,
			-- based on object_comparison.)
		do
			if tree /= void then
				if object_comparison then
					tree.compare_objects
				else
					tree.compare_references
				end;
				Result := tree.has (v)
			end
		end;

feature -- Measurement

	count: INTEGER is
			-- Number of items in tree
		do
			if tree /= void then
				Result := tree.count
			end
		end;

	min: like item is
			-- Minimum item in tree
		do
			Result := tree.min
		end;

	max: like item is
			-- Maximum item in tree
		do
			Result := tree.max
		end;

	item: G is
		do
			Result := active_node.item
		end;

feature -- Status report

	empty: BOOLEAN is
		do
			Result := tree = void
		end;

	Extendible: BOOLEAN is true;
			-- Can new items be added? (Answer: yes.)

	Prunable: BOOLEAN is true;
			-- Can items be removed? (Answer: yes.)

	after: BOOLEAN;
			-- Is there no valid cursor position to the right of cursor?

	before: BOOLEAN;
			-- Is there no valid cursor position to the left of cursor?

feature -- Cursor movement

	start is
		do
			before := false;
			if tree = void then
				after := true
			else
				after := false;
				active_node := tree.min_node
			end
		end;

	finish is
		do
			after := false;
			if tree = void then
				before := true
			else
				before := false;
				active_node := tree.max_node
			end
		end;

	forth is
		local
			new_node, prev_node: like tree
		do
			if before then
				before := false;
				if empty then
					after := true
				end
			else
				if active_node.has_right then
					active_node := active_node.right_child.min_node
				else
					prev_node := active_node;
					active_node := active_node.parent;
					from
					until
						active_node = void or else prev_node = active_node.left_child
					loop
						prev_node := active_node;
						active_node := active_node.parent
					end;
					if active_node = void then
						active_node := tree;
						after := true
					end
				end
			end
		end;

	back is
		local
			new_node, prev_node: like tree
		do
			if after then
				after := false;
				if empty then
					before := true
				end
			else
				if tree.has_left then
					active_node := active_node.left_child.max_node
				else
					prev_node := active_node;
					active_node := active_node.parent;
					from
					until
						active_node = void or else prev_node = active_node.right_child
					loop
						prev_node := active_node;
						active_node := active_node.parent
					end;
					if active_node = void then
						active_node := tree;
						before := true
					end
				end
			end
		end;

feature -- Comparison

	is_subset (other: like Current): BOOLEAN is
			-- Is current structure a subset of other?
		do
			if other.tree /= void then
				Result := tree = void or else tree.is_subset (other.tree)
			else
				Result := true
			end
		end;

feature -- Element change

	put (v: like item) is
			-- Put v at proper position in set
			-- (unless one already exists).
			-- Was declared in BINARY_SEARCH_TREE_SET as synonym of put and extend.
		require
			item_exists: v /= void
		do
			if tree = void then
				tree := new_tree (v)
			else
				tree.extend (v)
			end
		end;

	extend (v: like item) is
			-- Put v at proper position in set
			-- (unless one already exists).
			-- Was declared in BINARY_SEARCH_TREE_SET as synonym of put and extend.
		require
			item_exists: v /= void
		do
			if tree = void then
				tree := new_tree (v)
			else
				tree.extend (v)
			end
		end;

feature -- Removal

	wipe_out is
			-- Remove all items.
		do
			tree := void
		end;

	prune (v: like item) is
		do
			if tree /= void then
				tree := tree.pruned (v)
			end
		end;

feature -- Duplication

	duplicate (n: INTEGER): BINARY_SEARCH_TREE_SET [G] is
			-- New structure containing min (n, count)
			-- items from current structure
		local
			temp_tree: BINARY_SEARCH_TREE [G]
		do
			create Result.make;
			Result.set_tree (tree.duplicate (n))
		end;

feature -- Basic operations

	intersect (other: like Current) is
			-- Remove all items not in other.
		require
			set_exists: other /= void
		local
			m: like tree
		do
			if other.tree = void or tree = void then
				tree := void
			else
				if tree.has_left then
					tree.left_child.intersect (other.tree)
				end;
				if tree.has_right then
					tree.right_child.intersect (other.tree)
				end;
				if notother.has (tree.item) then
					if nottree.has_left then
						tree := tree.right_child
					elseif nottree.has_right then
						tree := tree.left_child
					else
						m := tree.min_node;
						m.remove_node;
						tree.replace (m.item)
					end
				end
			end
		end;

	subtract (other: like Current) is
			-- Remove all items also in other.
		require
			set_exists: other /= void
		local
			m: like tree
		do
			if other.tree /= void and tree /= void then
				if tree.has_left then
					tree.left_child.subtract (other.tree)
				end;
				if tree.has_right then
					tree.right_child.subtract (other.tree)
				end;
				if other.has (tree.item) then
					if nottree.has_left then
						tree := tree.right_child
					elseif nottree.has_right then
						tree := tree.left_child
					else
						m := tree.min_node;
						m.remove_node;
						tree.replace (m.item)
					end
				end
			end
		end;

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

feature {BINARY_SEARCH_TREE_SET} -- Implementation

	tree: BINARY_SEARCH_TREE [G];

	active_node: like tree;

	set_tree (t: like tree) is
			-- Set tree and active_node to t
		do
			tree := t;
			active_node := t
		end;

feature {NONE} -- Implementation

	new_tree (v: like item): like tree is
			-- New allocated node with item set to v
		do
			create Result.make (v)
		end;

end -- class BINARY_SEARCH_TREE_SET