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: "Trees implemented using a two way linked list representation";
	status: "See notice at end of class";
	names: two_way_tree, tree, two_way_list;
	representation: recursive, linked;
	access: cursor, membership;
	contents: generic;
	date: "$Date: 2007-03-30 19:10:11 +0000 (Fri, 30 Mar 2007) $";
	revision: "$Revision: 95354 $"

class TWO_WAY_TREE [G]

inherit
	DYNAMIC_TREE [G]
		undefine
			child_after, child_before, child_item, child_off
		redefine
			parent
		select
			has
		end;
	BI_LINKABLE [G]
		rename
			left as left_sibling,
			right as right_sibling,
			put_left as bl_put_left,
			put_right as bl_put_right
		export
			{ANY} left_sibling, right_sibling;
			{TWO_WAY_TREE} bl_put_left, bl_put_right, forget_left, forget_right
		end;
	TWO_WAY_LIST [G]
		rename
			active as child,
			put_left as child_put_left,
			put_right as child_put_right,
			after as child_after,
			back as child_back,
			before as child_before,
			count as arity,
			cursor as child_cursor,
			duplicate as twl_duplicate,
			empty as is_leaf,
			extend as child_extend,
			extendible as child_extendible,
			fill as twl_fill,
			finish as child_finish,
			first_element as first_child,
			forth as child_forth,
			full as twl_full,
			go_i_th as child_go_i_th,
			go_to as child_go_to,
			has as twl_has,
			index as child_index,
			isfirst as child_isfirst,
			islast as child_islast,
			item as child_item,
			last_element as last_child,
			make as twl_make,
			merge_left as twl_merge_left,
			merge_right as twl_merge_right,
			off as child_off,
			prune as twl_prune,
			put as child_put,
			readable as child_readable,
			remove as remove_child,
			remove_left as remove_left_child,
			remove_right as remove_right_child,
			replace as child_replace,
			search as search_child,
			start as child_start,
			writable as child_writable
		export
			{ANY} child;
			{NONE} twl_make, twl_has, twl_fill, twl_duplicate, twl_full
		undefine
			child_readable, is_leaf, child_writable, linear_representation, child_isfirst, child_islast, valid_cursor_index
		redefine
			first_child, last_child, new_cell
		select
			is_leaf
		end

creation
	make

feature -- Initialization

	make (v: like item) is
			-- Create single node with item v.
		do
			put (v);
			twl_make
		end;

feature -- Access

	parent: TWO_WAY_TREE [G];
			-- Parent node

	first_child: like parent;
			-- Leftmost child

	last_child: like parent;

feature {RECURSIVE_CURSOR_TREE} -- Element change

	set_child (n: like parent) is
			-- Set the child of parent to n.
		do
			child := n
		ensure
			child_set: child = n
		end;

feature -- Element change

	put_child (n: like parent) is
			-- Add n to the list of children.
			-- Do not move child cursor.
		do
			if is_leaf then
				first_child := n;
				child := n
			else
				last_child.bl_put_right (n);
				if child_after then
					child := n
				end
			end;
			last_child := n;
			n.attach_to_parent (Current);
			arity := arity + 1
		end;

	replace_child (n: like parent) is
			-- Replace current child by n.
		do
			put_child_right (n);
			remove_child
		end;

	put_child_left (n: like parent) is
			-- Add n to the left of cursor position.
			-- Do not move cursor.
		do
			child_back;
			put_child_right (n);
			child_forth;
			child_forth
		end;

	put_child_right (n: like parent) is
			-- Add n to the right of cursor position.
			-- Do not move cursor.
		do
			if child_before then
				if is_leaf then
					last_child := n
				end;
				n.bl_put_right (first_child);
				first_child := n;
				child := n
			elseif child_islast then
				child.bl_put_right (n);
				last_child := n
			else
				n.bl_put_right (child.right_sibling);
				n.bl_put_left (child)
			end;
			n.attach_to_parent (Current);
			arity := arity + 1
		end;

	merge_tree_before (other: like first_child) is
			-- Merge children of other into current structure
			-- after cursor position. Do not move cursor.
			-- Make other a leaf.
		do
			attach (other);
			twl_merge_left (other)
		end;

	merge_tree_after (other: like first_child) is
			-- Merge children of other into current structure
			-- after cursor position. Do not move cursor.
			-- Make other a leaf.
		do
			attach (other);
			twl_merge_right (other)
		end;

	prune (n: like first_child) is
		local
			l_child: like first_child
		do
			from
				l_child := first_child
			until
				l_child = void or l_child = n
			loop
				l_child := l_child.right_sibling
			end;
			if l_child /= void then
				if l_child = first_child then
					first_child := first_child.right_sibling;
					if child = n then
						child := first_child
					end;
					if l_child = last_child then
						last_child := last_child.left_sibling
					end
				elseif l_child = last_child then
					last_child := last_child.left_sibling;
					if child = n then
						child := last_child
					end
				else
					l_child.right_sibling.bl_put_left (l_child.left_sibling);
					if child = n then
						child := l_child.left_sibling
					end
				end;
				arity := arity - 1;
				if is_leaf and notchild_before then
					first_child := void;
					last_child := void;
					child_after := true
				end;
				n.attach_to_parent (void);
				n.simple_forget_left;
				n.simple_forget_right
			end
		end;

feature {LINKED_TREE} -- Implementation

	new_cell (v: like item): like first_child is
		do
			create Result.make (v);
			Result.attach_to_parent (Current)
		end;

	new_tree: like Current is
			-- A newly created instance of the same type, with
			-- the same node value.
			-- This feature may be redefined in descendants so as to
			-- produce an adequately allocated and initialized object.
		do
			create Result.make (item)
		end;

feature {NONE} -- Implementation

	attach (other: like first_child) is
			-- Attach all children of other to current node.
		local
			cursor: CURSOR
		do
			from
				other.child_start
			until
				other.child_off
			loop
				other.child.attach_to_parent (Current);
				other.child_forth
			end;
			other.child_go_to (cursor)
		end;

invariant

	off_constraint: (child = void) implies child_off;

end -- class TWO_WAY_TREE