I understand that this is an old thread, but I may have something that can help someone who is looking for a not-so-complicated solution.
I have done this several times in different ways. How this is done depends on several factors:
- Do you know the maximum number of key / value pairs that you need to track?
- Are all values of the same type?
- How fast should it be?
If the answers to 1 and 2 are yes, then this can be pretty straightforward. When the answer to 3 is “not important” or when the maximum number of pairs is not too large, I use arrays or blocks of dynamically allocated memory, considered as arrays.
There are two arrays in this scheme: - an array of indices (not a key) - an array of structures of a key / value pair containing the key name and value
You also have a structure that keeps track of a list of keys / values, containing (minimum) pointers to arrays of index and key / value structures, the number of key / value pairs currently defined, and the maximum number of key / value pairs that can be stored.
Initially, the number of key / value pairs is 0, each element of the array in the index array contains an initial value (it can be zero, but this is usually what indicates that it is not used, for example -1), and all elements of the array of structures are key pairs / values are reset (no name, no value).
The index array is maintained so that the index values refer to the structures of the key / value pair in another array in the correct order. Insertions and deletions do not move any existing pair structure, but only indexes. When the key / value pair is removed, nullify the structure containing it.
When using qsort () or its siblings, the comparison function uses the indices in the index array to access the names of the corresponding key / value pairs, and your exchange function changes the index values in the index array. The insert performs an overlay copy in place (from the end to the insertion point) to shuffle the key indices that appear after the new key has dropped one position in the index array, and the deletion does a similar upward shuffle to close the gap where the deleted key was .
A slightly faster version of this, which uses more memory for storage, uses a C connection to maintain the forward chain index in the unused elements of the key / value pair, and initialization combines them with the next “free” index in the context of the list. This prevents searching the list of free items when inserting a new pair. When you need a free key / value pair object, use the index stored in the "next free" for the new item and set the "next free" to the saved chain index in the newly declared free object. When you drop a pair, simply copy the “next free” value to the chain index in the freed object and set the index of the freed object as the new “next free” value.
An index array can also be implemented using pointers to key / value structures in memory. In this case, the “next free” and chain links in the list of free objects also become pointers.
The above diagram works well for small key size values and values and simple value types.