Insertion and Deletion - GNU libavl 2.0.3
Author: Ben Pfaff

2.8 Insertion and Deletion |

These functions insert and delete items in tables. There is also a function for searching a table without modifying it.

The design behind the insertion functions takes into account a couple of important issues:

- What should happen if there is a matching item already in the tree? If the items contain only keys and no values, then there's no point in doing anything. If the items do contain values, then we might want to leave the existing item or replace it, depending on the particular circumstances. The tbl_insert() and tbl_replace() functions are handy in simple cases like these.
- Occasionally it is convenient to insert one item into a table, then immediately replace it by a different item that has identical key data. For instance, if there is a good chance that a data item already exists within a table, then it might make sense to insert data allocated as a local variable into a table, then replace it by a dynamically allocated copy if it turned out that the item wasn't already in the table. That way, we save the time required to make an additional copy of the item to insert. The tbl_probe() function allows for this kind of flexibility.

    11. <Table insertion and deletion function prototypes 11> =
    void **tbl_probe (struct tbl_table *, void *);
    void *tbl_insert (struct tbl_table *, void *);
    void *tbl_replace (struct tbl_table *, void *);
    void *tbl_delete (struct tbl_table *, const void *);
    void *tbl_find (const struct tbl_table *, const void *);

This code is included in 16.

Each of these functions takes a table to manipulate as its first argument and a table item as its second argument, here called table and item, respectively. Both arguments must be non-null in all cases. All but tbl_probe() return a table item or a null pointer.

- tbl_probe(): Searches in table for an item matching item. If found, a pointer to the void * data item is returned. Otherwise, item is inserted into the table and a pointer to the copy within the table is returned. Memory allocation failure causes a null pointer to be returned.

  The pointer returned can be used to replace the item found or inserted by a different item. This must only be done if the replacement item has the same position relative to the other items in the table as did the original item. That is, for existing item e, replacement item r, and the table's comparison function f(), the return values of f(e, x) and f(r, x) must have the same sign for every other item x currently in the table. Calling any other table function invalidates the pointer returned and it must not be referenced subsequently.

- tbl_insert(): Inserts item into table, but not if a matching item exists. Returns a null pointer if successful or if a memory allocation error occurs. If a matching item already exists in the table, returns that item.
- tbl_replace(): Inserts item into table, replacing and returning any matching item. Returns a null pointer if the item was inserted but there was no matching item to replace, or if a memory allocation error occurs.
- tbl_delete(): Removes from table and returns an item matching item. Returns a null pointer if no matching item exists in the table.
- tbl_find(): Searches table for an item matching item and returns any item found. Returns a null pointer if no matching item exists in the table.

Exercises:

1. Functions tbl_insert() and tbl_replace() return `NULL` in two very different situations: an error or successful insertion. Why is this not necessarily a design mistake? [answer]

2. Suggest a reason for disallowing insertion of a null item. [answer]

3. Write generic implementations of tbl_insert() and tbl_replace() in terms of tbl_probe(). [answer]