note
	description: "Sorted sets implemented as binary search trees"
	library: "Free implementation of ELKS library"
	legal: "See notice at end of class."
	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: 2019-07-05 15:26:16 +0000 (Fri, 05 Jul 2019) $"
	revision: "$Revision: 103325 $"

class 
	BINARY_SEARCH_TREE_SET [G -> COMPARABLE]

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

	TRAVERSABLE_SUBSET [G]

create 
	make,
	make_from_iterable

feature {NONE} -- Initialization

	make
			-- Create set.
		do
			before := True
		end

	make_from_iterable (other: ITERABLE [G])
			-- Create a set with all items obtained from other.
		do
			make
			across
				other as o
			loop
				extend (o.item)
			end
		end
	
feature -- Measurement

	count: INTEGER_32
			-- Number of items in tree
		local
			t: like tree
		do
			t := tree
			if t /= Void then
				Result := t.count
			end
		end

	min: like item
			-- Minimum item in tree
		do
			check
					attached tree as t
			then
				Result := t.min
			end
		end

	max: like item
			-- Maximum item in tree
		do
			check
					attached tree as t
			then
				Result := t.max
			end
		end

	item: G
			-- Current item
		do
			check
					attached active_node as a
			then
				Result := a.item
			end
		end
	
feature -- Status report

	is_empty: BOOLEAN
			-- Is set empty?
		do
			Result := tree = Void
		end

	Extendible: BOOLEAN = True
			-- Can new items be added? (Answer: yes.)

	Prunable: BOOLEAN = 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?

	has alias "" (v: like item): BOOLEAN
			-- Is there a node with item v in tree?
			-- (Reference or object equality,
			-- based on object_comparison.)
		local
			t: like tree
		do
			t := tree
			if t /= Void then
				Result := t.has (v)
			end
		end

	off: BOOLEAN
			-- Is there no current item?
			-- off only if tree is_empty or if
			-- it is before or after.
		do
			Result := is_empty or Precursor {COMPARABLE_SET}
		end
	
feature -- Iteration

	new_cursor: ITERATION_CURSOR [G]
			-- Fresh cursor associated with current structure
		do
			if attached tree as t then
				Result := t.new_cursor
			else
				create {EMPTY_ITERATION_CURSOR [G]} Result
			end
		end
	
feature -- Cursor movement

	start
			-- Move cursor to first node.
		local
			t: like tree
		do
			before := False
			t := tree
			if t = Void then
				after := True
			else
				after := False
				active_node := t.min_node
			end
		end

	finish
			-- Move cursor to last node.
		local
			t: like tree
		do
			after := False
			t := tree
			if t = Void then
				before := True
			else
				before := False
				active_node := t.max_node
			end
		end

	forth
			-- Move cursor to next node.
		local
			prev_node: like tree
			a: like active_node
			r: like active_node
		do
			if before then
				before := False
				if is_empty then
					after := True
				end
			else
				a := active_node
				if a /= Void then
					r := a.right_child
					if r /= Void then
						active_node := r.min_node
					else
						from
							prev_node := a
							a := a.parent
						until
							a = Void or else prev_node = a.left_child
						loop
							prev_node := a
							a := a.parent
						end
						if a = Void then
							active_node := tree
							after := True
						else
							active_node := a
						end
					end
				end
			end
		end

	back
			-- Move cursor to previous node.
		local
			prev_node: like tree
			a: like active_node
			l: like active_node
		do
			if after then
				after := False
				if is_empty then
					before := True
				end
			else
				a := active_node
				if a /= Void then
					l := a.left_child
					if l /= Void then
						active_node := l.max_node
					else
						from
							prev_node := a
							a := a.parent
						until
							a = Void or else prev_node = a.right_child
						loop
							prev_node := a
							a := a.parent
						end
						if a = Void then
							active_node := tree
							before := True
						else
							active_node := a
						end
					end
				end
			end
		end
	
feature -- Element change

	put (v: like item)
			-- Put v at proper position in set
			-- (unless one already exists).
			-- Was declared in BINARY_SEARCH_TREE_SET as synonym of extend.
		require else
			item_exists: v /= Void
		local
			t: like tree
		do
			t := tree
			if t = Void then
				tree := new_tree (v)
			elseif not has (v) then
				t.extend (v)
			end
		end

	extend (v: like item)
			-- Put v at proper position in set
			-- (unless one already exists).
			-- Was declared in BINARY_SEARCH_TREE_SET as synonym of put.
		require else
			item_exists: v /= Void
		local
			t: like tree
		do
			t := tree
			if t = Void then
				tree := new_tree (v)
			elseif not has (v) then
				t.extend (v)
			end
		end
	
feature -- Removal

	wipe_out
			-- Remove all items.
		do
			tree := Void
		end

	prune (v: like item)
			-- Remove v.
		local
			t: like tree
		do
			t := tree
			if t /= Void then
				tree := t.pruned (v, t.parent)
			end
		end

	remove
			-- Remove current item.
		local
			l_item: like item
			l_next_item: detachable like item
		do
			if attached tree as t then
				l_item := item
				forth
				if not after then
					l_next_item := item
				end
				tree := t.pruned (l_item, t.parent)
				if l_next_item /= Void and attached tree as t2 then
					active_node := t2.tree_item (l_next_item)
				end
			end
		end
	
feature -- Duplication

	duplicate (n: INTEGER_32): BINARY_SEARCH_TREE_SET [G]
		obsolete "[
			Create a new container explicitly using `make_from_iterable` if available.
			Otherwise, replace a call to the feature with code that creates and initializes container.
			[2018-11-30]
		]"
			-- New structure containing min (n, count)
			-- items from current structure
		local
			t: like tree
		do
			create Result.make
			t := tree
			if t /= Void then
				Result.set_tree (t.duplicate (n))
			end
		end
	
feature {BINARY_SEARCH_TREE_SET} -- Implementation

	tree: detachable BINARY_SEARCH_TREE [G]

	active_node: like tree

	set_tree (t: like tree)
			-- Set tree and active_node to t
		do
			tree := t
			active_node := t
		end
	
feature {NONE} -- Implementation

	new_tree (v: like item): like tree
			-- New allocated node with item set to v
		do
			create Result.make (v)
			if object_comparison then
				Result.compare_objects
			end
		end

	subset_strategy_selection (v: G; other: TRAVERSABLE_SUBSET [G]): SUBSET_STRATEGY [G]
			-- Strategy to calculate several subset features selected depending
			-- on the dynamic type of v and other
		do
			if attached {HASHABLE} v as h then
				create {SUBSET_STRATEGY_HASHABLE [G]} Result
			elseif object_comparison and same_type (other) then
				create {SUBSET_STRATEGY_TREE [G]} Result
			else
				create {SUBSET_STRATEGY_GENERIC [G]} Result
			end
		end
	
invariant
	comparison_mode_equal: attached tree as t implies object_comparison = t.object_comparison

note
	copyright: "Copyright (c) 1984-2019, Eiffel Software and others"
	license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
	source: "[
		Eiffel Software
		5949 Hollister Ave., Goleta, CA 93117 USA
		Telephone 805-685-1006, Fax 805-685-6869
		Website http://www.eiffel.com
		Customer support http://support.eiffel.com
	]"

end -- class BINARY_SEARCH_TREE_SET

Generated by ISE EiffelStudio