Newsgroups: comp.lang.prolog
Path: cantaloupe.srv.cs.cmu.edu!rochester!udel!gatech2!news.mathworks.com!news.kei.com!simtel!nntp.coast.net!harbinger.cc.monash.edu.au!news.rmit.EDU.AU!news.unimelb.EDU.AU!munnari.OZ.AU!cs.mu.OZ.AU!mundook.cs.mu.OZ.AU!zs
From: zs@mundook.cs.mu.OZ.AU (Zoltan Somogyi)
Subject: Re: balanced insertion into complete trees
Message-ID: <9533220.25787@mulga.cs.mu.OZ.AU>
Sender: news@cs.mu.OZ.AU (CS-Usenet)
Organization: Computer Science, University of Melbourne, Australia
References: <49c6el$hhp@disunms.epfl.ch>
Date: Tue, 28 Nov 1995 09:25:14 GMT
Lines: 884

ballim@lith.di.epfl.ch (Afzal Ballim) writes:
>I have an application which requires me to maintain a
>very large list of items over which a total order can be
>defined, and upon which I need to do quick searching.
>I'd like to use balanced binary trees for this, and
>am wondering if anyone has code to do an insertion
>into such a structure that would give a new balanced
>tree?

The Mercury standard library has a module for operations on 2-3-4 trees.
If you remove the declarations, you have Prolog code left.

Zoltan Somogyi <zs@cs.mu.OZ.AU> http://www.cs.mu.oz.au/~zs/
Department of Computer Science, University of Melbourne, AUSTRALIA

%---------------------------------------------------------------------------%
% Copyright (C) 1995 University of Melbourne.
% This file may only be copied under the terms of the GNU Library General
% Public License - see the file COPYING.LIB in the Mercury distribution.
%---------------------------------------------------------------------------%

% tree234 - implements a map (dictionary) using 2-3-4 trees.
% main author: conway.
% stability: medium.

% See map.m for documentation.

%---------------------------------------------------------------------------%

:- module tree234.

:- interface.

:- import_module list, std_util, assoc_list.

:- type tree234(K, V).

:- pred tree234__init(tree234(K, V)).
:- mode tree234__init(uo) is det.

:- pred tree234__member(tree234(K, V), K, V).
:- mode tree234__member(in, out, out) is nondet.

:- pred tree234__search(tree234(K, V), K, V).
:- mode tree234__search(in, in, out) is semidet.

:- pred tree234__lookup(tree234(K, V), K, V).
:- mode tree234__lookup(in, in, out) is det.

:- pred tree234__insert(tree234(K, V), K, V, tree234(K, V)).
:- mode tree234__insert(in, in, in, out) is semidet.

:- pred tree234__set(tree234(K, V), K, V, tree234(K, V)).
:- mode tree234__set(di, in, di, uo) is det.
:- mode tree234__set(in, in, in, out) is det.

:- pred tree234__delete(tree234(K, V), K, tree234(K, V)).
:- mode tree234__delete(di, in, uo) is det.
:- mode tree234__delete(in, in, out) is det.

:- pred tree234__remove(tree234(K, V), K, V, tree234(K, V)).
:- mode tree234__remove(di, in, uo, uo) is semidet.
:- mode tree234__remove(in, in, out, out) is semidet.

:- pred tree234__remove_smallest(tree234(K, V), K, V, tree234(K, V)).
:- mode tree234__remove_smallest(in, out, out, out) is semidet.

:- pred tree234__keys(tree234(K, V), list(K)).
:- mode tree234__keys(in, out) is det.

:- pred tree234__values(tree234(K, V), list(V)).
:- mode tree234__values(in, out) is det.

:- pred tree234__update(tree234(K, V), K, V, tree234(K, V)).
:- mode tree234__update(in, in, in, out) is semidet.

	% count the number of elements in a tree
:- pred tree234__count(tree234(K, V), int).
:- mode tree234__count(in, out) is det.

:- pred tree234__assoc_list_to_tree234(assoc_list(K, V), tree234(K, V)).
:- mode tree234__assoc_list_to_tree234(in, out) is det.

:- pred tree234__tree234_to_assoc_list(tree234(K, V), assoc_list(K, V)).
:- mode tree234__tree234_to_assoc_list(in, out) is det.

%------------------------------------------------------------------------------%
%------------------------------------------------------------------------------%
:- implementation.

:- import_module int, require.

:- type tree234(K, V)	--->
		empty
	;	two(K, V, tree234(K, V), tree234(K, V))
	;	three(K, V, K, V, tree234(K, V), tree234(K, V), tree234(K, V))
	;	four(K, V, K, V, K, V, tree234(K, V), tree234(K, V),
						tree234(K, V), tree234(K, V)).

%------------------------------------------------------------------------------%

tree234__init(empty).

%------------------------------------------------------------------------------%

tree234__member(empty, _K, _V) :- fail.
tree234__member(two(K0, V0, T0, T1), K, V) :-
	(
		K = K0,
		V = V0
	;
		tree234__member(T0, K, V)
	;
		tree234__member(T1, K, V)
	).
tree234__member(three(K0, V0, K1, V1, T0, T1, T2), K, V) :-
	(
		K = K0,
		V = V0
	;
		K = K1,
		V = V1
	;
		tree234__member(T0, K, V)
	;
		tree234__member(T1, K, V)
	;
		tree234__member(T2, K, V)
	).
tree234__member(four(K0, V0, K1, V1, K2, V2, T0, T1, T2, T3), K, V) :-
	(
		K = K0,
		V = V0
	;
		K = K1,
		V = V1
	;
		K = K2,
		V = V2
	;
		tree234__member(T0, K, V)
	;
		tree234__member(T1, K, V)
	;
		tree234__member(T2, K, V)
	;
		tree234__member(T3, K, V)
	).

%------------------------------------------------------------------------------%

tree234__search(empty, _K, _V) :- fail.
tree234__search(two(K0, V0, T0, T1), K, V) :-
	compare(Result, K, K0),
	(
		Result = (<),
		tree234__search(T0, K, V)
	;
		Result = (=),
		V = V0
	;
		Result = (>),
		tree234__search(T1, K, V)
	).
tree234__search(three(K0, V0, K1, V1, T0, T1, T2), K, V) :-
	compare(Result0, K, K0),
	(
		Result0 = (<),
		tree234__search(T0, K, V)
	;
		Result0 = (=),
		V = V0
	;
		Result0 = (>),
		compare(Result1, K, K1),
		(
			Result1 = (<),
			tree234__search(T1, K, V)
		;
			Result1 = (=),
			V = V1
		;
			Result1 = (>),
			tree234__search(T2, K, V)
		)
	).
tree234__search(four(K0, V0, K1, V1, K2, V2, T0, T1, T2, T3), K, V) :-
	compare(Result0, K, K0),
	(
		Result0 = (<),
		tree234__search(T0, K, V)
	;
		Result0 = (=),
		V = V0
	;
		Result0 = (>),
		compare(Result1, K, K1),
		(
			Result1 = (<),
			tree234__search(T1, K, V)
		;
			Result1 = (=),
			V = V1
		;
			Result1 = (>),
			compare(Result2, K, K2),
			(
				Result2 = (<),
				tree234__search(T2, K, V)
			;
				Result2 = (=),
				V = V2
			;
				Result2 = (>),
				tree234__search(T3, K, V)
			)
		)
	).

%------------------------------------------------------------------------------%

tree234__update(empty, _K, _V, _T) :- fail.
tree234__update(two(K0, V0, T0, T1), K, V, T) :-
	compare(Result, K, K0),
	(
		Result = (<),
		tree234__update(T0, K, V, NewT0),
		T = two(K0, V0, NewT0, T1)
	;
		Result = (=),
		T = two(K, V, T0, T1)
	;
		Result = (>),
		tree234__update(T1, K, V, NewT1),
		T = two(K0, V0, T0, NewT1)
	).
tree234__update(three(K0, V0, K1, V1, T0, T1, T2), K, V, T) :-
	compare(Result0, K, K0),
	(
		Result0 = (<),
		tree234__update(T0, K, V, NewT0),
		T = three(K0, V0, K1, V1, NewT0, T1, T2)
	;
		Result0 = (=),
		T = three(K, V, K1, V1, T0, T1, T2)
	;
		Result0 = (>),
		compare(Result1, K, K1),
		(
			Result1 = (<),
			tree234__update(T1, K, V, NewT1),
			T = three(K0, V0, K1, V1, T0, NewT1, T2)
		;
			Result1 = (=),
			T = three(K0, V0, K, V, T0, T1, T2)
		;
			Result1 = (>),
			tree234__update(T2, K, V, NewT2),
			T = three(K0, V0, K1, V1, T0, T1, NewT2)
		)
	).
tree234__update(four(K0, V0, K1, V1, K2, V2, T0, T1, T2, T3), K, V, T) :-
	compare(Result0, K, K0),
	(
		Result0 = (<),
		tree234__update(T0, K, V, NewT0),
		T = four(K0, V0, K1, V1, K2, V2, NewT0, T1, T2, T3)
	;
		Result0 = (=),
		T = four(K, V, K1, V1, K2, V2, T0, T1, T2, T3)
	;
		Result0 = (>),
		compare(Result1, K, K1),
		(
			Result1 = (<),
			tree234__update(T1, K, V, NewT1),
			T = four(K0, V0, K1, V1, K2, V2, T0, NewT1, T2, T3)
		;
			Result1 = (=),
			T = four(K0, V0, K, V, K2, V2, T0, T1, T2, T3)
		;
			Result1 = (>),
			compare(Result2, K, K2),
			(
				Result2 = (<),
				tree234__update(T2, K, V, NewT2),
				T = four(K0, V0, K1, V1, K2, V2,
					T0, T1, NewT2, T3)
			;
				Result2 = (=),
				T = four(K0, V0, K1, V1, K, V,
					T0, T1, T2, T3)
			;
				Result2 = (>),
				tree234__update(T3, K, V, NewT3),
				T = four(K0, V0, K1, V1, K2, V2,
					T0, T1, T2, NewT3)
			)
		)
	).

%------------------------------------------------------------------------------%

tree234__lookup(T, K, V) :-
	(
		tree234__search(T, K, V0)
	->
		V = V0
	;
		error("tree234__lookup: key not found.")
	).

%------------------------------------------------------------------------------%

% tree234__insert is implemented using the simple top-down
% approach described in eg Sedgwick which splits 4 nodes into
% two 2 nodes on the downward traversal of the tree as we
% search for the right place to insert the new key-value pair.
% We know we have the right place if the subtrees of the node
% are empty (in which case we expand the node - which will always
% work because we already split 4 nodes into 2 nodes), or if the
% tree itself is empty.
% This algorithm is O(lgN).

tree234__insert(empty, K, V, two(K, V, empty, empty)).

tree234__insert(two(K0, V0, T0, T1), K, V, Tree) :-
	(
		T0 = empty,
		T1 = empty
	->
		compare(Result, K, K0),
		(
			Result = (<),
			Tree = three(K, V, K0, V0, empty, empty, empty)
		;
			Result = (=),
			fail
		;
			Result = (>),
			Tree = three(K0, V0, K, V, empty, empty, empty)
		)
	;
		compare(Result, K, K0),
		(
			Result = (<),
			(
				tree234__four(T0, K1, V1, T2, T3)
			->
				T4 = three(K1, V1, K0, V0, T2, T3, T1),
				tree234__insert(T4, K, V, Tree)
			;
				tree234__insert(T0, K, V, T2),
				Tree = two(K0, V0, T2, T1)
			)
		;
			Result = (=),
			fail
		;
			Result = (>),
			(
				tree234__four(T1, K1, V1, T2, T3)
			->
				T4 = three(K0, V0, K1, V1, T0, T2, T3),
				tree234__insert(T4, K, V, Tree)
			;
				tree234__insert(T1, K, V, T2),
				Tree = two(K0, V0, T0, T2)
			)
		)
	).

tree234__insert(three(K0, V0, K1, V1, T0, T1, T2), K, V, Tree) :-
	(
		T0 = empty,
		T1 = empty,
		T2 = empty
	->
		compare(Result0, K, K0),
		(
			Result0 = (<),
			Tree = four(K, V, K0, V0, K1, V1,
					empty, empty, empty, empty)
		;
			Result0 = (=),
			fail
		;
			Result0 = (>),
			compare(Result1, K, K1),
			(
				Result1 = (<),
				Tree = four(K0, V0, K, V, K1, V1,
					empty, empty, empty, empty)
			;
				Result1 = (=),
				fail
			;
				Result1 = (>),
				Tree = four(K0, V0, K1, V1, K, V,
					empty, empty, empty, empty)
			)
		)
	;
		compare(Result0, K, K0),
		(
			Result0 = (<),
			(
				tree234__four(T0, K2, V2, T3, T4)
			->
				T5 = four(K2, V2, K0, V0, K1, V1,
						T3, T4, T1, T2),
				tree234__insert(T5, K, V, Tree)
			;
				tree234__insert(T0, K, V, T3),
				Tree = three(K0, V0, K1, V1, T3, T1, T2)
			)
		;
			Result0 = (=),
			fail
		;
			Result0 = (>),
			compare(Result1, K, K1),
			(
				Result1 = (<),
				(
					tree234__four(T1, K2, V2, T3, T4)
				->
					T5 = four(K0, V0, K2, V2, K1, V1,
						T0, T3, T4, T2),
					tree234__insert(T5, K, V, Tree)
				;
					tree234__insert(T1, K, V, T3),
					Tree = three(K0, V0, K1, V1, T0, T3, T2)
				)
			;
				Result1 = (=),
				fail
			;
				Result1 = (>),
				(
					tree234__four(T2, K2, V2, T3, T4)
				->
					T5 = four(K0, V0, K1, V1, K2, V2,
							T0, T1, T3, T4),
					tree234__insert(T5, K, V, Tree)
				;
					tree234__insert(T2, K, V, T3),
					Tree = three(K0, V0, K1, V1, T0, T1, T3)
				)
			)
		)
	).

tree234__insert(four(K0, V0, K1, V1, K2, V2, T0, T1, T2, T3), K, V, Tree) :-
	T4 = two(K1, V1,
		two(K0, V0, T0, T1),
		two(K2, V2, T2, T3)
	),
	tree234__insert(T4, K, V, Tree).

%------------------------------------------------------------------------------%

% tree234__set uses the same algorithm as used for tree234__insert,
% except that instead of failing for equal keys, we replace the value.

tree234__set(empty, K, V, two(K, V, empty, empty)).

tree234__set(two(K0, V0, T0, T1), K, V, Tree) :-
	(
		T0 = empty,
		T1 = empty
	->
		compare(Result, K, K0),
		(
			Result = (<),
			Tree = three(K, V, K0, V0, empty, empty, empty)
		;
			Result = (=),
			Tree = two(K, V, T0, T1)
		;
			Result = (>),
			Tree = three(K0, V0, K, V, empty, empty, empty)
		)
	;
		compare(Result, K, K0),
		(
			Result = (<),
			(
				tree234__four(T0, K1, V1, T2, T3)
			->
				T4 = three(K1, V1, K0, V0, T2, T3, T1),
				tree234__set(T4, K, V, Tree)
			;
				tree234__set(T0, K, V, T2),
				Tree = two(K0, V0, T2, T1)
			)
		;
			Result = (=),
			Tree = two(K, V, T0, T1)
		;
			Result = (>),
			(
				tree234__four(T1, K1, V1, T2, T3)
			->
				T4 = three(K0, V0, K1, V1, T0, T2, T3),
				tree234__set(T4, K, V, Tree)
			;
				tree234__set(T1, K, V, T2),
				Tree = two(K0, V0, T0, T2)
			)
		)
	).

tree234__set(three(K0, V0, K1, V1, T0, T1, T2), K, V, Tree) :-
	(
		T0 = empty,
		T1 = empty,
		T2 = empty
	->
		compare(Result0, K, K0),
		(
			Result0 = (<),
			Tree = four(K, V, K0, V0, K1, V1,
				empty, empty, empty, empty)
		;
			Result0 = (=),
			Tree = three(K, V, K1, V1, empty, empty, empty)
		;
			Result0 = (>),
			compare(Result1, K, K1),
			(
				Result1 = (<),
				Tree = four(K0, V0, K, V, K1, V1,
						empty, empty, empty, empty)
			;
				Result1 = (=),
				Tree = three(K0, V0, K, V, empty, empty, empty)
			;
				Result1 = (>),
				Tree = four(K0, V0, K1, V1, K, V,
					empty, empty, empty, empty)
			)
		)
	;
		compare(Result0, K, K0),
		(
			Result0 = (<),
			(
				tree234__four(T0, K2, V2, T3, T4)
			->
				T5 = four(K2, V2, K0, V0, K1, V1,
					T3, T4, T1, T2),
				tree234__set(T5, K, V, Tree)
			;
				tree234__set(T0, K, V, T3),
				Tree = three(K0, V0, K1, V1, T3, T1, T2)
			)
		;
			Result0 = (=),
			Tree = three(K, V, K1, V1, T0, T1, T2)
		;
			Result0 = (>),
			compare(Result1, K, K1),
			(
				Result1 = (<),
				(
					tree234__four(T1, K2, V2, T3, T4)
				->
					T5 = four(K0, V0, K2, V2, K1, V1,
						T0, T3, T4, T2),
					tree234__set(T5, K, V, Tree)
				;
					tree234__set(T1, K, V, T3),
					Tree = three(K0, V0, K1, V1, T0, T3, T2)
				)
			;
				Result1 = (=),
				Tree = three(K0, V0, K, V, T0, T1, T2)
			;
				Result1 = (>),
				(
					tree234__four(T2, K2, V2, T3, T4)
				->
					T5 = four(K0, V0, K1, V1, K2, V2,
						T0, T1, T3, T4),
					tree234__set(T5, K, V, Tree)
				;
					tree234__set(T2, K, V, T3),
					Tree = three(K0, V0, K1, V1, T0, T1, T3)
				)
			)
		)
	).

tree234__set(four(K0, V0, K1, V1, K2, V2, T0, T1, T2, T3), K, V, Tree) :-
	T4 = two(K1, V1,
		two(K0, V0, T0, T1),
		two(K2, V2, T2, T3)
	),
	tree234__set(T4, K, V, Tree).

%------------------------------------------------------------------------------%

:- pred tree234__four(tree234(K, V), K, V, tree234(K, V), tree234(K, V)).
:- mode tree234__four(di, uo, uo, uo, uo) is semidet.
:- mode tree234__four(in, out, out, out, out) is semidet.

tree234__four(four(K0, V0, K1, V1, K2, V2, T0, T1, T2, T3),
		K1, V1, two(K0, V0, T0, T1), two(K2, V2, T2, T3)).

%------------------------------------------------------------------------------%

tree234__delete(Tree0, K, Tree) :-
	(
		tree234__remove(Tree0, K, _V, Tree1)
	->
		Tree = Tree1
	;
		Tree = Tree0
	).

%------------------------------------------------------------------------------%

tree234__remove(empty, _K, _V, empty) :- fail.

tree234__remove(two(K0, V0, T0, T1), K, V, Tree) :-
	compare(Result0, K, K0),
	(
		Result0 = (<),
		tree234__remove(T0, K, V, T2),
		Tree = two(K0, V0, T2, T1)
	;
		Result0 = (=),
		tree234__glue(T0, T1, Tree),
		V = V0
	;
		Result0 = (>),
		tree234__remove(T1, K, V, T2),
		Tree = two(K0, V0, T0, T2)
	).

tree234__remove(three(K0, V0, K1, V1, T0, T1, T2), K, V, Tree) :-
	compare(Result0, K, K0),
	(
		Result0 = (<),
		tree234__remove(T0, K, V, T3),
		Tree = three(K0, V0, K1, V1, T3, T1, T2)
	;
		Result0 = (=),
		tree234__glue(T0, T1, T3),
		Tree = two(K1, V1, T3, T2),
		V = V0
	;
		Result0 = (>),
		compare(Result1, K, K1),
		(
			Result1 = (<),
			tree234__remove(T1, K, V, T3),
			Tree = three(K0, V0, K1, V1, T0, T3, T2)
		;
			Result1 = (=),
			tree234__glue(T1, T2, T3),
			Tree = two(K0, V0, T0, T3),
			V = V1
		;
			Result1 = (>),
			tree234__remove(T2, K, V, T3),
			Tree = three(K0, V0, K1, V1, T0, T1, T3)
		)
	).

tree234__remove(four(K0, V0, K1, V1, K2, V2, T0, T1, T2, T3), K, V, Tree) :-
	compare(Result0, K, K0),
	(
		Result0 = (<),
		tree234__remove(T0, K, V, NewT0),
		Tree = four(K0, V0, K1, V1, K2, V2, NewT0, T1, T2, T3)
	;
		Result0 = (=),
		tree234__glue(T0, T1, T0_and_1),
		Tree = three(K1, V1, K2, V2, T0_and_1, T2, T3),
		V = V0
	;
		Result0 = (>),
		compare(Result1, K, K1),
		(
			Result1 = (<),
			tree234__remove(T1, K, V, NewT1),
			Tree = four(K0, V0, K1, V1, K2, V2, T0, NewT1, T2, T3)
		;
			Result1 = (=),
			tree234__glue(T1, T2, T1_and_2),
			Tree = three(K0, V0, K2, V2, T0, T1_and_2, T3),
			V = V1
		;
			Result1 = (>),
			compare(Result2, K, K2),
			(
				Result2 = (<),
				tree234__remove(T2, K, V, NewT2),
				Tree = four(K0, V0, K1, V1, K2, V2,
						T0, T1, NewT2, T3)
			;
				Result2 = (=),
				tree234__glue(T2, T3, T2_and_3),
				Tree = three(K0, V0, K1, V1, T0, T1, T2_and_3),
				V = V2
			;
				Result2 = (>),
				tree234__remove(T3, K, V, NewT3),
				Tree = four(K0, V0, K1, V1, K2, V2,
						T0, T1, T2, NewT3)
			)
		)
	).

%------------------------------------------------------------------------------%

tree234__remove_smallest(empty, _K, _V, empty) :- fail.

tree234__remove_smallest(two(K0, V0, T0, T1), K, V, Tree) :-
	(
		T0 = empty
	->
		K = K0,
		V = V0,
		Tree = T1
	;
		tree234__remove_smallest(T0, K, V, NewT0),
		Tree = two(K0, V0, NewT0, T1)
	).

tree234__remove_smallest(three(K0, V0, K1, V1, T0, T1, T2), K, V, Tree) :-
	(
		T0 = empty
	->
		K = K0,
		V = V0,
		Tree = two(K1, V1, T1, T2)
	;
		tree234__remove_smallest(T0, K, V, NewT0),
		Tree = three(K0, V0, K1, V1, NewT0, T1, T2)
	).

tree234__remove_smallest(four(K0, V0, K1, V1, K2, V2, T0, T1, T2, T3),
								K, V, Tree) :-
	(
		T0 = empty
	->
		K = K0,
		V = V0,
		Tree = three(K1, V1, K2, V2, T1, T2, T3)
	;
		tree234__remove_smallest(T0, K, V, NewT0),
		Tree = four(K0, V0, K1, V1, K2, V2, NewT0, T1, T2, T3)
	).

%------------------------------------------------------------------------------%

% tree234__glue(A, B, C) is true iff C is a 234-tree which is the
% same as the 234-tree A with the 234-tree B attatched to the right-most
% node. It is used when removing a node from the a tree to glue the two
% resulting fragments together.
% XXX a better algorithm could be devised that leaves the tree more
% balanced (this algorithm is not the *proper* way to join 2 234 trees).

:- pred tree234__glue(tree234(K, V), tree234(K, V), tree234(K, V)).
:- mode tree234__glue(di, di, uo) is det.
:- mode tree234__glue(in, in, out) is det.

tree234__glue(empty, T, T).
tree234__glue(two(K0, V0, T0, T1), T, two(K0, V0, T0, NewT1)) :-
	tree234__glue(T1, T, NewT1).
tree234__glue(three(K0, V0, K1, V1, T0, T1, T2), T,
		three(K0, V0, K1, V1, T0, T1, NewT2)) :-
	tree234__glue(T2, T, NewT2).
tree234__glue(four(K0, V0, K1, V1, K2, V2, T0, T1, T2, T3), T,
		four(K0, V0, K1, V1, K2, V2, T0, T1, T2, NewT3)) :-
	tree234__glue(T3, T, NewT3).

%------------------------------------------------------------------------------%

tree234__keys(Tree, Keys) :-
	tree234__keys_2(Tree, [], Keys).

:- pred tree234__keys_2(tree234(K, V), list(K), list(K)).
:- mode tree234__keys_2(in, in, out) is det.

tree234__keys_2(empty, List, List).
tree234__keys_2(two(K0, _V0, T0, T1), L0, L) :-
	tree234__keys_2(T1, L0, L1),
	tree234__keys_2(T0, [K0|L1], L).
tree234__keys_2(three(K0, _V0, K1, _V1, T0, T1, T2), L0, L) :-
	tree234__keys_2(T2, L0, L1),
	tree234__keys_2(T1, [K1|L1], L2),
	tree234__keys_2(T0, [K0|L2], L).
tree234__keys_2(four(K0, _V0, K1, _V1, K2, _V2, T0, T1, T2, T3), L0, L) :-
	tree234__keys_2(T3, L0, L1),
	tree234__keys_2(T2, [K2|L1], L2),
	tree234__keys_2(T1, [K1|L2], L3),
	tree234__keys_2(T0, [K0|L3], L).

%------------------------------------------------------------------------------%

tree234__values(Tree, Values) :-
	tree234__values_2(Tree, [], Values).

:- pred tree234__values_2(tree234(K, V), list(V), list(V)).
:- mode tree234__values_2(in, in, out) is det.

tree234__values_2(empty, List, List).
tree234__values_2(two(_K0, V0, T0, T1), L0, L) :-
	tree234__values_2(T1, L0, L1),
	tree234__values_2(T0, [V0|L1], L).
tree234__values_2(three(_K0, V0, _K1, V1, T0, T1, T2), L0, L) :-
	tree234__values_2(T2, L0, L1),
	tree234__values_2(T1, [V1|L1], L2),
	tree234__values_2(T0, [V0|L2], L).
tree234__values_2(four(_K0, V0, _K1, V1, _K2, V2, T0, T1, T2, T3), L0, L) :-
	tree234__values_2(T3, L0, L1),
	tree234__values_2(T2, [V2|L1], L2),
	tree234__values_2(T1, [V1|L2], L3),
	tree234__values_2(T0, [V0|L3], L).

%------------------------------------------------------------------------------%

tree234__assoc_list_to_tree234(AssocList, Tree) :-
	tree234__assoc_list_to_tree234_2(AssocList, empty, Tree).

:- pred tree234__assoc_list_to_tree234_2(assoc_list(K, V), tree234(K, V),
					tree234(K, V)).
:- mode tree234__assoc_list_to_tree234_2(in, in, out) is det.

tree234__assoc_list_to_tree234_2([], Tree, Tree).
tree234__assoc_list_to_tree234_2([K - V | Rest], Tree0, Tree) :-
	tree234__set(Tree0, K, V, Tree1),
	tree234__assoc_list_to_tree234_2(Rest, Tree1, Tree).

%------------------------------------------------------------------------------%

tree234__tree234_to_assoc_list(Tree, AssocList) :-
	tree234__tree234_to_assoc_list_2(Tree, [], AssocList).

:- pred tree234__tree234_to_assoc_list_2(tree234(K, V), assoc_list(K, V),
						assoc_list(K, V)).
:- mode tree234__tree234_to_assoc_list_2(in, in, out) is det.

tree234__tree234_to_assoc_list_2(empty, List, List).
tree234__tree234_to_assoc_list_2(two(K0, V0, T0, T1), L0, L) :-
	tree234__tree234_to_assoc_list_2(T1, L0, L1),
	tree234__tree234_to_assoc_list_2(T0, [K0 - V0 | L1], L).
tree234__tree234_to_assoc_list_2(three(K0, V0, K1, V1, T0, T1, T2), L0, L) :-
	tree234__tree234_to_assoc_list_2(T2, L0, L1),
	tree234__tree234_to_assoc_list_2(T1, [K1 - V1 | L1], L2),
	tree234__tree234_to_assoc_list_2(T0, [K0 - V0 | L2], L).
tree234__tree234_to_assoc_list_2(four(K0, V0, K1, V1, K2, V2, T0, T1, T2, T3),
					L0, L) :-
	tree234__tree234_to_assoc_list_2(T3, L0, L1),
	tree234__tree234_to_assoc_list_2(T2, [K2 - V2 | L1], L2),
	tree234__tree234_to_assoc_list_2(T1, [K1 - V1 | L2], L3),
	tree234__tree234_to_assoc_list_2(T0, [K0 - V0 | L3], L).

%------------------------------------------------------------------------------%

	% count the number of elements in a tree
tree234__count(empty, 0).
tree234__count(two(_, _, T0, T1), N) :-
	tree234__count(T0, N0),
	tree234__count(T1, N1),
	N is 1 + N0 + N1.
tree234__count(three(_, _, _, _, T0, T1, T2), N) :-
	tree234__count(T0, N0),
	tree234__count(T1, N1),
	tree234__count(T2, N2),
	N is 2 + N0 + N1 + N2.
tree234__count(four(_, _, _, _, _, _, T0, T1, T2, T3), N) :-
	tree234__count(T0, N0),
	tree234__count(T1, N1),
	tree234__count(T2, N2),
	tree234__count(T3, N3),
	N is 3 + N0 + N1 + N2 + N3.

%------------------------------------------------------------------------------%
%------------------------------------------------------------------------------%
