Jump Table (skip list) is a randomized data structure, based on the linked list of parallel, easy to implement, insert, delete, find the complexity of O (Logn). The specific definition of the jump table,
The jump watch was invented by William Pugh, who was really a bull and made some very nice things. It's easy to say a jump watch.
One kind of list, but it adds the jumping function on the basis of the list, it is this jumping function, so that when looking for elements, the jump table can provide O (log n) time complex
Degree. Such balanced data structures such as red and black trees have a time complexity of O (log n), and the advantage of a balanced binary tree skiplist with respect to a red-black tree is better supported and
operation, but it is not easy to implement a data structure like a red-black tree, but as long as you are familiar with the basic operation of the linked list, coupled with the understanding of the principle of the jumping table, to achieve a table data
Structure is a natural thing.
In addition, the jump table in the current popular open source projects also have many applications, such as LEVELDB's core data structure memtable is implemented with a jump table, Redis sorted set data
The structure is also implemented with a jump table.
Skiplist Main Ideas
Starting with the linked list, if it is a simple list (not necessarily ordered), then we look for an element x in the list, we need to traverse the entire list until we find the element x.
Now let's consider an ordered list:
To search for elements {13, 39} From this ordered table, the number of comparisons is {3, 5}, and the total comparison is 3 + 5 = 8 times. Do we think there's a better algorithm? We thought about the
An ordered array lookup problem we can use a binary lookup algorithm, but we cannot use a binary lookup for an ordered list. This time we were thinking about the balance tree, like BST, they were all by putting some
Nodes are taken out as an index of some meaning in their nodes, such as the parent node is generally larger than the left child node and the small less right operand child node. So this time we think of similar binary search tree practices to put some
The node is extracted as an index. Get the following structure:
In this structure we extract {3, 18, 77} as a primary index, so that the search can reduce the number of comparisons, such as in the search 39 o'clock compared only 3 times (by comparison 3,18,39).
Of course, we can also extract some elements from the first index, as a level two index, which can be more rapid element search.
This is basically the heart of the jump table, in fact, is a "space for Time" an algorithm, by adding a forward pointer to each node (that is, the layer), so as to improve the efficiency of the search.
Jump lists are built on a per-layer basis. The bottom layer is an ordinary ordered list. Each higher level serves as the "fast track" for the following list, where the elements in layer I press a fixed probability p (usually
to 0.5 or 0.25) appears in the layer i+1. On average, each element appears in a list of 1/(1-P), while the highest-level element (usually a special head element at the front of the Jump List)
Appears in an O (log1/p N) list.
Skiplist basic data structure and its implementation
A hop table, which should have the following characteristics:
1, a jump table should have several layers (level) composition;
2, the first layer of the jump table contains all the elements;
3, each layer is an orderly chain list;
4, if element x appears on layer I, then all layers smaller than I contain x;
5, each node contains a key and its corresponding value and an array of pointers to the next node of the same-level linked list
。
Skip table Basic Data structure
To define a skip table data type:
// Skip table Structure struct skip_list { int level; // number of layers Node *head; // point to head node } Skip_list;
Where level is the maximum number of levels of the current hop table, head is a pointer to the header node of the Jump table as.
Data structures for each node of the Hop table:
struct node { KeyType key; // key value ValueType value; // value values struct node *next[1]; // array of subsequent pointers, flexible arrays to achieve variable length of structure } Node;
For this structure, it is important to say that struct node *next[1] is actually a flexible array , mainly used to make the struct contain variable long fields. We can get a variable with the following method
Node * Type of memory space for the number of layers (n):
#define New_node (n) ((node*) malloc (sizeof (node) +n*sizeof (node*))
By the above we can request a specified size of memory according to the number of layers N, thus saving unnecessary memory space (such as a fixed-size next array will waste a lot of memory space).
Create a skip Table node
// Create a node Node *create_node (int level , KeyType key, ValueType val) { *p=New_node (level); if (! p) return NULL; P->key=key; P->value=val; return p; }
Create a skip table
The initialization of the list requires the initialization of the head and the end of each layer of the head (based on the predefined max_level) pointing to the ending (NULL)
//Create a skip tableSkip_list *Create_sl () {skip_list*sl= (skip_list*)malloc(sizeof(skip_list));//request to skip table structure memory if(null==SL)returnNULL; SL->level=0;//set the layer level of the jump table, the initial layer is 0 layers (array starting from 0)Node*h=create_node (max_l-1,0,0);//Creating a head node if(h==NULL) { Free(SL); returnNULL; } SL->head =h; inti; //empty the next array of the header for(i=0; i<max_l; ++i) {h->next[i] =NULL; } Srand (Time (0)); returnSL; }
Jump Table Insert Operation
We know that a jump table is a randomized data structure that is randomized when the element is inserted in a random number of layers, and the layer is generated by a random algorithm:
// when inserting an element, the number of layers that the element occupies is completely random. int Randomlevel () { int level=1; while (rand ()%2) level + +; level = (max_l>level)? level:max_l; return Level ; }
Equivalent to doing a coin toss experiment, if encountered positive (rand produced odd), continue to lose, encountered opposite, then stop, with the number of coins lost in the experiment level as the element occupies the number of layers.
It is obvious that the random variable level satisfies the geometric distribution of the parameter P = 1/2, the desired level e[level] = 1/p = 2. That is, the number of layers of each element, the expected value is 2 layers.
Because the data structure of the jump table is orderly on the whole, it is necessary to find the appropriate position when inserting, then modify the pointer (similar to the operation in the linked list), and then update the tab
Level variable. It takes three steps to summarize the insertion of a jump table:
1: Find the location to be inserted, each layer with the new update array;
2: The need to randomly generate a number of layers;
3: From the upper to the bottom of the insertion, and the normal list is inserted exactly the same;
For example, insert a node with key 25, such as:
For step 1, we need to iterate over each layer and save the dropped nodes in this layer (after which the secondary node is null or the successor key is greater than or equal to the key being inserted), for example,
Nodes that have a white star-colored flag are saved to the update array.
For step 2 We have shown that a random number of layers is generated by a random algorithm, but when this randomly generated layer level is greater than the maximum number of layers in the current hop table, we
At this point, you need to update the current Hop table maximum layer to level update content, you should update its content for the head node of the jumping table, think about why do so, hehe. And then it's more
The maximum number of layers for the new hop table.
For step 3 is the same as normal list insertion, but now is the insertion node operation for each layer of the linked list. The final insert result because the newly inserted key is 25 node level randomly
4 is greater than the maximum number of layers before insertion, so the number of layers in the hop table is 4.
The implementation code is as follows:
BOOLInsert (Skip_list *SL, KeyType key, ValueType val) {Node*update[max_l]; Node*q=null,*p=sl->head;//Q,p Initialization inti=sl->level-1; /******************step1*******************/ //from the top level, look down where you want to insert and update//The drop-down node pointer is saved to the update array for(; i>=0; --i) { while((Q=p->next[i]) && q->key<key) P=Q; Update[i]=p; } if(q && Q->key = = key)//key already exists in the case{Q->value =Val; return true; } /******************step2*******************/ //generate a random level of layers intLevel =Randomlevel (); //if the number of newly generated layers is larger than the number of layers in the skip table if(level>sl->Level ) { //point the newly added layer to the header in the update array for(i=sl->level; i<level; + +i) {Update[i]=sl->Head; } SL->level=Level ; } //printf ("%d\n", sizeof (Node) +level*sizeof (node*)); /******************step3*******************/ //Create a new node to insert, one layer at a levelq=Create_node (level, Key, Val); if(!q)return false; //Update node-by-layer pointers as normal linked list inserts for(i=level-1; i>=0; --i) {q->next[i]=update[i]->Next[i]; Update[i]->next[i]=Q; } return true; }
Skip Table Delete node operation
Delete node operation and insert almost, find each layer need to delete the location, delete and operation ordinary linked list exactly the same. However, it is important to note that if the level of the node is the largest,
You need to update the level of the jump table. The implementation code is as follows:
BOOLErase (Skip_list *SL, KeyType key) {Node*update[max_l]; Node*q=null, *p=sl->Head; inti = sl->level-1; for(; i>=0; --i) { while((Q=p->next[i]) && Q->key <key) {P=Q; } Update[i]=p; } //determine if the key to be deleted if(!q | | (Q&&q->key! =key)) return false; //Level-by- layer deletion is the same as regular linked list deletion for(i=sl->level-1; i>=0; --i) {if(UPDATE[I]->NEXT[I]==Q)//Delete a node{Update[i]->next[i]=q->Next[i]; //If the node at the highest level is deleted, the level-- if(sl->head->next[i]==NULL) SL->level--; } } Free(q); Q=NULL; return true; }
Find operations for Jump tables
The advantage of jumping table is to find faster than the normal list, in fact, the search operation has been in the insertion, delete operations, the code is as follows:
ValueType *search (Skip_list *SL, KeyType key) {Node*q,*p=sl->Head; Q=NULL; inti=sl->level-1; for(; i>=0; --i) { while((Q=p->next[i]) && q->key<key) {P=Q; } if(Q && key==q->key)return& (q->value); } returnNULL; }
Destruction of Jump Tables
The above describes the creation of the Jump table, node insertion, node deletion, which involves the dynamic allocation of memory, do not forget to release the requested memory after the use of the jump table, otherwise memory leaks.
Not much to say, the code is as follows:
// release Jump Table void sl_free (skip_list *sl) { if(! SL) return; *q=sl->head; *next; while (q) { next=q->next[0]; Free (q); Q=next; } Free (SL); }
Analysis of Skiplist complexity
Skiplist analysis such as
Reference:
Https://www.cs.auckland.ac.nz/software/AlgAnim/niemann/s_skl.htm
Http://www.cnblogs.com/xuqiang/archive/2011/05/22/2053516.html
Skip List Jump Table implementation