Module of managing dynamic sets or associative arrays

Extends the functionality of Pascal by offering alternative data structure : set like array (the order is not kept) with fast find/delete. Its size can change automatically during the execution of the program. The price is that it is somewhat slower than a number indexes access of an array.

This unit defines TDynHashArray, which is very similar to a TList, since it also stores pointer/objects.

It supports Add, Remove, Contains, First, Count and Clear.

Because of the hashing nature the operations adding, removing and finding is done in constant time on average.

Inner structure: There are three parts: 1. The array itself (FItems). Every entry is a pointer to the first TDynHashArrayItem of a list with the same hash index. The first item of every same index list is the list beginning and its IsOverflow flag is set to false. All other items are overflow items. To get all items with the same hash index, do a FindHashItem. Then search through all "Next" items until Next is nil or its IsOverflow flag is set to false. 2. The items beginning with FFirstItem is a 2-way-connected list of TDynHashArrayItem. This list contains all used items. 3. To reduce GetMem/FreeMem calls, free items are cached.

Issues: The maximum capacity is the PrimeNumber. You can store more items, but the performance decreases. The best idea is to provide your own hash function.

Important: Items in the TDynHashArray must not change their key. When changing the key of an item, remove it and add it after the change.
Name of the class that store all functions and data for an hashed array.
Type for hash function
Each hash function specified by the user has to have these parameters
Pointer to an element to be stored in the array.
It points to the next element in the doubly linked list.
It points to the previous element in the doubly linked list.
False if it is the first element of the linked list.
Options for how this class should work.
It will use cached result if available in IndexOfKey
Turns on a cache for contains operations.
Implements set/associative array
Array pointing to link lists
Number of elements stored
The minimum number of items that will be allocated for an array.
The size of the array can be changed anytime. However, even if a size is given by FCapacity is smaller than this minimum number, then this minimum number of items will be allocated. This is done for efficiency and speed.
The size of the array cannot be larger than this number.
FCapacity is overridden by this number, if that is larger than this.
It contains the cached key.
It contains the cached index derived from the key.
The lower element limit for reallocation.
The number of elements allocated are halved if the number of elements in the array goes below this number.
The upper element count limit for reallocation.
The number of elements allocated are doubled if the number of elements in the array reaches this number.
The pointer to the user-defined hash function.
Optional user-defined function for converting keys.
Optional user-defined hash function which can be SlowAlternativeHashMethod.
Changes the number of items (pre-)allocated.
Specify your own hash function to be used by the class.
The hash function has to convert a string into a number in a random fashion.
Rebuilds the internal datastructures.
It is called anytime when there is a change that makes it necessary. E.g. hash function changes or because of dynamic reallocation.
Sets the cache.
The cache is set as given by the parameters.
Adds an item to the set/array.

An example:

uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} Classes, dynhasharray,strings;

var A:TDynHashArray; s:pchar; begin A:=TDynHashArray.Create; s:=StrNew ('u'); A.Add(s); if A.Contains(s) then writeln('1:it contains s.'); writeln('1:count:',A.Count); A.Clear;

if A.Contains(s) then writeln('2:it contains s.'); writeln('2:count:',A.Count); ReadLn; StrDispose(s);
Returns true if the item is in the set.

An example:

uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} Classes, dynhasharray,strings;

var A:TDynHashArray; s:pchar; begin A:=TDynHashArray.Create; s:=StrNew ('u'); A.Add(s); if A.Contains(s) then writeln('1:it contains s.'); writeln('1:count:',A.Count); A.Clear;

if A.Contains(s) then writeln('2:it contains s.'); writeln('2:count:',A.Count); ReadLn; StrDispose(s);
Returns true if the item is in the set.(through OnGetKeyForHashItem)
Removes an element from the set/hash array

An example:

{$mode objfpc}{$H+}

uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} Classes, dynhasharray,strings;

var A:TDynHashArray; s:pchar; s2:pchar; begin A:=TDynHashArray.Create; s:=StrNew ('u'); s2:=StrNew ('i'); A.Add(s); A.Add(s2); if A.Contains(s2) then writeln('1:it contains s2.'); writeln('1:count:',A.Count); A.Remove(s2); if A.Contains(s2) then writeln('2:it contains s2.'); writeln('2:count:',A.Count); ReadLn; StrDispose(s);StrDispose(s2); end.
Removes all elements from the set/hash array

An example:

uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} Classes, dynhasharray,strings;

var A:TDynHashArray; s:pchar; begin A:=TDynHashArray.Create; s:=StrNew ('u'); A.Add(s); if A.Contains(s) then writeln('1:it contains s.'); writeln('1:count:',A.Count); A.Clear;

if A.Contains(s) then writeln('2:it contains s.'); writeln('2:count:',A.Count); ReadLn; StrDispose(s);
Clears the FContainsCache cache
Returns the first item or nil
Number of elements stored in the set/array.

An example:

uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} Classes, dynhasharray,strings;

var A:TDynHashArray; s:pchar; begin A:=TDynHashArray.Create; s:=StrNew ('u'); A.Add(s); if A.Contains(s) then writeln('1:it contains s.'); writeln('1:count:',A.Count); A.Clear;

if A.Contains(s) then writeln('2:it contains s.'); writeln('2:count:',A.Count); ReadLn; StrDispose(s);
Returns calculated index from Item through OnGetKeyForHashItem
Returns calculated index from Item
It uses user-defined hash functions or built-in algorithm
Finds an item as PDynHashArrayItem among all items
Finds an item as PDynHashArrayItem among all items (through OnGetKeyForHashItem)
Finds an item among all items (through OnGetKeyForHashItem)
Gets a link list from the "main" array FItems by index
So it returns a link list which can be processed.
Deletes a PDynHashArrayItem from link list
Copies all items into a given TList
Another hash function that can be used.
Check if data in TDynHashArray are ok
Returns a number indicating the nature of inconsistency. 0 means OK.
Prints out essential data to aid debugging TDynHashArray.
The minimum number of items that will be allocated for an array.
The size of the array can be changed anytime. However, even if a size is given by FCapacity is smaller than this minimum number, then this minimum number of items will be allocated. This is done for efficiency and speed.
The size of the array cannot be larger than this number.
FCapacity is overridden by this number, if that is larger than this.
Space is allocated for this number of items.
The pointer to the user-defined hash function.
THe pointer to the user-defined hash function.
User-defined function to obtain a key from an item
If this function is specified,then it is possible to use this class as an associative array. Otherwise, it implements a set.
Prints out essential data to aid debugging DynHashArrayItemMemManager.
Raised if index is invalid in IndexOfKey.
The index can be invalid if user-defined/custom function are faulty.
A small memory manager