How about the skip-list form, specifically the "indexed skipist" in a related article. This should insert O (lg N) insertion and search, and O (1) access the first node for both use cases.
- Edit -
When I think of O (1) algorithms, I think of fundamentally based methods. Here is the O (1) insert with the returned rank. The idea is to split the key into nibbles and save the number of all inserted elements that have this prefix. Unfortunately, the constant is high (<= 64 sections and additions), and the memory is O (2 x 2 ^ INT_BITS), which is terrible. This is a version for 16-bit ints, expanding to 32 bits, should be simple.
int *p1;int *p2;int *p3;int *p4; void **records; unsigned int min = 0xFFFF; int init(void) { p1 = (int*)calloc(16,sizeof(int)); p2 = (int*)calloc(256, sizeof(int)); p3 = (int*)calloc(4096, sizeof(int)); p4 = (int*)calloc(65536,sizeof(int)); records = (void**)calloc(65536,sizeof(void*)); return 0; }
This framework also supports O (1) GetMin and RemoveMin. (GetMin is instantaneous; Remove has a constant similar to Insert.)
void* getMin(int* key) { return data[*key=min]; } void* removeMin(int* key) { int next = 0; void* data = records[min]; unsigned int i4 = min; unsigned int i3= (i4>> 4); unsigned int i2= (i3>> 4); unsigned int i1= (i2>> 4); p4[i4]--; p3[i3]--; p2[i2]--; p1[i1]--; *key = min; while (!p1[i1]) { if (i1==15) { min = 0xFFFF; return NULL;} i2 = (++i1)<<4; } while (!p2[i2]) i3 = (++i2)<<4; while (!p3[i3]) i4 = (++i3)<<4; while (!p4[i4]) ++i4; min = i4; return data; }
If your data is sparse and well distributed, you can delete the p4
counter, and instead enter insertion sorting at the P3 level. This will reduce storage costs by 16, due to a higher worst-case insertion when there are many similar values.
Another idea to improve storage is to combine this idea with something like Extendable Hash . Use the integer key as the hash value and keep the count of inserted nodes in the directory. The execution of the sum of the corresponding dictionary entries in the box (as indicated above) should be O (1) with a large constant, but the storage will be reduced to O (N)
source share