Redis's Jumping table

Source: Internet
Author: User

A jumping table is a data structure that inserts, queries, and deletes the average time complexity of O (Nlogn), which is O (n) in the worst case, which is almost impossible to come by.

compared to the red and black trees .The worst time complexity is much worse, the red-black tree is O (Nlogn), and the Jump table is O (n) The average time complexity is the same implementation is much simpler

Https://en.wikipedia.org/wiki/Skip_list Wiki's jumping table example

the structure of the jumping table is as follows

Jumping table implementation or a linked list, is an ordered list, in the traversal of the time based on the comparison, but the ordinary linked list can only traverse, jumping table added a layer of the concept, the higher the number of elements, the less, each time first from the top to find, and then gradually drop the layer, until the appropriate location. You can see that the nodes at the top level are far less than the number of nodes at the bottom, thus realizing a hopping lookup.

definitions in Redis/* *  Jump Table  */typedef struct zskiplist {    //  header node and footer node     struct zskiplistNode *header, *tail;    //  Number of nodes in the table     unsigned long length;    //  number of layers of the node with the largest number of middle-level tables     int level;}  zskiplist; Jumping table Nodes/* *  jumping table node  */typedef struct zskiplistNode {     //  member Objects     robj *obj;    //  score      double score;    //  Back Hands     struct  zskiplistnode *backward;    //  Floor     struct  zskiplistlevel {        //  Forward Hands          struct zskiplistNode *forward;         //  span         unsigned int span;    }  level[];} The  zskiplistNode; jump table is a spatial time-out data structure, compared to a doubly linked list, the extra space overhead is the level array element in Zskiplistnode, where redundancy stores the forward pointers for each layer. Some methods of redis jumping table implementationZslcreatenodezslcreatezslfreenodezslfreezslrandomlevelzslinsertzsldeletenodezsldelete and a few other focus on several methods/* *  creates and returns a new jump table  * * t = o (1)  */zskiplist *zslcreate (void)   {    int j;    zskiplist *zsl;    //   Allocated Space     zsl = zmalloc (sizeof (*ZSL));    //  Set the height and start layer number     zsl->level = 1;    zsl->length =  0;    //  Initialize header nodes    //headers must have the highest level    // t  = o (1)     zsl->header = zslcreatenode (ZSKIPLIST_MAXLEVEL,0,NULL);     for  (j = 0; j < zskiplist_maxlevel; j++)  {         zsl->header->level[j].forward = NULL;         zsl->header->level[j].span = 0;     }    zsl->header->backward = null;    //  Set Footer     zsl- &GT;TAIL&NBSP;=&NBSP;NULL;&NBSP;&NBSP;&NBSP;&NBSP;RETURN&NBSP;ZSL;} Return a random value, as the level//level of the new Jumping table node is reasonable distribution is the efficiency of the jump table Int zslrandomlevel (void)  {    int  level = 1;    while  ((random () &0xffff)  <  (zskiplist_p &NBSP;*&NBSP;0XFFFF))         level += 1;     return  (Level<zskiplist_maxlevel)  ? level : zskiplist_maxlevel;} /* *  creates a member for &NBSP;OBJ&NBSP, a new node with a score of  score , *  and inserts the new node into jump table  zsl . The return value of the  *  *  function is the new node.  * * t_wrost = o (n^2),  t_avg = o (n log n)  */ Zskiplistnode *zslinsert (zskiplist *zsl, double score, robj *obj)  {     zskiplistnode *update[zskiplist_maxlevel], *x;    unsigned int rank[zskiplist_maxlevel];     int i, level;    redisassert (!isnan (score));     //   Find the insertion position of the node at each layer     // t_wrost = o (n^2),  t_avg = o (N  log n)     x = zsl->header;    for  (i  = zsl->level-1; i >= 0; i--)  {         /* store rank that is crossed to reach the insert  position */        //  if  i  is not  zsl-> level-1  Layer         //  then  i  the start  rank  value of the layer is  i+1   rank  values         //  various layers of  rank  Value one layer accumulation         //  final  rank[0]  value plus one is the pre-node row of the new node          // rank[0]  will later become the basis for calculating  span  values and  rank  values          rank[i] = i ==  (ZSL-&GT;LEVEL-1)  ? 0 : rank[i+1];         //  traverse the Jumping table         /along the forward pointer / t_wrost = o (n^2),  t_avg = o (n log n)          while  (x->level[i].forward &&              (x->level[i].forward->score < score | |                 //  Comparison Score                  (x->level[i ].forward->score == score &&                   Members,  t = o (N)                  comparestringobjects (x->level[i].forward->obj,obj)  < 0))  {             //  record the number of nodes that have been crossed along the way              rank[i] += x->level[i].span;             //  move to next pointer              x = x->level[i].forward;         }        //  record the nodes that will be connected to the new node          update[i] = x;    }    /*  we assume the key is not already inside, since we allow duplicated      * scores, and the re-insertion of score and redis  object should never     * happen since the caller  of zslinsert ()  should test in the hash table      * if the element is already inside or not.       *     * zslinsert ()   callers will ensure that the same score and elements of the same member do not appear,      *  so there's no need for further checks, so you can create new elements directly.      */    //  gets a random value as the number of layers for the new node     //  t = o (N)     level = zslrandomlevel ();     //   If the number of layers in the new node is larger than the number of other nodes in the table     //  initializes unused layers in the header node and logs them to  update  array     //  in the future also points to the new node     if  (level >  Zsl->level)  {        //  initialize not used layer          // t = o (1)         for  (i  = zsl->level; i < level; i++)  {             rank[i] = 0;             update[i] = zsl->header;             update[i]->level[i].span = zsl->length;         }        //  Update the maximum number of nodes in a table          zsl->level = level;    }    //   Create a new node &NBSP;&NBSP;&NBSp; x = zslcreatenode (Level,score,obj);    //  points the previously recorded pointer to the new node and makes the appropriate settings     // t = o (1)     for  (i = 0; i  < level; i++)  {        //  set the   of the new node forward  Pointer         x->level[i].forward = update[i]- >level[i].forward;        //  the  forward  of each node that will be recorded along the way The pointer points to the new node         update[i]->level[i].forward = x;         /* update span covered by update[i] as  x is inserted here */        //  Calculate the number of nodes spanned by a new node         x->level[i].span = update[i]-> level[i].span -  (rank[0]&nbsp- rank[i]);        //  The  span  value of nodes along the way after the new node is inserted         //  where  +1  calculates the new node          update[i]->level[i].span =  (Rank[0] - rank[i])  + 1;     }    /* increment span for untouched levels  */    //  the  span  values of the non-contact nodes also need to be added, which point directly from the table header to the new node     //  t = o (1)     for  (i = level; i < zsl-> level; i++)  {        update[i]->level[i].span++;     }    //  set the new node's back pointer     x->backward =   (Update[0] == zsl->header)  ? NULL : update[0];     if  (X->level[0].forwarD)         x->level[0].forward->backward = x;     else        zsl->tail = x;     //  the node count of the jumping table is increased by one     zsl->length++;    return x;}

procedure for jumping tables to find nodes(Take the Insert element as an example, delete, The process of finding is the same) 1. Start with the head, looking forward based on the forward pointer, if the previous element is larger than the element to be found, or if the tail pointer is encountered, the lower level continues to look up, and if the next element is not greater than the element to be found, forward advances a node and continues the comparison. 2. Repeat the 1 steps until the value of the previous node that Level1 encounters is greater than the value to be looked up eventually always finding the previous position that is larger than the value of the node to be found, inserting the element at this location.

Redis's Jumping table

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.