Skiplists were introduced by Pugh [60] who also presented
a number of applications and extensions of skiplists [59].  Since then they
have been studied extensively.  Several researchers have done very
precise analyses of the expected length and variance of the length of the
search path for the 
 th element in a skiplist [45,44,56].
Deterministic versions [53], biased versions [8,26],
and self-adjusting versions [12] of skiplists have all been
developed.  Skiplist implementations have been written for various
languages and frameworks and have been used in open-source database
systems [69,61]. A variant of skiplists is used in the HP-UX
operating system kernel's process management structures [42].
th element in a skiplist [45,44,56].
Deterministic versions [53], biased versions [8,26],
and self-adjusting versions [12] of skiplists have all been
developed.  Skiplist implementations have been written for various
languages and frameworks and have been used in open-source database
systems [69,61]. A variant of skiplists is used in the HP-UX
operating system kernel's process management structures [42].
 on the
 on the 
 in Figure 4.5.  Assume that
  in Figure 4.5.  Assume that 
 selects a height
  of 4 for the newly created node.
 selects a height
  of 4 for the newly created node.
 or a
 or a 
 operation, the expected
  number of pointers in a
 operation, the expected
  number of pointers in a 
 that get changed is constant.
 that get changed is constant.
 into
 into  based on a coin toss, we promote it with some probability
  based on a coin toss, we promote it with some probability  ,
, 
 .
.
  
 .
.
 that minimizes the preceding expression?
 that minimizes the preceding expression?
 method in a
 method in a 
 sometimes performs
  redundant comparisons; these occur when
 sometimes performs
  redundant comparisons; these occur when 
 is compared to the
  same value more than once.  They can occur when, for some node,
 is compared to the
  same value more than once.  They can occur when, for some node, 
 ,
,
  
![$ \ensuremath{\mathtt{u.next[r]}} = \ensuremath{\mathtt{u.next[r-1]}}$](img2339.png) .  Show how these redundant comparisons
  happen and modify
.  Show how these redundant comparisons
  happen and modify 
 so that they are avoided.  Analyze the
  expected number of comparisons done by your modified
 so that they are avoided.  Analyze the
  expected number of comparisons done by your modified 
 method.
 method.
 interface, but also allows fast access to elements by rank.
  That is, it also supports the function
 interface, but also allows fast access to elements by rank.
  That is, it also supports the function 
 , which returns the
  element whose rank is
, which returns the
  element whose rank is 
 in
 in 
 expected time. (The rank
  of an element
 expected time. (The rank
  of an element 
 in an
 in an 
 is the number of elements in the
 is the number of elements in the 
 that are less than
  that are less than 
 .)
.)
 in the
 in the 
 code on
  page
 code on
  page ![[*]](crossref.png) is a finger;  the shaded nodes in
  Figure 4.3 show the contents of the finger.)  One can
  think of a finger as pointing out the path to a node in the lowest
  list,
 is a finger;  the shaded nodes in
  Figure 4.3 show the contents of the finger.)  One can
  think of a finger as pointing out the path to a node in the lowest
  list,  .
.
A finger search implements the 
 operation using a
  finger, by walking up the list using the finger until reaching a node
 operation using a
  finger, by walking up the list using the finger until reaching a node
  
 such that
 such that 
 and
 and 
 or
 or 
 and then performing a normal search for
 and then performing a normal search for 
 starting from
 starting from 
 .
  It is possible to prove that the expected number of steps required
  for a finger search is
.
  It is possible to prove that the expected number of steps required
  for a finger search is 
 , where
, where  is the number values
  in
 is the number values
  in  between
 between 
 and the value pointed to by the finger.
 and the value pointed to by the finger.
Implement a subclass of 
 called
 called 
 that
  implements
 that
  implements 
 operations using an internal finger.  This subclass
  stores a finger, which is then used so that every
 operations using an internal finger.  This subclass
  stores a finger, which is then used so that every 
 operation
  is implemented as a finger search.  During each
 operation
  is implemented as a finger search.  During each 
 operation
  the finger is updated so that each
 operation
  the finger is updated so that each 
 operation uses, as a
  starting point, a finger that points to the result of the previous
 operation uses, as a
  starting point, a finger that points to the result of the previous
  
 operation.
 operation.
 , that truncates a
, that truncates a 
 at position
  at position 
 .  After the execution of this method, the size
  of the list is
.  After the execution of this method, the size
  of the list is 
 and it contains only the elements at indices
 and it contains only the elements at indices
  
 .  The return value is another
.  The return value is another 
 that
  contains the elements at indices
 that
  contains the elements at indices 
 .  This method
  should run in
.  This method
  should run in 
 time.
 time.
 method,
 method, 
 , that takes as an
  argument a
, that takes as an
  argument a 
 ,
, 
 , empties it and appends its contents,
  in order, to the receiver.  For example, if
, empties it and appends its contents,
  in order, to the receiver.  For example, if 
 contains
 contains  and
  and 
 contains
 contains  , then after calling
, then after calling 
 ,
, 
 will contain
  will contain 
 and
 and 
 will be empty. This method should
  run in
 will be empty. This method should
  run in 
 time.
 time.
 , design
  and implement a space-efficient
, design
  and implement a space-efficient 
 ,
, 
 .  To do this, store the
  data, in order, in an
.  To do this, store the
  data, in order, in an 
 , and store the blocks of this
, and store the blocks of this 
 in an
  in an 
 . If the original
. If the original 
 implementation uses
 implementation uses 
 space to store
  space to store 
 elements, then the
 elements, then the 
 will use enough space
  for
 will use enough space
  for 
 elements plus
 elements plus 
 wasted space.
 wasted space.
 as your underlying structure, design and implement an
  application that reads a (large) text file and allows you to search,
  interactively, for any substring contained in the text.  As the user
  types their query, a matching part of the text (if any) should appear 
  as a result.
 as your underlying structure, design and implement an
  application that reads a (large) text file and allows you to search,
  interactively, for any substring contained in the text.  As the user
  types their query, a matching part of the text (if any) should appear 
  as a result.
Hint 1: Every substring is a prefix of some suffix, so it suffices to store all suffixes of the text file.
Hint 2: Any suffix can be represented compactly as a single integer indicating where the suffix begins in the text.
Test your application on some large texts, such as some of the books available at Project Gutenberg [1]. If done correctly, your applications will be very responsive; there should be no noticeable lag between typing keystrokes and seeing the results.