mkavl: Multi-Key AVL Trees
Matthew J. Miller (


The idea behind multi-key AVL trees is that a single item can be keyed multiple ways to different allow O(lg N) lookups. The simplest example would be if you have items that have two separate key fields. For example, if you have an employee database where each employee has a unique ID and phone number. The multi-key AVL essentially manages two separate AVLs under the covers for the same employee data, one keyed by ID and one by phone number, so an employee can be looked up efficiently by either field.

When the mkavl tree is created, M different comparison functions are given. When mkavl_add is called, the item is inserted in M different AVLs, with all M AVL nodes pointing to the same data item.

The only similar data structure I could find was the multi_index library in C++'s Boost.

The backend AVL implementation comes from Ben Plaff's open source AVL library.

In essence, this adds two things the backend AVL implementation. First, it more transparently handles a single data item being added to multiple AVL trees (each keyed differently). Second, it provides for greater than and less than lookups for keys not in the tree. E.g., if you wanted to find the first ID greater than X, you can do this even if X itself doesn't exist in the AVL.

For the unit test of this library, see test_mkavl.c. For example usage, see employee_example.c and malloc_example.c.


A more complex example is, say you want to be able to query your employee database to find all employees with a given last name without walking the entire database. Let's say the employee ID is the primary key. You could create an mkavl tree with two comparison function keyed in the following manner:

  1. Key1: <ID>
  2. Key2: <LastName | ID>

Knowing the zero is the minimum ID value, you could lookup the first employee with the last name "Smith" in O(lg N) time by doing a greater than or equal to lookup on the key <"Smith" | 0>. If the record returned doesn't have the the LastName "Smith", then there are no matching records. Otherwise, you can continue iterating through all the "Smith" records doing greater than lookups until you hit NULL or a non-"Smith" record.


Just run make all to build the dynamic and shared libraries in lib/. Use "-lmkavl" to link the library. Running make clean will remove generated files (e.g., .o).

GNU General Public License

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see <>.

 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines