zoukankan      html  css  js  c++  java
  • Implementing the skip list data structure in java --reference

    reference:http://www.mathcs.emory.edu/~cheung/Courses/323/Syllabus/Map/skip-list-impl.html

    • The link list element structure used to implement a Skip List
      • The link list element used to implement the skip list has 4 links (not including the data portion):




    • The Entry strcuture in a Skip List (the SkipListEntry class)
      • Skip List entry:
          public class SkipListEntry
          {
             public String key;
             public Integer value;
        
             public SkipListEntry up;       // up link
             public SkipListEntry down;     // down link
             public SkipListEntry left;     // left link
             public SkipListEntry right;    // right link        
               
             ...
             (methods)
          }
        

        Note:

        • As you can see, my entry type is again very specific (no generic types):
          • String key
          • Integer value             

        • When I write the demo program, I will do it using specific types (classes)not parameterized classes

          I have showed you how to convert a specific class into a parameterized class, so you can write one if you want to


        • Reason for using specific classes:
          • My choice is didactic in nature; I don't want to spend time analyzing the overly complex syntax of parameterized classes
          • I want to spend my time teaching algorithms, not Java syntax




    • Making (and using) the special −∞ and +∞ elements
      • Representing the −∞ element and the +∞ element:
        • The −∞ and the +∞ is just an ordinary Skip List Entry containing a special value for the key field.

      • We can accommodate the −∞ element and the +∞ element by defining 2 special key value:
          public class SkipListEntry
          {
             public String key;						     
             public Integer value;						     
        
             public SkipListEntry up, down, left, right;			     
          									
             public static String negInf = "-oo";  // -inf key value
             public static String posInf = "+oo";  // +inf key value
           
           
             ....
          }
        

      • How to instantiate a Skip List entry containing +∞:
             SkipListEntry x = new SkipListEntry( SkipListEntry.posInf, null );      
        

        How to check if an Skip List entry x contains +∞:

               key == SkipListEntry.posInf             
        




      OK, now we move on to the Skip list itself....





    • Structure (class) to represent a Skip List
      • Remember that a Skip List is a very complicated list

        But.... It is never the less a list

        • To represent a list, we only use a pointer (that points to the first element)
        • Often, we use more pointers for improve efficiency (such as a tail pointer)

      • Variables in the SkipList class:
           public class SkipList
           {
             public SkipListEntry head;    // First element of the top level
             public SkipListEntry tail;    // Last element of the top level
            
            
             public int n;                 // number of entries in the Skip List   
            
             public int h;       // Height
             public Random r;    // Coin toss
            
             ....
            
           }
        

        Note:

        • The Random object r is used to determine the height of a newly added entry           

          (We use r to simulate a coin toss experiment)


      • Example illustrating how the variables are used:

        Note:

        • Since the logical top level does not contain any entries:
          • The implementation will omit the logical top layer

        • The variables head and tail provide quick access to the end elements of the real top layer

          Usage of head and tail:

          • They allow us to easily add an new layer above the top layer




    • Constructing a Skip List object
      • The constructor will construct an empty Skip List which looks like this:
      • Constructor code:
          public SkipList()     // Constructor...
          {
             SkipListEntry p1, p2;
        
             /* -----------------------------------
                Create an -oo and an +oo object
        	----------------------------------- */
             p1 = new SkipListEntry(SkipListEntry.negInf, null);
             p2 = new SkipListEntry(SkipListEntry.posInf, null);
        
        
             /* --------------------------------------
                Link the -oo and +oo object together
        	--------------------------------------- */
             p1.right = p2;
             p2.left = p1;
        
             /* --------------------------------------
                Initialize "head" and "tail"
        	--------------------------------------- */
             head = p1;
             tail = p2;
        
             /* --------------------------------------
                Other initializations
        	--------------------------------------- */
             n = 0;                   // No entries in Skip List
             h = 0;		      // Height is 0
        
             r = new Random();	      // Make random object to simulate coin toss
          }
        

      • The SkipList class so far:
           public class SkipList
           {
             public SkipListEntry head;    // First element of the top level
             public SkipListEntry tail;    // Last element of the top level
            
             public int n;                 // number of entries in the Skip List    
            
             public int h;       // Height
             public Random r;    // Coin toss
            
             public SkipList()    // Constructor...
             {
           	SkipListEntry p1, p2;
            
           	p1 = new SkipListEntry(SkipListEntry.negInf, null);
           	p2 = new SkipListEntry(SkipListEntry.posInf, null);
            
           	head = p1;
           	tail = p2;
            
           	p1.right = p2;
           	p2.left = p1;
            
           	n = 0;
            
           	h = 0;
           	r = new Random();
             }
            
             ...
           }
        




    • Implementing the basic Map operations
      • Basic Map operations:
        • get()
        • put()
        • remove()            

        Notice that each basic operation must first find (search) the appropriate entry (using a key) before the operation can be completed.

        So we must learn how to search a Skip List for a given key first....





    • Search operation in a skip list
      • Consider the links traversed to locate the key 50:

      • Psuedo code:
        
           p = head;
        
           repeat
           {
        
              Move to the right until your right neighbor node         
              contains a key that is greater than k     
        
              if ( not lowest level )
                 Drop down one level
              else
                 exit
           }
        
        

      • Search algorithm for Skip List:
        
          /* ------------------------------------------------------
             findEntry(k): find the largest key x <= k
                           on the LOWEST level of the Skip List
             ------------------------------------------------------ */
        
          public SkipListEntry findEntry(String k)
          {
             SkipListEntry p;
        
             /* -----------------
                Start at "head"
                ----------------- */
             p = head;
        
             while ( true )
             {
                /* ------------------------------------------------
                   Search RIGHT until you find a LARGER entry
        
                   E.g.: k = 34
        
                             10 ---> 20 ---> 30 ---> 40
                                              ^
                                              |
                                              p must stop here
        		p.right.key = 40
                   ------------------------------------------------ */           
                while ( (p.right.key) != SkipListEntry.posInf &&
                        (p.right.key).compareTo(k) <= 0 )
                {
                   p = p.right;         // Move to right
                }
        
                /* ---------------------------------
                   Go down one level if you can...
                   --------------------------------- */
                if ( p.down != null )
                {  
                   p = p.down;          // Go downwards
                }
                else
        	{
                   break;       // We reached the LOWEST level... Exit...
                }
             }
        
             return(p);         // Note: p.key <= k
          }
        


      • Note:
        • If the key k is found in the Skip ListfindEntry(k) will return the reference to the entry containg the key k
        • If the key k is not found in the Skip ListfindEntry(k) will return the reference to the floorEntry(k) entry containg a key that issmaller than k

          Example: findEntry(42) will return the reference to 39:





    • Implementing the "get(Key k)" method
      • get(k):
          /** Returns the value associated with a key. */               
        
          public Integer get (String k)
          {
             SkipListEntry p;
        
             p = findEntry(k);
        
             if ( k.equals( p.key ) )
                return(p.value);
             else
                return(null);
          }
        








    • Put(k,v): inserting into a Skip List
      • Pseudo code for put(k,v):
            put(k, v)
            {
               SkipListEntry p;
        
               p = findEntry(k);
        
               if ( k.equals( p.key ) )    // Found !
               {
                  p.value = v;             // Update the value
        	  return;                  // Done
               }
        
               /* ==================================================
                  Not found.
        
        	  Then:   p == floorEntry(k) !!!
        	  ================================================== */       
        
               (1) insert (k,v)  AFTER  p
               (2) make a column of (k,v) of RANDOM height
            }
        


      • Recall what happens when we insert a new entry:
        • Before insertion:

        • After inserting key 42:

          Note:

          • As part of the insert operation, we will make a column (see figure above) for that key
          • The height of the column will be random...

            (We have also seen how to use a random "trial" to generate a random height)



      • Step-by-step depictions of the steps necessary for insertion: put("42", ??)
        • Before the insertion:

        • Step 1: find the insert position p = findEntry(k)

        • Step 2: insert q after p:




        • Now make a column of random heightrepeat these steps a random number of times
          • Starting at p, (using p to) scan left and find the first entry that has an up-entry:

            Make p point to the up-element:



          • Create a new entry with the same key (we are making the "tower"):

          • Insert the newly created entryright of p and up from q:

          • Make q point to the newly inserted entry (to continue the iteration if necessay)

        • I will repeat the steps and show the effect of building a "tower":
          • Starting at pscan left and find the first entry that has an up-element:

          • Create a new entry (we are making another level of the "tower"):

          • Insert the newly created entryright of p and up from q:

          • Make q point to the newly inserted entry (to continue the iteration if necessay)

            (And so on)


      • Note:
        • If the height of the "tower" is = h:

          we must add an new empty layer before we can insert another entry:





    • Adding a (empty) layer
      • Before we can do anything, We need to what are the changes in the Skip List when we add an empty layer to the Skip List:
        • Here is the Skip List before we add a new (empty) top layer:

        • Here is the Skip List before we add a new (empty) top layer:

      • Add layer algorithm:
           SkipListEntry p1, p2;
        
           /* -----------------------------
              Make the -oo and +oo entries
              ---------------------------- */
           p1 = new SkipListEntry(SkipListEntry.negInf, null);        
           p2 = new SkipListEntry(SkipListEntry.posInf, null);
        
           /* --------------------
              Link them
              -------------------- */
           p1.right = p2;
           p1.down  = head;
        
           p2.left = p1;
           p2.down = tail;
        
           head.up = p1;
           tail.up = p2;
        
           /* --------------------
              Update head and tail
              -------------------- */
           head = p1;
           tail = p2;
        
           h = h + 1;         // One more level...
        






    • The put() method
      • put(k,v) psuedo code:
        
             p = findEntry(k);         // Find insert location
        
             if ( entry found )
             {
                update the value in p;
        	exit;
             }
        
             /* ----------------------------------
                Insert a brand new entry (k,v)
        
                     p   put q here   
                     |     |
                     V     V
                    [ ] <------> [ ]
        	---------------------------------- */
        
              q = new Entry(k,v);            // Make new entry
              link q after p;
        
              /* ------------------------
                 Make a random tower...
        	 ------------------------ */
              while ( random() < 0.5 /* coin toss */ )
              {
                 if ( height of tower >= h )
        	 {
        	    create a new TOP layer (see: click here)
                 }
        
        	 p = Find the first left element in the next level above;       
        
        	 q = new Entry(k,v);
        	 link q after p;
              }
        



      • The put() method for Skip List in Java:
          public Integer put (String k, Integer v)
          {
             SkipListEntry p, q;
             int       i;
        
             p = findEntry(k);                  // Try find the entry
        
             /* ------------------------
                Check if key is found
                ------------------------ */
             if ( k.equals(p.key) )  // If key found, update the value and we are done...
             {
                Integer old = p.value;         // Remember the old value
        
                p.value = v;                   // Update value
        
                return(old);		       // Return the old value
             }
        
             /* -------------------------------------------------------------
                Key k is not found, then p = floorEntry(k) (See: click here)
        
                The rest of the code will insert a new entry (k,v)
                ------------------------------------------------------------- */
        
             q = new SkipListEntry(k,v);       // Create a new entry with k and v   
        
             /* --------------------------------------------------------------
                Insert q into the lowest level after SkipListEntry p:
        
                                 p   put q here           p        q
                                 |     |                  |        |
        		         V     V                  V        V        V
                Lower level:    [ ] <------> [ ]    ==>  [ ] <--> [ ] <--> [ ]
                --------------------------------------------------------------- */
             q.left = p;
             q.right = p.right;
             p.right.left = q;
             p.right = q;
        
             /* -----------------------------------------------------
                Make a "tower" of the entry e or RANDOM height
        	----------------------------------------------------- */
        
             i = 0;                   // Current level = 0
        
             while ( r.nextDouble() < 0.5 /* Coin toss */ )
             {
                // Coin toss success ! ---> build one more level !!!
        
                /* -------------------------------------------------------------------
        	   Check if we need to increase the height of the -oo and +oo "pillars
        	   ------------------------------------------------------------------- */
                if ( i >= h )   // We reached the top level !!!
                {
                   Create a new empty TOP layer (see: click here)
                   (Put the code from above here.... I left it out for brevity)
                }
        
                /* ------------------------------------
                   Find first element with an UP-link
                   ------------------------------------ */
                while ( p.up == null )
                {
                   p = p.left;
                }
        
        	/* --------------------------------
        	   Make p point to this UP element
        	   -------------------------------- */
                p = p.up;
        
        	/* ---------------------------------------------------
                   Add one more (k,*) to the column
        
        	   Schema for making the linkage:
        
                        p <--> e(k,*) <--> p.right
                                  ^
        		          |
        		          v
        		          q
        	   ---------------------------------------------------- */
           	SkipListEntry e;
           		 
           	e = new SkipListEntry(k, null);  // Don't need the value...
           		 
           	/* ---------------------------------------
           	   Initialize links of e
           	   --------------------------------------- */
           	e.left = p;
           	e.right = p.right;
           	e.down = q;
           		 
           	/* ---------------------------------------
           	   Change the neighboring links..
           	   --------------------------------------- */
           	p.right.left = e;
           	p.right = e;
           	q.up = e;
        
                q = e;       // Set q up for next iteration (if there is one)
                             // See here for more detail: click here
        
                i = i + 1;   // Current level increases by one
             }
        
             n = n + 1;      // One more entry in the Skip List
        
             return(null);   // No old value
          }
        

      • Example Program: (Demo above code)                                                 

        Example output: (The keys are strings)

         -  -  -  -  -  -  -  -  -  -
         10
         13
         15 15
         2
         21
         25
         31 31 31
         33 33 33 33 33 33 33 33 33 33
         36
         38
         39 39 39 39 39
         41 41 41
         42 42 42 42
         5 5 5
         54 54
         57
         59 59 59 59 59 59 59
         60 60
         63 63
         65
         69
         7
         71 71 71 71 71
         72
         77 77
         81
         82
         86
         88
         90
         92 92
         99
         +  +  +  +  +  +  +  +  +  +         
        




    • Deleting an entry from a Skip List
      • What you must do to the skip list to remove an entry:
        • Before deletinng the entry 25:

        • After deleting the entry 25:

          (The whole column containing entries for 25 must be deleted !!!)




      • Step-by-step to accomplish: remove(25)
        • Before the deletion:

        • Step 1: locate the desired element (at the lowest level of the skip list):

        • While p != null, repeat these steps to remove the column:
          • Unlink the element at p (by making the left neighbor and the right neighbor pointing to each other)

          • Move p upward (prepare for loop)


        • Result of removal:




    • The Removal Algorithm
      • Psuedo code:
           p = findExntry(k);
        
           if (p.key != k)
             return(null);     // Not found, don't remove
        
           /* ------------------------------------------------------------
              We are at level 0
              Travel up the tower and link the left and right neighbors
              ------------------------------------------------------------ */        
           while ( p != null )
           {
              p.left.right = p.right;
              p.right.left = p.left;
           }
        

        补充,jdk中有一个java.util.concurrent.ConcurrentSkipListMap,可以参考这个skiplist实现。

      • * @author Doug Lea
        * @param <K> the type of keys maintained by this map
        * @param <V> the type of mapped values
        * @since 1.6

  • 相关阅读:
    bootstrap select动态赋值与赋默认值
    json学习
    JsonObject学习遇到的一个奇葩的问题,当value为空时,key不见了
    servlet+jsp实现文件上传,和图片预览
    解决webstorm运行vue项目时不能同步的问题
    webStrom配置less且自动生成.css和自动压缩为.min.css
    怎么升级本地vue版本
    css这一段时间学习中遇到的比较有用,但是容易忘记的属性
    vue.js将unix时间戳转换为自定义时间格式
    文档碎片——createDocumentFragment
  • 原文地址:https://www.cnblogs.com/davidwang456/p/3620957.html
Copyright © 2011-2022 走看看