• 123 skip list 确定性跳跃表的实现


    /Files/rocketfan/determinsticList_readme.pdf
    确定性跳跃表,可以实现o(log(n))级别的插入删除和查找,复杂度与二叉搜索树相同,但是实现起来简单许多
    这里给出一个实现,不允许重复的key。关于确定性跳跃表的定义及详细介绍,可参展数据结构与算法分析 c语言描述 中文第二版的p357.

    //123 skip list 的实现文件
      1 /*
      2  *  \file determin_skip_list.h
      3  *  \author pku_goldenlock
      4  *  \date  2009-8-7
      5  */
      6 
      7 #ifndef _DETERMIN_SKIP_LIST_H
      8 #define _DETERMIN_SKIP_LIST_H
      9 
     10 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
     11     TypeName(const TypeName&); \
     12     void operator=(const TypeName&)
     13 
     14 #include <iostream>
     15// #include "skip_list.h"
     16 namespace skip_list {
     17 
     18 /**
     19  * class SkipNode. 
     20  * the node type for DeterminSkipList to operate.
     21  */
     22 template <typename ElemType>
     23 class SkipNode {
     24     public:
     25         template <typename T>  friend class DeterminSkipList;
     26         SkipNode();
     27         SkipNode(const ElemType &key_input, SkipNode *right_input = NULL, 
     28                  SkipNode *down_input = NULL);
     29     private:
     30         DISALLOW_COPY_AND_ASSIGN(SkipNode); /** Do not all copy and assign*/
     31         ElemType key;       /**< The key is what we use for comparing during Search,Insert,Remove.*/
     32         SkipNode *right;    /**< Point to the right skip node ont the same level*/
     33         SkipNode *down;     /**< Point to the lower level skip node where we will go down from current node */
     34 };
     35 
     36 template <typename ElemType>
     37 SkipNode<ElemType>::SkipNode() : right(NULL), down(NULL) {}
     38 
     39 template <typename ElemType>
     40 SkipNode<ElemType>::SkipNode(const ElemType& key_input, SkipNode *right_input, 
     41                              SkipNode *down_input)
     42     : key(key_input), right(right_input), down(down_input) {}
     43 
     44 /* *
     45  * DeterminSkipList
     46  * An implementaion of skip list using 1-2-3 skip list
     47  */
     48 template <typename ElemType>
     49 class DeterminSkipList {
     50     public:
     51         /** Client should determin Max and Max + 1 value*/
     52         DeterminSkipList(const ElemType &max,const ElemType &max_1);
     53         ~DeterminSkipList();
     54         /** Clear the whoe skip list free all allocated resouces on heap*/
     55         void Clear();
     56         bool Search(const ElemType &value) const
     57         /**
     58          * If the list already has one node whose key == value
     59          * return false and do not do insert otherwise insert a new node with
     60          * its key == value and return true
     61          */
     62         bool Insert(const ElemType &value);
     63         /**
     64          * If the list already has one node whose key == value
     65          * remove it and return true otherwise return false
     66          */
     67         bool Remove(const ElemType &value);
     68         /** For debug*/
     69         /** Show the internal structure of the skip list*/
     70         void Print() const
     71         /** Return false if current structure of the skip list is wrong*/
     72         bool IsValid() const;
     73         
     74     private:
     75         /** For simplicty here do not allow copy and assign*/
     76         DISALLOW_COPY_AND_ASSIGN(DeterminSkipList);
     77         void Init();
     78         void ClearHelp(SkipNode<ElemType> *current);
     79         /**
     80          * Helper function for Search
     81          * If could not find one node with key value == item return bottom
     82          * otherwise return postion of node containing the key
     83          * */
     84         SkipNode<ElemType> * SearchHelp(const ElemType &value) const
     85         /** Helper function for Remove, find all the nodes with key == value and modify it to other_value*/
     86         void FindAndModifyRemoveHelp(const ElemType &value, const ElemType &other_value);
     87         /** lower the head if possible during Remove help to keep skip list structure consistent*/
     88         void LowerHeadRemoveHelp();
     89    
     90     private:
     91         //actual data skip list store
     92         SkipNode<ElemType> *head;   /**< where we start*/
     93         SkipNode<ElemType> *bottom; /**< mark if we have down to the lowerest level*/
     94         SkipNode<ElemType> *tail;   /**< mark the end of each level*/
     95 
     96         const ElemType Max;         /**< Max > any client input key value*/
     97         const ElemType Max_1;       /**< Max_1 > Max*/
     98 };
     99 
    100 template <typename ElemType>
    101 DeterminSkipList<ElemType>::DeterminSkipList(const ElemType &max, const ElemType &max_1)
    102     : head(NULL), bottom(NULL), tail(NULL), Max(max), Max_1(max_1)
    103 {
    104     Init();
    105 }
    106 
    107 template <typename ElemType>
    108 DeterminSkipList<ElemType>::~DeterminSkipList()
    109 {
    110     if (head) {
    111         Clear();
    112     }
    113 }
    114 
    115 template <typename ElemType>
    116 void DeterminSkipList<ElemType>::Init()
    117 {
    118     //init head bottom and tail see paper p372 figure 6
    119     bottom = new SkipNode<ElemType>;
    120     bottom->right = bottom->down = bottom;
    121    
    122     tail = new SkipNode<ElemType>(Max_1);
    123     tail->right = tail;
    124 
    125     head = new SkipNode<ElemType>(Max, tail, bottom);
    126 }
    127 
    128 template <typename ElemType>
    129 void DeterminSkipList<ElemType>::Clear()
    130 {
    131     ClearHelp(head->down);
    132     delete head;
    133     delete bottom;
    134     delete tail;
    135     head = NULL;
    136     bottom = NULL;
    137     tail = NULL;
    138 }
    139 
    140 template <typename ElemType>
    141 void DeterminSkipList<ElemType>::ClearHelp(SkipNode<ElemType> *current)
    142 {
    143     SkipNode<ElemType> *temp;
    144     if (current == bottom)
    145         return;
    146     ClearHelp(current->down);
    147     while (current != tail) {
    148         temp = current;
    149         current = current->right;
    150         delete temp;
    151     }
    152 }
    153 
    154 template <typename ElemType>
    155 inline bool DeterminSkipList<ElemType>::Search(const ElemType &value) const
    156 {
    157     return ((SearchHelp(value) == bottom) ? false : true ); 
    158 }
    159 
    160 template <typename ElemType>
    161 SkipNode<ElemType> * DeterminSkipList<ElemType>::
    162         SearchHelp(const ElemType &value) const
    163 {
    164     SkipNode<ElemType> *current;
    165 
    166     current = head;
    167     while (current != bottom) {
    168         while (value > current->key)
    169             current = current->right;
    170         if (current->down == bottom)
    171             return ((value == current->key) ? current : bottom);
    172         current = current->down;
    173     }
    174     return NULL;
    175 }
    176 
    177 /*
    178  * Insert a key value to the skip list.
    179  * if that the key value has already existed. 
    180  * return false and will not insert.  
    181  * else insert and return true.
    182  */
    183 template <typename ElemType>
    184 bool DeterminSkipList<ElemType>::Insert(const ElemType &value)
    185 {
    186     SkipNode<ElemType> *current, *new_node;
    187     
    188     current = head;
    189     bottom->key = value;
    190     bool can_insert = true;
    191     while (current != bottom) {
    192         while (value > current->key) 
    193             current = current->right;
    194         //if exists one elem whose key == value return false do not need insert
    195         if ((current->down == bottom) && (value == current->key)) {
    196             can_insert = false//can not insert but should check if need to adjust head before return
    197             break;
    198         }
    199         //if gap size is 3 or at bottom level and must insert 
    200         //then promote the middle element
    201         if ((current->down == bottom)
    202              || (current->key > current->down->right->right->key)) {
    203             new_node = new SkipNode<ElemType>;
    204             new_node->right = current->right; 
    205             new_node->down = current->down->right->right;
    206             current->right = new_node;
    207             new_node->key = current->key;
    208             current->key = current->down->right->key;
    209         }
    210         current = current->down;
    211     }
    212     //if need to raise the height of the skip list,raise it
    213     if (head->right != tail) {
    214         new_node = new SkipNode<ElemType>;
    215         new_node->down = head;
    216         new_node->right = tail;
    217         new_node->key = Max;
    218         head = new_node;
    219     }
    220 
    221     return can_insert;
    222 }
    223 template <typename ElemType>
    224 void DeterminSkipList<ElemType>::FindAndModifyRemoveHelp(const ElemType &value, const ElemType &other_value)
    225 {
    226     SkipNode<ElemType> *current;
    227 
    228     current = head;
    229     while (current != bottom) {
    230         while (value > current->key)
    231             current = current->right;
    232         if (value == current->key)
    233             current->key = other_value;
    234         current = current->down;
    235     }
    236 
    237 }
    238 template <typename ElemType>
    239 void DeterminSkipList<ElemType>::LowerHeadRemoveHelp()
    240 {
    241     SkipNode<ElemType> *temp;
    242     if (head->down->right == tail) {
    243         temp = head->down;
    244         head->down = temp->down;
    245         delete temp;
    246     }
    247 }
    248 template <typename ElemType>
    249 bool DeterminSkipList<ElemType>::Remove(const ElemType &value)
    250 {
    251     //empty list can not remove
    252     if (head->down == bottom)
    253         return false;
    254     //current node, previous node of current, start mark the begining of each level when the node goes down
    255     //if previous finally equal to start means have not advanced toward right on this level
    256     //next save the start position of the next level for current node
    257     SkipNode<ElemType> *current, *previous, *temp, *next;
    258 
    259     current = head->down;
    260     int visit_num = 0;
    261     bool can_remove = true
    262     for(;;) {  //loop and will return when curent->down == bottom
    263         previous = NULL;
    264         while (value > current->key) {   //try advance toward right as far as possible
    265             previous = current;
    266             current = current->right;
    267         }
    268         //visit num will mark if a node is a height 1 node 
    269         if (value == current->key)   
    270             visit_num++;
    271 
    272         //if on level 1 try to remove if possible and return
    273         if (current->down == bottom) {
    274             if (visit_num == 0) {       //can not find do not  need to remove
    275                 LowerHeadRemoveHelp(); ///might need to lower the head
    276                 can_remove = false;
    277                 return false;
    278             }
    279             else { //need to remove 
    280                 if(visit_num == 1) {  //if node height == 1 just remove it
    281                     //delete need to consider down fild of the upper level
    282                     //so swap current and current->right
    283                     temp = current->right; //to be deleted
    284                     current->key = current->right->key;
    285                     current->right = temp->right;
    286                     delete temp;
    287                     LowerHeadRemoveHelp(); ///might need to lower the head
    288                 } else {    
    289                     //if current node height > 1, swap the key with neighbour than delete the neighbour
    290                     //here swap with left neigbour,notice we must have advaced right on 
    291                     //this level otherwise it must be a height 1 node.
    292                     //we will find all the node with key value current->key and modify it 
    293                     //to previous->key
    294                     LowerHeadRemoveHelp(); //need to make sure the sturcture correct first
    295                     FindAndModifyRemoveHelp(current->key, previous->key); 
    296                     previous->right = current->right; 
    297                     delete current;
    298                 }
    299                 return true;
    300             }
    301         } 
    302         //on other levels ,not level 1
    303         //save the postion to go down on the lower level
    304         next = current->down;  //the next level will be unchaged when dealing the current level
    305         //current->key == current->down->right->key means the gap we want to down 
    306         //is of size only 1
    307         if (current->key == current->down->right->key) {
    308             //the first gap case, consider current gap and the next
    309             if (previous == NULL) {  //have not advanced on this level
    310                 //if the next gap has 2 or more one level lower element 
    311                 //one element need to lower down,the other one need to raise one level, 
    312                 //just swap do not need to delte space
    313                 if (current->right->key > current->right->down->right->key) {
    314                     current->key = current->right->down->key;
    315                     current->right->down = current->right->down->right;
    316                 } else {
    317                     //one element need to lower down,need to delete space
    318                     temp = current->right;
    319                     current->key = temp->key;
    320                     current->right = temp->right;
    321                     delete temp; 
    322                 }
    323             } else {    //not the first so consider the privious gap and the current
    324                 if (previous->key > previous->down->right->key) { 
    325                     temp = previous->down->right;
    326                     if (temp->right->key != previous->key)
    327                         temp = temp->right;
    328                     previous->key = temp->key;
    329                     current->down = temp->right;
    330                 } else {                       
    331                     previous->key = current->key;
    332                     previous->right = current->right;
    333                     delete current;
    334                 }
    335             }
    336         } 
    337         current = next; //go to the next level (one level lower)
    338     }
    339 }
    340 
    341 template <typename ElemType>
    342 bool DeterminSkipList<ElemType>::IsValid() const
    343 {
    344     SkipNode<ElemType> *current, *temp, *temp2;
    345     int gap_size;
    346 
    347     current = head;
    348     while (current->down != bottom) {
    349         temp = current;
    350         while (temp != tail) {
    351             temp2 = temp->down;
    352             gap_size = 0;
    353             while(temp2->key != temp->key) {
    354                 gap_size++;
    355                 temp2 = temp2->right;
    356             }
    357             if (gap_size < 1 || gap_size > 3)
    358                 return false;
    359             temp = temp->right;
    360         }
    361         current = current->down;
    362     }
    363     return true;
    364 }
    365 
    366 
    367 template <typename ElemType>
    368 void DeterminSkipList<ElemType>::Print() const 
    369 {
    370     using namespace std;
    371     SkipNode<ElemType> *current, *temp;
    372 
    373     current = head;
    374     while (current != bottom) {
    375         temp = current;
    376         while (temp != NULL) {
    377             if (temp != tail) {
    378                 cout << temp->key << "(" 
    379                      << temp->down->key << "";
    380                 temp = temp -> right;
    381             } else {
    382                 cout << temp->key << "[" 
    383                      << "tail" << "";
    384                 temp = NULL;
    385             }
    386         }
    387         cout << endl;
    388         current = current->down;
    389     }
    390     cout << endl;
    391 }
    392 
    393 
    394 //end fo namespace skip_list
    395 
    396 #endif //end of _DETERMIN_SKIP_LIST_H

    //123 skip list 的测试文件
     1 #include <iostream>
     2 #include <string>
     3 #include <fstream>
     4 
     5 #include "determin_skip_list.h"
     6 
     7 using namespace std;
     8 using namespace skip_list;
     9 
    10 /**
    11  * TestSkipList is the kernal test fuction of Insert,Search and Remove of a
    12  * determinstic skip list.
    13  * @param skip_list is the user created empty skip list for test
    14  * @param in is the ifstream relating to the opened file
    15  * @param out is the ofstream relating to the file to write result
    16  */
    17 template <typename T>
    18 void TestSkipList(DeterminSkipList<T> &skip_list, ifstream &in, ofstream &out
    19 {
    20     string op;
    21     string value;
    22     ///loop to get input and to corresponding operation on skip_list
    23     ///and write the result to the out put file
    24     while(in >> op >> value) {
    25         if (op == "INS") {
    26             if (skip_list.Insert(value))
    27                 out << op << " " << value << endl;
    28             else
    29                 out << "DUP" << " " << value << endl;
    30         } else if (op == "FIND") {
    31             if (skip_list.Search(value))
    32                 out << op << " " << value << endl;
    33             else
    34                 out << "NONE" << " " << value << endl;
    35         } else if (op == "REM") {
    36             if (skip_list.Remove(value))
    37                 out << op << " " << value << endl;
    38             else
    39                 out << "NONE" << " " << value << endl;
    40         }
    41         if (!skip_list.IsValid())
    42             cout << "not valid for " << op << " " << value << endl; 
    43     }
    44 }
    45 
    46 int main(int argc, char *argv[])
    47 {
    48     if (argc != 3) {
    49         cout << "Usage is : " 
    50              << "test_determin_skip_list <input_file> <output_file>" 
    51              << endl;
    52         return -1;
    53     }
    54     ///argv[1] the name of the file to open
    55     ///argv[2] the name of the file to wirte
    56     ifstream in(argv[1]);
    57     if (!in) {
    58         cout << "Could not find the file named "
    59              << argv[1<< " to open!"<< endl;
    60         return -1;
    61     }
    62     ofstream out(argv[2]);
    63     ///create a empty skip list key type is string,
    64     ///assumming for any input key value
    65     ///key value < Max < Max_1
    66     char a[2];
    67     a[0= char(254); a[1= '\0';
    68     const string Max(a);
    69     a[0= char(255);
    70     const string Max_1(a);
    71     DeterminSkipList<string> skip_list(Max, Max_1); 
    72 
    73     try {
    74         TestSkipList(skip_list, inout); ///The main test process
    75     } catch(std::bad_alloc&) { ///will exit if can not allocate more space
    76         cout << "no more available memory" << endl;
    77         in.close();
    78         out.close();
    79         return -1;
    80     }
    81 
    82     in.close();
    83     out.close();
    84     return 0;
    85 }
  • 相关阅读:
    软件开发模型
    Java学习--数组
    10年软件测试经验
    Log4net
    文件下载界面
    VB.NET中文双引号的处理方法
    SOAPUI使用
    .net数字转换成汉字大写
    SQL调用Webservices
    SQL大小写金额转换
  • 原文地址:https://www.cnblogs.com/rocketfan/p/1556797.html
Copyright © 2020-2023  润新知