Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>What about a form of <a href="http://en.m.wikipedia.org/wiki/Skip_list" rel="nofollow">skip-list</a>, specifically the " indexed skiplist" in the linked article. That should give O(lg N) insert and lookup, and O(1) access to the first node for both your use cases. </p> <p>--Edit--</p> <p>When I think of O(1) algorithms, I think of radix-based methods. Here is an O(1) insert with rank returned. The idea is to break the key up into nibbles, and keep count of all the inserted items which have that prefix. Unfortunately, the the constant is high (&lt;=64 dereferences and additions), and the storage is O(2 x 2^INT_BITS), which is awful. This is the version for 16 bit ints, expanding to 32 bits should be straightforward.</p> <pre><code>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; } //records that we are storing one more item, //counts the number of smaller existing items int Add1ReturnRank(int* p, int offset, int a) { int i, sum=0; p+=offset; for (i=0;i&lt;a;i++) sum += p[i]; p[i]++; return sum; } int insert(int key, void* data) { unsigned int i4 = (unsigned int)key; unsigned int i3= (i4&gt;&gt; 4); unsigned int i2= (i3&gt;&gt; 4); unsigned int i1= (i2&gt;&gt; 4); int rank = Add1ReturnRank(p1,0, i1&amp;0xF); rank += Add1ReturnRank(p2,i2&amp;0xF0,i2&amp;0xF); rank += Add1ReturnRank(p3,i3&amp;0xFF0,i3&amp;0xF); rank += Add1ReturnRank(p4,i4&amp;0xFFF0,i4&amp;0xF); if (min&gt;key) {min = key;} store(&amp;records[i4],data); return rank; } </code></pre> <p>This structure also supports O(1) GetMin and RemoveMin. (GetMin is instant, Remove has a constant similar to Insert.)</p> <pre><code>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&gt;&gt; 4); unsigned int i2= (i3&gt;&gt; 4); unsigned int i1= (i2&gt;&gt; 4); p4[i4]--; p3[i3]--; p2[i2]--; p1[i1]--; *key = min; while (!p1[i1]) { if (i1==15) { min = 0xFFFF; return NULL;} i2 = (++i1)&lt;&lt;4; } while (!p2[i2]) i3 = (++i2)&lt;&lt;4; while (!p3[i3]) i4 = (++i3)&lt;&lt;4; while (!p4[i4]) ++i4; min = i4; return data; } </code></pre> <p>If your data is sparse and well distributed, you could remove the <code>p4</code> counter, and instead do an insertion sort into the P3 level. That would reduce storage costs by 16, at the cost of a higher worst case insert when there are many similar values.</p> <p>Another idea to improve the storage would be to do combine this idea with something like an <a href="http://en.wikipedia.org/wiki/Extendible_hashing" rel="nofollow">Extendable Hash</a>. Use the integer key as the hash value, and keep count of the inserted nodes in the directory. Doing a sum over the relevant dictionary entries on an insert (as above) should still be O(1) with a large constant, but the storage would reduce to O(N)</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload