C-language implementation of the Hop table, unlike the Redis version

Source: Internet
Author: User
Tags delete key redis version

Originally the principle of jumping table is very simple (relative to the red and black trees), but the national day on and off for 5 days to finish writing it ...

I learned before the jump table is purely chain-based structure, the process of writing a look at the implementation of Redis, and found that each of its key columns are represented by an array. Think about it. This implementation is very good in terms of performance and code simplicity, except that the maximum number of layers of the hop table is fixed (because it is an array of arrays). And in practice, it may not be desirable to increase the number of layers in a skipped table without limit.

In the end, however, my own implementation was implemented in a purely chained structure, as the array of Redis has already been implemented.

On the principle of jumping table on the internet a lot, here no longer repeat, the code omission is kindly pointed out. The previous diagram shows the logical structure of the hop table in my Code:


Skip Table API Definition--skip_list.h
#ifndef skip_list_h_included#define skip_list_h_includedtypedef struct skip_list_s *skip_list_t;/** * @ Return the newly created empty hop Table instance */skip_list_tskip_list_create ();/** * Destroys the Hop table instance and does not destroy the values contained in the skipped table. */voidskip_list_destroy (skip_list_t SL);/** * Query the value corresponding to key in the jump table. * Return NULL does not mean that the jump table must not contain key, the result of Skip_list_contains (SL, key) will prevail. * @paramkey the key to query, allow key to not exist in the skip table. * @return the value of key corresponding to */void*skip_list_get (skip_list_t SL, int key);/** * Add a key-value pair to the Jump table, which will make skip_list_contains (SL, key) ==1. * If the same key already exists in the Jump table, replace its old value, otherwise create a new key-value pair. * @paramvaluekey the corresponding new value, which is allowed to be null. * @return The value of key in the Jump table */void*skip_list_put (skip_list_t sl, int key, void *value);/** * Remove a key-value pair from the Jump table, which will make the Skip_list_ Contains (SL, key) ==0. * @paramkey The key to delete, allow key to not exist in the skip table. * @return the value of key corresponding to the */void*skip_list_remove (skip_list_t sl, int key),/** * @return The key is present in the Jump table 1, otherwise 0 */intskip_list_ Contains (skip_list_t SL, int key);/** * @return The number of keys in the Jump table */intskip_list_count (skip_list_t SL);/** * Retrieves a collection of keys in the Jump table, with the results sorted in ascending order of the keys * @ Param[out] keys is used to store the key set * @param [int] Lengthkeys The length of the array * @return the number of keys (=min (length, the number of all keys in the jump table) */intskip_list_key_set (skip_list_t sl, int keys[], int length);/** * Retrieves a collection of values in a skipped table, and results in ascending order of the keys * @param [out] values are used to store the value collection * @param [int] lengthvalues Array length * Number of @return values (=min (length, number of all keys in the jump table) */intskip_list_value_set (skip_list_t sl, void * values[], int length); #endif//skip_list_h_included

Skip Table API Test--MAIN.C
#include <stdio.h> #include <stdlib.h> #include <time.h> #include "skip_list.h" #define Count10int Main () {skip_list_t sl;int I, tmp, *keys;keys = (int*) malloc (count*sizeof (int)); Srand (Time (NULL)); sl = Skip_list_create (); for (i=0; i<count; i++) {Keys[i] = rand (); tmp = rand ();p rintf ("Put%5d:%5d, Return%5d", Keys[i], TMP, (int) Skip_li St_put (SL, keys[i], (void*) tmp));p rintf (", count=%d\n", Skip_list_count (SL));} Puts ("*****************************************"); for (i=0; i<count; i++) {printf ("Put%5d:%5d, Return%d\n", keys[ I], keys[i], (int) skip_list_put (SL, keys[i], (void*) keys[i]));} Puts ("*****************************************"); Skip_list_key_set (SL, keys, COUNT);p rintf ("Key set:"); for (i=0; i<count-1; i++) {printf ("%d,", Keys[i]);} printf ("%d\n", Keys[count-1]);p UTS ("*****************************************"); for (i=0; i<count; i++) {printf ( "Get%5d, Return%d\n", Keys[i], (int) skip_list_get (SL, keys[i]));} Puts ("**************************************** * "); for (i=0; i<count; i++) {printf (" Constains%5d, Return%d\n ", Keys[i], skip_list_contains (SL, keys[i]));} Puts ("*****************************************"); for (i=0; i<count; i++) {printf ("Remove%5d, return%5d", Keys[i] , (int) skip_list_remove (SL, keys[i]));p rintf (", count=%d\n", Skip_list_count (SL));} Puts ("*****************************************"); for (i=0; i<count; i++) {printf ("Constains%5d,%d\n", Keys[i], Skip_list_contains (SL, keys[i]));} Skip_list_destroy (SL); free (keys); return 0;}

Skip Table API Implementation--SKIP_LIST.C
#include "skip_list.h" #include <stdlib.h>typedef struct data_s *data_t;typedef struct node_s *node_t;// Represents a key value stored in a node to a struct data_s {int key;void *value;};/ /represents a node in a hop table struct node_s {node_t right;node_t down;data_t data;//Note that all nodes of the same column point to the same data};//randomly generates a node height static according to the probability distribution of the binary lookup tree Inline intrand_level () {int level = 1;while (rand () &1) {level++;} return level;} From node to the right, start by layer down to find keys corresponding key value pairs//In a layer found immediately after the return to improve the search speed//node cannot be nullstatic inline Data_tsearch_data (node_t node, int key) { for (; node, node = Node->down) {for (; Node->right && key > node->right->data->key; node = node-& Gt;right);//At this time Node->data->key < key <= Node->right->data->keyif (node->right && key = = Node->right->data->key) {return node->right->data;}} return NULL;} From node to the right, start by layer down to find keys corresponding key-value pairs, and the vertical path is recorded in the Upadte array//must go to the lowest level before returning, in order to record the full update path//node and update cannot be nullstatic inline Data_tsearch_data_update (node_t node, int key, node_t *update) {for (;; node = Node->down) {for (; Node->right && key > node->right->data->key; node = node->right);//node->data->key < key <= node->right->data->key//ensure that the current node must be on the left side of the target key, For Remove when update *update++ = node;if (!node->down) {break;}} if (node->right && key = = Node->right->data->key) {return node->right->data;} return NULL;} Add some empty layers above the top of the jump table//top_left cannot be null, performance can be improved by static inline Intgain_empty_top_lines (node_t top_left, int count) {int i;for ( i = 0; I < count; i++) {node_t tmp;tmp = (node_t) malloc (sizeof (struct node_s)); tmp->right = Top_left->right;tmp->down = Top_ Left->down;top_left->right = Null;top_left->down = tmp;} return i;} Clearing a few empty layers of the top level of the Skip table//top_left cannot be null, performance can be improved by static inline Intclean_empty_top_lines (node_t top_left) {int count;for (count = 0;!top_left->right; count++) {node_t tmp = top_left->down;if (!tmp) {break;} Top_left->right = Tmp->right;top_left->down = Tmp->down;free (TMP);} return count;} Adds a column position to the new key-value pair in the Jump table//data andUpdate cannot be nullstatic inline voidadd_key_column (data_t data, node_t *update, int length) {int i;for (i=0; i<length; i++) { node_t tmp;tmp = (node_t) malloc (sizeof (struct node_s)); tmp->data = Data;tmp->right = update[i]->right;update[ I]->right = tmp;} for (i=0; i<length-1; i++) {update[i]->right->down = Update[i+1]->right;} Update[length-1]->right->down = NULL;}  Delete the column where key is located in the Jump table//update cannot be nullstatic inline voidremove_key_column (int key, node_t *update, int length) {int i;for (i = 0; i < length; i++) {node_t right = Update[i]->right;if (right && Right->data->key = = key) {update[i]->right = right- >right;free (right);}}} Releases the node and returns its next (right or bottom) node static inline Node_tfree_and_next (node_t node, node_t next) {Free (node); return next;} struct skip_list_s {struct node_s top_left;//jump table upper-left corner of the node int level;//jump surface number int count;//The number of key-value pairs in the Jump table};skip_list_tskip_list_ Create () {skip_list_t SL;SL = (skip_list_t) malloc (sizeof (struct skip_list_s)); sl->top_left.right = NULL;SL->top_left.down = Null;sl->level = 1;sl->count = 0;return sl;} Voidskip_list_destroy (skip_list_t sl) {node_t left, node;for (left = &sl->top_left; left->down; left = left- >down) {for (node = left->right; node; node = free_and_next (node, node->right));}  for (node = left->right; node, node = free_and_next (node, node->right)); Free_and_next (left, left->down)); free (SL);} Void*skip_list_get (skip_list_t SL, int key) {data_t Data;data = Search_data (&sl->top_left, key); if (data) {return Data->value;} return NULL;} Void*skip_list_put (skip_list_t SL, int key, void *value) {void *old_value = null;data_t Data;data = Search_data (&AMP;SL-&G T;top_left, key); if (data) {Old_value = Data->value;data->value = value;} else {node_t *update;int target_level; Target_level = Rand_level (); if (Target_level > Sl->level) {sl->level + = Gain_empty_top_lines (&sl->top_ Left, target_level-sl->level);} Update = (Node_t*) malloc (sizeof (node_t) *sl->level), Search_data_update (&sl->top_left, key, update);d ATA = (data_t) malloc (sizeof (struct data_s));d Ata->key = Key;data->value = Value;//target_level<=sl->leveladd_key_column ( Data, update+ (Sl->level-target_level), target_level); free (update); sl->count++;} return old_value;} Void*skip_list_remove (skip_list_t SL, int key) {void *old_value = null;node_t *update;data_t data;update = (node_t*) Mallo C (sizeof (node_t) *sl->level);d ata = search_data_update (&sl->top_left, key, update), if (data) {// Delete key column Remove_key_column (key, update, sl->level);//clear the empty line that appears above the deleted key column sl->level-= Clean_empty_top_lines ( &sl->top_left); old_value = Data->value;free (data); sl->count--;} Free (update); return old_value;} Intskip_list_contains (skip_list_t SL, int key) {return!! Search_data (&sl->top_left, key);} Intskip_list_count (skip_list_t sl) {return sl->count;} Intskip_list_key_set (skip_list_t sl, int keys[], int length) {int I;node_t left, node;for (left = &sl->top_left; left->down; left = Left->down); for (i = 0, node = left->right; i&lt ; Length && node; i++, node = node->right) {Keys[i] = Node->data->key;} return i;} Intskip_list_value_set (skip_list_t sl, void *values[], int length) {int i;node_t left, node;for (left = &sl->top_le Ft left->down; left = Left->down); for (i = 0, node = left->right; i<length && node; i++, node = node->right) {values[i ] = Node->data->value;} return i;}

The C language implementation of the jump table, unlike the Redis version

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.