  
  [1X8 AVL trees[0X
  
  
  [1X8.1 The idea of AVL trees[0X
  
  AVL  trees  are  balanced binary trees called "AVL trees" in honour of their
  inventors  G.M.  Adelson-Velskii and E.M. Landis (see [AM62]). A description
  in English can be found in [Knu97] in Section 6.2.3 about balanced trees.
  
  The  general idea is to store data in a binary tree such that all entries in
  the  left  subtree  of a node are smaller than the entry at the node and all
  entries  in  the right subtree are bigger. The tree is kept "balanced" which
  means that for each node the depth of the left and right subtrees differs by
  at  most  1. In this way, finding something in the tree, adding a new entry,
  deleting  an  entry  all  have  complexity  log(n)  where n is the number of
  entries in the tree. If one additionally stores the number of entries in the
  left  subtree  of  each node, then finding the k-th entry, removing the k-th
  entry  and inserting an entry in position k also have complexity log(n). The
  [5Xorb[0m  contains  an  implementation  of  such tree objects providing all these
  operations.
  
  "Entries" in AVL tree objects are key-value pairs and the sorting is done by
  the  key. If all values as [9Xtrue[0m then no memory is needed to store the values
  (see  the  corresponding behaviour for hash tables). The only requirement on
  the  type  of  the keys is that two arbitrary keys must be comparable in the
  sense  that  one  can  decide  which  of  them  is smaller. If [5XGAP[0ms standard
  comparison  operations  <  and  =  work  for your keys, no further action is
  required,  if  not,  then  you  must  provide  your own three-way comparison
  function (see below).
  
  Note  that  the  AVL  trees  implemented  here  can be used in basically two
  different  ways, which can sometimes be mixed: The usual way is by accessing
  entries  by  their  key,  the  tree  is  then automatically kept sorted. The
  alternative  way  is  by accessing entries by their index in the tree! Since
  the  nodes  of the trees remember how many elements are stored in their left
  subtree,  it  is  in  fact  possible to access the k-th entry in the tree or
  delete  it.  It is even possible to insert something in position k. However,
  note  that  if you do this latter operation, you are yourself responsible to
  keep the entries in the tree sorted. You can ignore this responsibility, but
  then  you  can no longer access the entries in the tree by their key and the
  corresponding functions might fail or even run into errors.
  
  This  usage  can  be  useful,  since  in  this  way  AVL  trees  provide  an
  implementation  of a list data structure where the operation list access (by
  index), adding an element (in an arbitrary position) and deleting an element
  (by  its  index) all have complexity log(n) where n is the number of entries
  in the list.
  
  
  [1X8.2 Using AVL trees[0X
  
  An AVL tree is created using the following function:
  
  [1X8.2-1 AVLTree[0m
  
  [2X> AVLTree( [0X[3X[opt][0X[2X ) _________________________________________________[0Xfunction
  [6XReturns:[0X  A new AVL tree object
  
  This function creates a new AVL tree object. The optional argument [3Xopt[0m is an
  options record, in which you can bind the following components:
  
  [10Xcmpfunc[0m  is a three-way comparison function taking two arguments [3Xa[0m and [3Xb[0m and
  returning  -1  if [3Xa[0m < [3Xb[0m, +1 if [3Xa[0m > [3Xb[0m and 0 if [3Xa[0m = [3Xb[0m. If no function is given
  then the generic function [2XAVLCmp[0m ([14X8.2-2[0m) is taken. This three-way comparison
  function  is  stored  with  the tree and is used for all comparisons in tree
  operations.  [10Xallocsize[0m  is  the  number of nodes which are allocated for the
  tree  initially. It can be useful to specify this if you know that your tree
  will  eventually  contain  a lot of entries, since then the tree object does
  not have to grow that many times.
  
  For  every  AVL  tree a three-way comparison function is needed, usually you
  can get away with using the following default one:
  
  [1X8.2-2 AVLCmp[0m
  
  [2X> AVLCmp( [0X[3Xa, b[0X[2X ) ___________________________________________________[0Xfunction
  [6XReturns:[0X  -1, 0 or 1
  
  This function calls the [9X<[0m operation and the [9X=[0m operation to provide a generic
  three-way comparison function to be used in AVL tree operations. See [2XAVLTree[0m
  ([14X8.2-1[0m)  for a description of the return value. This function is implemented
  in the kernel and should be particularly fast.
  
  The following functions are used to access entries by key:
  
  [1X8.2-3 AVLAdd[0m
  
  [2X> AVLAdd( [0X[3Xt, key, val[0X[2X ) ____________________________________________[0Xfunction
  [6XReturns:[0X  [9Xtrue[0m or [9Xfail[0m
  
  The  first  argument [3Xt[0m must be an AVL tree. This function stores the key [3Xkey[0m
  with  value  [3Xvalue[0m  in  the  tree  assuming  that  the keys in it are sorted
  according  to  the  three-way  comparison  function stored with the tree. If
  [3Xvalue[0m  is  [9Xtrue[0m then no additional memory is needed. It is an error if there
  is already a key equal to [3Xkey[0m in the tree, in this case the function returns
  [9Xfail[0m. Otherwise it returns [9Xtrue[0m.
  
  [1X8.2-4 AVLLookup[0m
  
  [2X> AVLLookup( [0X[3Xt, key[0X[2X ) ______________________________________________[0Xfunction
  [6XReturns:[0X  an value or [9Xfail[0m
  
  The first argument [3Xt[0m must be an AVL tree. This function looks up the key [3Xkey[0m
  in  the  tree and returns the value which is associated to it. If the key is
  not  in the tree, the value [9Xfail[0m is returned. This function assumes that the
  keys  in  the tree are sorted according to the three-way comparison function
  stored with the tree.
  
  [1X8.2-5 AVLDelete[0m
  
  [2X> AVLDelete( [0X[3Xt, key[0X[2X ) ______________________________________________[0Xfunction
  [6XReturns:[0X  an value or [9Xfail[0m
  
  The first argument [3Xt[0m must be an AVL tree. This function looks up the key [3Xkey[0m
  in  the tree, deletes it and returns the value which was associated with it.
  If  [3Xkey[0m  is  not  contained in the tree then [9Xfail[0m is returned. This function
  assumes  that  the  keys  in  the tree are sorted according to the three-way
  comparison function stored with the tree.
  
  [1X8.2-6 AVLFindIndex[0m
  
  [2X> AVLFindIndex( [0X[3Xt, key[0X[2X ) ___________________________________________[0Xfunction
  [6XReturns:[0X  an integer or [9Xfail[0m
  
  The first argument [3Xt[0m must be an AVL tree. This function looks up the key [3Xkey[0m
  in  the  tree  and  returns the index, under which it is stored in the tree.
  This  index  is  one-based, that is, it takes values from 1 to the number of
  entries  in  the  tree.  If  [3Xkey[0m  is  not contained in the tree then [9Xfail[0m is
  returned.  This  function  assumes  that  the  keys  in  the tree are sorted
  according to the three-way comparison function stored with the tree.
  
  The following functions are used to access entries in trees by their index:
  
  [1X8.2-7 AVLIndex[0m
  
  [2X> AVLIndex( [0X[3Xt, index[0X[2X ) _____________________________________________[0Xfunction
  [6XReturns:[0X  a key or [9Xfail[0m
  
  The  first  argument [3Xt[0m must be an AVL tree. This function returns the key at
  index  [3Xindex[0m  in the tree, so [3Xindex[0m must be an integer in the range 1 to the
  number of elements in the tree. If the value is out of these bounds, [9Xfail[0m is
  returned.  Note  that to use this function it is not necessary that the keys
  in the tree are sorted according to the three-way comparison function stored
  with the tree.
  
  [1X8.2-8 AVLIndexLookup[0m
  
  [2X> AVLIndexLookup( [0X[3Xt, index[0X[2X ) _______________________________________[0Xfunction
  [6XReturns:[0X  a value or [9Xfail[0m
  
  The  first  argument  [3Xt[0m must be an AVL tree. This function returns the value
  associated  to  the  key  at  index  [3Xindex[0m  in the tree, so [3Xindex[0m must be an
  integer  in  the range 1 to the number of elements in the tree. If the value
  is  out of these bounds, [9Xfail[0m is returned. Note that to use this function it
  is  not  necessary  that  the  keys  in the tree are sorted according to the
  three-way comparison function stored with the tree.
  
  [1X8.2-9 AVLIndexAdd[0m
  
  [2X> AVLIndexAdd( [0X[3Xt, key, value, index[0X[2X ) ______________________________[0Xfunction
  [6XReturns:[0X  a key or [9Xfail[0m
  
  The  first argument [3Xt[0m must be an AVL tree. This function inserts the key [3Xkey[0m
  at  index [3Xindex[0m in the tree and associates the value [3Xvalue[0m with it. If [3Xvalue[0m
  is  [9Xtrue[0m  then  no additional memory is needed to store the value. The index
  [3Xindex[0m  must  be  an  integer  in the range 1 to n+1 where n is the number of
  entries  in the tree. The new key is inserted before the key which currently
  is  stored  at  index [3Xindex[0m, so calling with [3Xindex[0m equal to n+1 puts the new
  key  at the end. If [3Xindex[0m is not in the corrent range, this function returns
  [9Xfail[0m and the tree remains unchanged.
  
  [12XCaution:[0m  With  this function it is possible to put a key into the tree at a
  position  such  that  the keys in the tree are no longer sorted according to
  the  three-way comparison function stored with the tree! If you do this, the
  functions   [2XAVLAdd[0m   ([14X8.2-3[0m),   [2XAVLLookup[0m  ([14X8.2-4[0m),  [2XAVLDelete[0m  ([14X8.2-5[0m)  and
  [2XAVLFindIndex[0m ([14X8.2-6[0m) will no longer work since they assume that the keys are
  sorted!
  
  [1X8.2-10 AVLIndexDelete[0m
  
  [2X> AVLIndexDelete( [0X[3Xt, index[0X[2X ) _______________________________________[0Xfunction
  [6XReturns:[0X  a key or [9Xfail[0m
  
  The  first  argument [3Xt[0m must be an AVL tree. This function deletes the key at
  index [3Xindex[0m in the tree and returns the value which was associated with it.
  
  The following functions allow low level access to the AVL tree object:
  
  [1X8.2-11 AVLFind[0m
  
  [2X> AVLFind( [0X[3Xt, key[0X[2X ) ________________________________________________[0Xfunction
  [6XReturns:[0X  an integer or [9Xfail[0m
  
  The  first argument [3Xt[0m must be an AVL tree. This function locates the key [3Xkey[0m
  in  the tree and returns the position in the positional object, at which the
  node  which  contains  the  key  is  stored.  This  position  will always be
  divisible  by 4. Use the functions [2XAVLData[0m ([14X8.2-13[0m) and [2XAVLValue[0m ([14X8.2-14[0m) to
  access the key and value of the node respectively. The function returns [9Xfail[0m
  if  the key is not found in the tree. This function assumes that the keys in
  the  tree  are  sorted according to the three-way comparison function stored
  with the tree.
  
  [1X8.2-12 AVLIndexFind[0m
  
  [2X> AVLIndexFind( [0X[3Xt, index[0X[2X ) _________________________________________[0Xfunction
  [6XReturns:[0X  an integer or [9Xfail[0m
  
  The  first  argument  [3Xt[0m must be an AVL tree. This function locates the index
  [3Xindex[0m  in  the  tree  and  returns the position in the positional object, at
  which the node which hash this index is stored. This position will always be
  divisible  by 4. Use the functions [2XAVLData[0m ([14X8.2-13[0m) and [2XAVLValue[0m ([14X8.2-14[0m) to
  access the key and value of the node respectively. The function returns [9Xfail[0m
  if  the key is not found in the tree. This function does not assume that the
  keys  in  the tree are sorted according to the three-way comparison function
  stored with the tree.
  
  [1X8.2-13 AVLData[0m
  
  [2X> AVLData( [0X[3Xt, pos[0X[2X ) ________________________________________________[0Xfunction
  [6XReturns:[0X  an key
  
  The  first  argument  [3Xt[0m must be an AVL tree and the second a position in the
  positional  object  corresponding to a node as returned by [2XAVLFind[0m ([14X8.2-11[0m).
  The function returns the key associated with this node.
  
  [1X8.2-14 AVLValue[0m
  
  [2X> AVLValue( [0X[3Xt, pos[0X[2X ) _______________________________________________[0Xfunction
  [6XReturns:[0X  a value
  
  The  first  argument  [3Xt[0m must be an AVL tree and the second a position in the
  positional  object  corresponding to a node as returned by [2XAVLFind[0m ([14X8.2-11[0m).
  The function returns the value associated with this node.
  
  The  following convenience methods for standard list methods are implemented
  for AVL tree objects:
  
  [1X8.2-15 Display[0m
  
  [2X> Display( [0X[3Xt[0X[2X ) _______________________________________________________[0Xmethod
  [6XReturns:[0X  nothing
  
  This function displays the tree in a user-friendly way. Do not try this with
  trees containing many nodes!
  
  [1X8.2-16 ELM_LIST[0m
  
  [2X> ELM_LIST( [0X[3Xt, index[0X[2X ) _______________________________________________[0Xmethod
  [6XReturns:[0X  A key or [9Xfail[0m
  
  This  method  allows  for  easy access to the key at index [3Xindex[0m in the tree
  using  the  square  bracket  notation  [10X[3Xt[0m[10X[[3Xindex[0m[10X][0m. It does exactly the same as
  [2XAVLIndex[0m ([14X8.2-7[0m). This is to make AVL trees behave more like lists.
  
  [1X8.2-17 Position[0m
  
  [2X> Position( [0X[3Xt, key[0X[2X ) _________________________________________________[0Xmethod
  [6XReturns:[0X  an integer or [9Xfail[0m
  
  This  method  allows  to  use  the [10XPosition[0m operation to locate the index at
  which  the  key  [3Xkey[0m  is  stored  in  the  tree. It does exactly the same as
  [2XAVLFindIndex[0m ([14X8.2-6[0m). This is to make AVL trees behave more like lists.
  
  [1X8.2-18 Add[0m
  
  [2X> Add( [0X[3Xt, key[, index][0X[2X ) _____________________________________________[0Xmethod
  [6XReturns:[0X  nothing
  
  This  method  allows  to use the [10XAdd[0m operation to add a key (with associated
  value  [9Xtrue[0m)  to  the  tree  at  index  [3Xindex[0m.  It  does exactly the same as
  [2XAVLIndexAdd[0m  ([14X8.2-9[0m), so the same warning about sortedness as there applies!
  If  [3Xindex[0m is omitted, the key is added at the end. This is to make AVL trees
  behave more like lists.
  
  [1X8.2-19 Remove[0m
  
  [2X> Remove( [0X[3Xt, index[0X[2X ) _________________________________________________[0Xmethod
  [6XReturns:[0X  a key
  
  This method allows to use the [10XRemove[0m operation to remove a key from the tree
  at  index  [3Xindex[0m.  If  [3Xindex[0m is omitted, the last key in the tree is remove.
  This  method  returns the deleted key or [9Xfail[0m if the tree was empty. This is
  to make AVL trees behave more like lists.
  
  [1X8.2-20 Length[0m
  
  [2X> Length( [0X[3Xt[0X[2X ) ________________________________________________________[0Xmethod
  [6XReturns:[0X  a key
  
  This  method  returns the number of entries stored in the tree [3Xt[0m. This is to
  make AVL trees behave more like lists.
  
  [1X8.2-21 \in[0m
  
  [2X> \in( [0X[3Xkey, t[0X[2X ) ______________________________________________________[0Xmethod
  [6XReturns:[0X  [9Xtrue[0m or [9Xfalse[0m
  
  This  method  tests  whether or not the key [3Xkey[0m is stored in the AVL tree [3Xt[0m.
  This is to make AVL trees behave more like lists.
  
  
  [1X8.3 The internal data structures[0X
  
  An  AVL  tree is a positional object in which the first 7 positions are used
  for administrative data (see table below) and then from position 8 on follow
  the  nodes of the tree. Each node uses 4 positions such that all nodes begin
  at  positions  divisible  by  4.  The system allocates the positional object
  larger than actually needed such that not every new node leads to the object
  being  copied.  Nodes  which  become  free are collected in a free list. The
  following table contains the information what is stored in each of the first
  7 entries:
  
        1 | last actually used position, is always congruent 3 mod 4          
        2 | position of first node in free list                               
        3 | number of currently used nodes in the tree                        
        4 | position of largest allocated position is always congruent 3 mod 4
        5 | three-way comparison function                                     
        6 | position of the top node                                          
        7 | a plain list holding the values stored under the keys             
  
  The four positions used for a node contain the following information, recall
  that each node starts at a position divisible by 4:
  
        0 mod 4 | reference to the key                                           
        1 mod 4 | position of left node or 0 if empty, balance factor (see below)
        2 mod 4 | position of right node or 0 if empty                           
        3 mod 4 | index: number of nodes in left subtree plus one                
  
  Since  all  positions  of  nodes  are  divisible  by 4, we can use the least
  significant  two  bits  of the left node reference for the so called balance
  factor.  Balance factor 0 (both bits 0) indicates that the depth of the left
  subtree  is  equal to the depth of the right subtree. Balance factor 1 (bits
  01)  indicates  that  the depth of the right subtree is one greater than the
  depth of the left subtree. Balance factor 2 (or -1 in [Knu97], here bits 10)
  indicates  that  the depth of the left subtree is one greater than the depth
  of the right subtree.
  
  For  freed nodes the position of the next free node in the free list is held
  in the 0 mod 4 position and 0 means the end of the free list.
  
  Position 7 in the positional object can contain the value [9Xfail[0m, in this case
  all  stored  values are [9Xtrue[0m. This is a measure to limit the memory usage in
  the  case  that  the only relevant information in the tree is the key and no
  values  are  stored  there.  This  is  in particular interesting if the tree
  structure is just used as a list implementation.
  
  Note  that  all functions dealing with AVL trees are both implemented on the
  [5XGAP[0m  level and on the kernel level. Both implementations do exactly the same
  thing,  the  kernel  version  is  only  much faster and tuned for efficiency
  whereas  the [5XGAP[0m version documents the functionality better and is used as a
  fallback if the C-part of the [5Xorb[0m is not compiled.
  
