All of lore.kernel.org
 help / color / mirror / Atom feed
* Split Trees (my design, similar to binary treaps)
@ 2003-05-08  4:22 Kevin Bealer
  2003-05-22 15:30 ` Hans Reiser
  0 siblings, 1 reply; 24+ messages in thread
From: Kevin Bealer @ 2003-05-08  4:22 UTC (permalink / raw)
  To: Hans Reiser, reiserfs-list; +Cc: jmacd, kevinbealer


Here is how 'Split Trees' work.

Each node has four components; Left, Right,
Value, and Level.  Every operation is the same
as a 'simple' binary tree except insert and
delete.

Need to preserve two invariants:
  1. Basic binary tree ordering invariant.
  2. No node's level is higher than its parent's.

Insert:

Basically, you select a 'level' for each node,
the same way you would in a skip list, i.e. half
the nodes are level 0, half the remaining are
level 1; 2^32 nodes implies 32 different levels.
No 'maximum level' has to be chosen initially.

If the node level is zero, insertion is exactly
the same as a 'simple' binary tree - traverse to
the bottom of the tree and attach to one side of
a bottom level leaf node.

Insertions of other nodes are more complex,
because that is where balancing is done.

Given a new node with value V and level N,
traverse down the tree until you get to a node
whose level is LESS than N.

To preserve the invariant, insert the new node
ABOVE the node which is of a lower level.

(If you look at only the subset of nodes of the
same or higher level as the new node, they form
a normal binary tree, rooted at the "top" node.
We are inserting a new leaf a the bottom of this
'subset' tree.)


Now we have the problem: what to do with the
node which we are inserting ABOVE.  We split it
into two halves - nodes which are less than (or
equal to) the new node in value, and nodes which
are higher in value.  This preserves the order
of the tree of course.

Suprisingly, splitting a binary tree is very
easy and can be done in O(ln n) time.

The split algorithm is conceptually simple.
There are two sides of the subtree which is
being split, the left half, and the right half,
with a jagged line down the middle.  This jagged
line will follow the pointers (edges) which we
would follow if we were to insert the new node
at the actual bottom-level leaf.

Now I introduce several terms: the left-receiver
and the right-receiver.  The left receiver is
where we attach nodes with values less than or
equal to V and the right is where we attach
nodes with values greater than V.  OLDTREE is
the tree we are splitting (it was attached where
newnode is now attached).  The 'disputed area'
is the subtree which contains nodes that may
belong in the left or right reciever.


At first, the left receiver is the Left side of
the NEWNODE, the right receiver is the RIGHT
side.  We attach the OLDTREE to whichever side
it belongs to (based on its value).

If OLDTREE->value is less than V, attach OLDTREE
to NEWNODE->left.  Then we need to split the new
'disputed area', which is OLDTREE->right, over
the new left and right receivers.  The right
receiver is still the same, but now the left
receiver is OLDTREE->right.

If the OLDTREE->value is greater than V, we do
the symmetric operation (switch R & L in the
paragraph above).

When you reach a NULL value for OLDTREE, you are
done - the division is complete.

There is a tiny wrinkle -- At first the left
receiver is the "left" pointer of NEWNODE, but
once a left-attachment is made, it is always a
"right" pointer, and vice versa.  Therefore,
there are four almost-identical "Split"
functions.
SplitLR() - calls down to SplitRR if it makes a
    Left attachment, otherwise calls SplitLL.

SplitRR() - recurses to SplitRR if it makes a
    Left attachment, otherwise calls SplitRL.

SplitLL() - calls SplitRL if it makes a Right
    attachment, otherwise recurses to SplitRL.

SplitRL() - always recurses to itself, because
    an attachment had been made to both sides
    of NEWNODE.

Actually, in the code the recursion has mostly
been removed because it was so easy to do.


Delete:

I haven't written the code for this yet, but
it should be trivial.

Deletion is basically the same as with a
'simple' binary tree.  Basically, replace the
node with the highest-valued node not higher
than V; or with the lowest-valued node not lower
than V.

The only trick is that you need to promote the
moved node to whatever level the deleted node
was, by assigning the deleted node's level to
its 'level' variable.

After a lot of deletion, the tree could become
biased with a lot of high level nodes.  This
is easy to prevent - when traversing the tree
during deletion, if you see a leaf node, lower
its level to zero (which is always a legal thing
to do).

For non-leaf nodes, demote them by one level if
they are 2 or more levels above both children.
This will 'comb out' the inequality, in an
amortized way.

I'll follow up with the code and an example
in two more emails.


Kevin



__________________________________
Do you Yahoo!?
The New Yahoo! Search - Faster. Easier. Bingo.
http://search.yahoo.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-05-08  4:22 Split Trees (my design, similar to binary treaps) Kevin Bealer
@ 2003-05-22 15:30 ` Hans Reiser
  2003-05-22 16:09   ` Alexander G. M. Smith
  2003-05-27  1:38   ` Enrique Perez-Terron
  0 siblings, 2 replies; 24+ messages in thread
From: Hans Reiser @ 2003-05-22 15:30 UTC (permalink / raw)
  To: Kevin Bealer; +Cc: reiserfs-list, jmacd

Forgive me for asking some bonehead questions.....

Are skip lists height balanced?  (All paths to the leaves are equal?)

Kevin Bealer wrote:

>Here is how 'Split Trees' work.
>
>Each node has four components; Left, Right,
>Value, and Level.  Every operation is the same
>as a 'simple' binary tree except insert and
>delete.
>
>Need to preserve two invariants:
>  1. Basic binary tree ordering invariant.
>  2. No node's level is higher than its parent's.
>
>Insert:
>
>Basically, you select a 'level' for each node,
>the same way you would in a skip list, i.e. half
>the nodes are level 0, half the remaining are
>level 1; 2^32 nodes implies 32 different levels.
>
How do you determine which level a node is?

>No 'maximum level' has to be chosen initially.
>
>If the node level is zero, insertion is exactly
>the same as a 'simple' binary tree - traverse to
>the bottom of the tree and attach to one side of
>a bottom level leaf node.
>
>Insertions of other nodes are more complex,
>because that is where balancing is done.
>
>Given a new node with value V and level N,
>traverse down the tree until you get to a node
>whose level is LESS than N.
>
>To preserve the invariant, insert the new node
>ABOVE the node which is of a lower level.
>
Interesting.  Also, this suggests that skip lists are not height 
balanced.....?

What is the average fan-out?  Is all data in leaves and are all pointers 
in internal nodes?

>
>(If you look at only the subset of nodes of the
>same or higher level as the new node, they form
>a normal binary tree, rooted at the "top" node.
>We are inserting a new leaf a the bottom of this
>'subset' tree.)
>
>
>Now we have the problem: what to do with the
>node which we are inserting ABOVE.  We split it
>into two halves - nodes which are less than (or
>equal to) the new node in value, and nodes which
>are higher in value.  This preserves the order
>of the tree of course.
>
>Suprisingly, splitting a binary tree is very
>easy and can be done in O(ln n) time.
>
Why does splitting of a tree not a node occur?

>
>The split algorithm is conceptually simple.
>There are two sides of the subtree which is
>being split, the left half, and the right half,
>with a jagged line down the middle.  This jagged
>line will follow the pointers (edges) which we
>would follow if we were to insert the new node
>at the actual bottom-level leaf.
>
>Now I introduce several terms: the left-receiver
>and the right-receiver.  The left receiver is
>where we attach nodes with values less than or
>equal to V and the right is where we attach
>nodes with values greater than V.  OLDTREE is
>the tree we are splitting (it was attached where
>newnode is now attached).  The 'disputed area'
>is the subtree which contains nodes that may
>belong in the left or right reciever.
>
>
>At first, the left receiver is the Left side of
>the NEWNODE, the right receiver is the RIGHT
>side.  We attach the OLDTREE to whichever side
>it belongs to (based on its value).
>
>If OLDTREE->value is less than V, attach OLDTREE
>to NEWNODE->left.  Then we need to split the new
>'disputed area', which is OLDTREE->right, over
>the new left and right receivers.  The right
>receiver is still the same, but now the left
>receiver is OLDTREE->right.
>
>If the OLDTREE->value is greater than V, we do
>the symmetric operation (switch R & L in the
>paragraph above).
>
>When you reach a NULL value for OLDTREE, you are
>done - the division is complete.
>
>There is a tiny wrinkle -- At first the left
>receiver is the "left" pointer of NEWNODE, but
>once a left-attachment is made, it is always a
>"right" pointer, and vice versa.  Therefore,
>there are four almost-identical "Split"
>functions.
>SplitLR() - calls down to SplitRR if it makes a
>    Left attachment, otherwise calls SplitLL.
>
>SplitRR() - recurses to SplitRR if it makes a
>    Left attachment, otherwise calls SplitRL.
>
>SplitLL() - calls SplitRL if it makes a Right
>    attachment, otherwise recurses to SplitRL.
>
>SplitRL() - always recurses to itself, because
>    an attachment had been made to both sides
>    of NEWNODE.
>
>Actually, in the code the recursion has mostly
>been removed because it was so easy to do.
>
>
>Delete:
>
>I haven't written the code for this yet, but
>it should be trivial.
>
>Deletion is basically the same as with a
>'simple' binary tree.  Basically, replace the
>node with the highest-valued node not higher
>than V; or with the lowest-valued node not lower
>than V.
>
>The only trick is that you need to promote the
>moved node to whatever level the deleted node
>was, by assigning the deleted node's level to
>its 'level' variable.
>
>After a lot of deletion, the tree could become
>biased with a lot of high level nodes.  This
>is easy to prevent - when traversing the tree
>during deletion, if you see a leaf node, lower
>its level to zero (which is always a legal thing
>to do).
>
>For non-leaf nodes, demote them by one level if
>they are 2 or more levels above both children.
>This will 'comb out' the inequality, in an
>amortized way.
>
>I'll follow up with the code and an example
>in two more emails.
>
>
>Kevin
>
>
>
>__________________________________
>Do you Yahoo!?
>The New Yahoo! Search - Faster. Easier. Bingo.
>http://search.yahoo.com
>
>
>  
>


-- 
Hans



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-05-22 15:30 ` Hans Reiser
@ 2003-05-22 16:09   ` Alexander G. M. Smith
  2003-05-22 17:16     ` Hans Reiser
  2003-05-27  1:38   ` Enrique Perez-Terron
  1 sibling, 1 reply; 24+ messages in thread
From: Alexander G. M. Smith @ 2003-05-22 16:09 UTC (permalink / raw)
  To: Hans Reiser; +Cc: reiserfs-list

Hans Reiser wrote on Thu, 22 May 2003 19:30:16 +0400:
> Forgive me for asking some bonehead questions.....
> 
> Are skip lists height balanced?  (All paths to the leaves are equal?)

Only on the average, at least in the original skip list algorithm.  The
height is determined randomly when the node is created; there is no
rebalancing.  The random distribution is defined as you would expect,
50% of the nodes have 1 level, 25% have 2 levels, ... 0.5**n of the
nodes have n levels.  Surprisingly, this works fairly well.

- Alex

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-05-22 16:09   ` Alexander G. M. Smith
@ 2003-05-22 17:16     ` Hans Reiser
  2003-05-22 20:21       ` Alexander G. M. Smith
  2003-05-23 19:24       ` Kevin Bealer
  0 siblings, 2 replies; 24+ messages in thread
From: Hans Reiser @ 2003-05-22 17:16 UTC (permalink / raw)
  To: Alexander G. M. Smith; +Cc: reiserfs-list

Alexander G. M. Smith wrote:

>Hans Reiser wrote on Thu, 22 May 2003 19:30:16 +0400:
>  
>
>>Forgive me for asking some bonehead questions.....
>>
>>Are skip lists height balanced?  (All paths to the leaves are equal?)
>>    
>>
>
>Only on the average, at least in the original skip list algorithm.  The
>height is determined randomly when the node is created; there is no
>rebalancing.  The random distribution is defined as you would expect,
>50% of the nodes have 1 level, 25% have 2 levels, ... 0.5**n of the
>nodes have n levels.  Surprisingly, this works fairly well.
>
>- Alex
>
>
>  
>
To have a level means to be on that level or lower?

-- 
Hans



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-05-22 17:16     ` Hans Reiser
@ 2003-05-22 20:21       ` Alexander G. M. Smith
  2003-05-22 22:48         ` Hans Reiser
  2003-05-23 19:24       ` Kevin Bealer
  1 sibling, 1 reply; 24+ messages in thread
From: Alexander G. M. Smith @ 2003-05-22 20:21 UTC (permalink / raw)
  To: Hans Reiser; +Cc: reiserfs-list

Hans Reiser wrote on Thu, 22 May 2003 21:16:15 +0400:
> Alexander G. M. Smith wrote:
> >Only on the average, at least in the original skip list algorithm.  The
> >height is determined randomly when the node is created; there is no
> >rebalancing.  The random distribution is defined as you would expect,
> >50% of the nodes have 1 level, 25% have 2 levels, ... 0.5**n of the
> >nodes have n levels.  Surprisingly, this works fairly well.
>
> To have a level means to be on that level or lower?

Yes, at least for skip lists.  A level n node has n next pointers
(or maybe n+1 if you are counting starting at zero) in the skip list.
All nodes have level 0 next node pointers (same as an ordinary linked
list).  Half of them have level 0 and level 1 pointers (level 1 pointers
point to the next node that is level 1 or higher, skipping past level 0
nodes - that's why it's a "skip list").  A quarter have level 2, 1, and 0
pointers.  In general, when you create a node, randomly determine its
level (rarely is infinite :-), allocate an array of pointers that big,
and thread it into the 0 to n different parallel level lists.  Of course,
the list head/tail endpoints have to have all n levels.

- Alex

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-05-22 20:21       ` Alexander G. M. Smith
@ 2003-05-22 22:48         ` Hans Reiser
  2003-05-22 23:27           ` Alexander G. M. Smith
  0 siblings, 1 reply; 24+ messages in thread
From: Hans Reiser @ 2003-05-22 22:48 UTC (permalink / raw)
  To: Alexander G. M. Smith; +Cc: reiserfs-list

Alexander G. M. Smith wrote:

>Hans Reiser wrote on Thu, 22 May 2003 21:16:15 +0400:
>  
>
>>Alexander G. M. Smith wrote:
>>    
>>
>>>Only on the average, at least in the original skip list algorithm.  The
>>>height is determined randomly when the node is created; there is no
>>>rebalancing.  The random distribution is defined as you would expect,
>>>50% of the nodes have 1 level, 25% have 2 levels, ... 0.5**n of the
>>>nodes have n levels.  Surprisingly, this works fairly well.
>>>      
>>>
>>To have a level means to be on that level or lower?
>>    
>>
>
>Yes, at least for skip lists.  A level n node has n next pointers
>(or maybe n+1 if you are counting starting at zero) in the skip list.
>All nodes have level 0 next node pointers (same as an ordinary linked
>list).  Half of them have level 0 and level 1 pointers (level 1 pointers
>point to the next node that is level 1 or higher, skipping past level 0
>nodes - that's why it's a "skip list").  A quarter have level 2, 1, and 0
>pointers.  In general, when you create a node, randomly determine its
>level (rarely is infinite :-), allocate an array of pointers that big,
>and thread it into the 0 to n different parallel level lists.  Of course,
>the list head/tail endpoints have to have all n levels.
>
>- Alex
>
>
>  
>
Do nodes contain both pointers and data?

-- 
Hans



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-05-22 22:48         ` Hans Reiser
@ 2003-05-22 23:27           ` Alexander G. M. Smith
  2003-05-23 18:56             ` Kevin Bealer
  0 siblings, 1 reply; 24+ messages in thread
From: Alexander G. M. Smith @ 2003-05-22 23:27 UTC (permalink / raw)
  To: Hans Reiser; +Cc: reiserfs-list

Hans Reiser wrote on Fri, 23 May 2003 02:48:05 +0400:
> Do nodes contain both pointers and data?

Yes, that's a common way of doing skip lists.  Or the node could contain
the level pointers and a data pointer.  The nodes are also awkwardly
variable sized due to the random number of levels.  That leads to
allocation fragmentation unless extra steps are taken.

I don't know how the split trees approach does it.

- Alex

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-05-22 23:27           ` Alexander G. M. Smith
@ 2003-05-23 18:56             ` Kevin Bealer
  2003-06-02 17:33               ` Hans Reiser
  0 siblings, 1 reply; 24+ messages in thread
From: Kevin Bealer @ 2003-05-23 18:56 UTC (permalink / raw)
  To: Alexander G. M. Smith, Hans Reiser; +Cc: reiserfs-list


As Alexander said, data can be in the node or
elsewhere in
either a skip list or skip tree.  Skip List nodes are
variable
sized; skip tree nodes are uniform, three pointers +
data.
(Unless the data is variable sized).

Skip Lists look like:

XX-----X-----X
X--X--X--X--X--X--X--X


--- "Alexander G. M. Smith" <agmsmith@rogers.com>
wrote:
> Hans Reiser wrote on Fri, 23 May 2003 02:48:05
> +0400:
> > Do nodes contain both pointers and data?
> 
> Yes, that's a common way of doing skip lists.  Or
> the node could contain
> the level pointers and a data pointer.  The nodes
> are also awkwardly
> variable sized due to the random number of levels. 
> That leads to
> allocation fragmentation unless extra steps are
> taken.
> 
> I don't know how the split trees approach does it.
> 
> - Alex


__________________________________
Do you Yahoo!?
The New Yahoo! Search - Faster. Easier. Bingo.
http://search.yahoo.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-05-22 17:16     ` Hans Reiser
  2003-05-22 20:21       ` Alexander G. M. Smith
@ 2003-05-23 19:24       ` Kevin Bealer
  2003-06-03 17:49         ` Hans Reiser
  1 sibling, 1 reply; 24+ messages in thread
From: Kevin Bealer @ 2003-05-23 19:24 UTC (permalink / raw)
  To: Hans Reiser, Alexander G. M. Smith; +Cc: reiserfs-list

Sorry, last message was accidentally sent prematurely.

To continue:

Skip lists (turned 90 degrees) look like:

topnode--x------x
C0
A1-----A1-----A1
C2
C3
B4-----B4
C5
A6-----A6-----A6
C7
C8
B9-----B9
C11
A12----A12----A12

With pointers vertically between all aligned letters
(conceptually at least).

Now here is the reason why SkipTrees do NOT need
variable sized nodes:

The Pointer from A1 to A6 is used, so is the pointer
from A1 to B4 and from B4 to C5.

However, the pointers from C2 and C3 to B4, B4 to A6,
and B9 to A12 are NEVER USED for example.  You are
sacrificing
pointers to get to a binary tree, but the pointers you
lose
are the pointers you don't need anyway.

In SkipList, you need those pointers only to copy
their value to
other pointers which will not be used.  The nodes
can't shrink,
because an insertion changes which pointers are used
and which
are not.

If * is a wildcard, the rule is:

No pointer from C* to B* or B* to A* is ever used.  If
you were
going to get to A6, you would have gotten there while
traversing
the "A" list, and if you are at the C list level, you
have already left 
the A and B lists behind.

To convert a Skip List to a Skip Tree, note that every
decision
you need to make is based on a NODE->VALUE comparison.
After each decision, processing can go in two
directions, so there
are two "edges" from that decision.

Decisions become binary tree nodes.  EDGES become left
and
right pointers.

The first decision in following the skip list is "Is
the search
value greater than "1" (i.e. node A1's value is 1). 
Thus the
top node of the Skip Tree is A1.  If the value is less
than 1,
we look at C0.  Thus C0 is on the left hand side of
A1.

Just traverse the skip list, and wherever you make a
decision
based on a value, there is a node.  Note that this
skip list is
not really balanced.  Due to the extra pointers, the
policy is
normally to have FEWER high-level nodes in a Skip List
than
would be predicted by the (1/2, 1/4, 1/8) progression
from the
bottom up.  Usually 3/4 on the bottom level, then 3/4
of the
remaining on the next level, etc.

With a skip tree, we actually want the balanced
version, i.e.
ratios of 1/2 on each level, although other ratios can
be used.

Kevin

--- Hans Reiser <reiser@namesys.com> wrote:
> Alexander G. M. Smith wrote:
> 
> >Hans Reiser wrote on Thu, 22 May 2003 19:30:16
> +0400:
> >  
> >
> >>Forgive me for asking some bonehead questions.....
> >>
> >>Are skip lists height balanced?  (All paths to the
> leaves are equal?)
> >>    
> >>
> >
> >Only on the average, at least in the original skip
> list algorithm.  The
> >height is determined randomly when the node is
> created; there is no
> >rebalancing.  The random distribution is defined as
> you would expect,
> >50% of the nodes have 1 level, 25% have 2 levels,
> ... 0.5**n of the
> >nodes have n levels.  Surprisingly, this works
> fairly well.
> >
> >- Alex
> >
> >
> >  
> >
> To have a level means to be on that level or lower?
> 
> -- 
> Hans
> 
> 


__________________________________
Do you Yahoo!?
The New Yahoo! Search - Faster. Easier. Bingo.
http://search.yahoo.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-05-22 15:30 ` Hans Reiser
  2003-05-22 16:09   ` Alexander G. M. Smith
@ 2003-05-27  1:38   ` Enrique Perez-Terron
  2003-05-27 20:47     ` Hans Reiser
  2003-05-28 16:44     ` Kevin Bealer
  1 sibling, 2 replies; 24+ messages in thread
From: Enrique Perez-Terron @ 2003-05-27  1:38 UTC (permalink / raw)
  To: reiserfs-list; +Cc: kevinbealer


Hello,

Prompted by this discussion I wrote some code to make sense of the
structures described, and they work wonderfully.

However, I found that in the split trees it is not necessary to
manipulate the levels of the remaining nodes after a deletion. It is
possible to reverse the effects of the split that occurs during
insertion; it is quite easy.

The reversal procedure merges two non-overlapping trees, the left and
right subtrees of the node that was removed. By non-overlapping I mean
that the largest key in the tree with small keys is smaller than the
smallest key in the other tree.

The procedure retains the desirable property of working downwards and
not looking back, so two processes could lock and update different parts
of the tree and propagate effects downwards, automatically avoiding
deadlocks. The procedure also avoids having to traverse entire subtrees
to update levels. It only touches nodes along the left edge of the right
subtree, and along the right edge of the left subtree. This should be
O(ln n).

The code can be found at http://home.online.no/~enrio/b3.c

Regards, Enrique


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-05-27  1:38   ` Enrique Perez-Terron
@ 2003-05-27 20:47     ` Hans Reiser
  2003-05-28 16:44     ` Kevin Bealer
  1 sibling, 0 replies; 24+ messages in thread
From: Hans Reiser @ 2003-05-27 20:47 UTC (permalink / raw)
  To: Enrique Perez-Terron; +Cc: reiserfs-list, kevinbealer

I am traveling, and so I will not participate in this thread for 7-10 
days....

-- 
Hans



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-05-27  1:38   ` Enrique Perez-Terron
  2003-05-27 20:47     ` Hans Reiser
@ 2003-05-28 16:44     ` Kevin Bealer
  1 sibling, 0 replies; 24+ messages in thread
From: Kevin Bealer @ 2003-05-28 16:44 UTC (permalink / raw)
  To: Enrique Perez-Terron; +Cc: reiserfs-list


Sounds great.  I thought that merging as you describe
might be possible but never figured out the details. 
(I haven't looked at
your code, I'll assume for now all works as
described).

Have you tested performance of merge-delete versus
simple
deletion?

Note that in my (simple delete with adjustments)
version you don't need to modify levels of the whole
tree, only the nodes on the path to the one you are
moving.  Asymptotically, this should keep the tree on
the correct average level.

If you don't adjust levels at all, I think the
performance cost would be small in practice.  But I
never actually implemented the delete in my version.

Kevin Bealer


--- Enrique Perez-Terron
<enrique.perez-terron@norway.online.no> wrote:
> 
> Hello,
> 
> Prompted by this discussion I wrote some code to
> make sense of the
> structures described, and they work wonderfully.
> 
> However, I found that in the split trees it is not
> necessary to
> manipulate the levels of the remaining nodes after a
> deletion. It is
> possible to reverse the effects of the split that
> occurs during
> insertion; it is quite easy.
> 
> The reversal procedure merges two non-overlapping
> trees, the left and
> right subtrees of the node that was removed. By
> non-overlapping I mean
> that the largest key in the tree with small keys is
> smaller than the
> smallest key in the other tree.
> 
> The procedure retains the desirable property of
> working downwards and
> not looking back, so two processes could lock and
> update different parts
> of the tree and propagate effects downwards,
> automatically avoiding
> deadlocks. The procedure also avoids having to
> traverse entire subtrees
> to update levels. It only touches nodes along the
> left edge of the right
> subtree, and along the right edge of the left
> subtree. This should be
> O(ln n).
> 
> The code can be found at
> http://home.online.no/~enrio/b3.c
> 
> Regards, Enrique
> 


__________________________________
Do you Yahoo!?
Yahoo! Calendar - Free online calendar with sync to Outlook(TM).
http://calendar.yahoo.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-05-23 18:56             ` Kevin Bealer
@ 2003-06-02 17:33               ` Hans Reiser
  2003-06-04  4:54                 ` Kevin Bealer
  0 siblings, 1 reply; 24+ messages in thread
From: Hans Reiser @ 2003-06-02 17:33 UTC (permalink / raw)
  To: Kevin Bealer, ReiserFS

Kevin Bealer wrote:

>As Alexander said, data can be in the node or
>elsewhere in
>either a skip list or skip tree.  Skip List nodes are
>variable
>sized; skip tree nodes are uniform, three pointers +
>data.
>(Unless the data is variable sized).
>
>Skip Lists look like:
>
>XX-----X-----X
>X--X--X--X--X--X--X--X
>
>
>--- "Alexander G. M. Smith" <agmsmith@rogers.com>
>wrote:
>  
>
>>Hans Reiser wrote on Fri, 23 May 2003 02:48:05
>>+0400:
>>    
>>
>>>Do nodes contain both pointers and data?
>>>      
>>>
>>Yes, that's a common way of doing skip lists.  Or
>>the node could contain
>>the level pointers and a data pointer.  The nodes
>>are also awkwardly
>>variable sized due to the random number of levels. 
>>That leads to
>>allocation fragmentation unless extra steps are
>>taken.
>>
>>I don't know how the split trees approach does it.
>>
>>- Alex
>>    
>>
>
>
>__________________________________
>Do you Yahoo!?
>The New Yahoo! Search - Faster. Easier. Bingo.
>http://search.yahoo.com
>
>
>  
>
So the fanout of a skip tree is 3?  (Just got back from Italy.....)

-- 
Hans



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-05-23 19:24       ` Kevin Bealer
@ 2003-06-03 17:49         ` Hans Reiser
  2003-06-04  5:17           ` Enrique Perez-Terron
  2003-06-04  5:22           ` Kevin Bealer
  0 siblings, 2 replies; 24+ messages in thread
From: Hans Reiser @ 2003-06-03 17:49 UTC (permalink / raw)
  To: Kevin Bealer; +Cc: Alexander G. M. Smith, reiserfs-list

Kevin Bealer wrote:

>Sorry, last message was accidentally sent prematurely.
>
>To continue:
>
>Skip lists (turned 90 degrees) look like:
>
>topnode--x------x
>C0
>A1-----A1-----A1
>C2
>C3
>B4-----B4
>C5
>A6-----A6-----A6
>C7
>C8
>B9-----B9
>C11
>A12----A12----A12
>
>With pointers vertically between all aligned letters
>(conceptually at least).
>
I don't understand the diagram above, which means I don't understand the 
rest.  I think you are explaining something you understand too well to 
explain....;-)

>
>Now here is the reason why SkipTrees do NOT need
>variable sized nodes:
>
>The Pointer from A1 to A6 is used, so is the pointer
>from A1 to B4 and from B4 to C5.
>
>However, the pointers from C2 and C3 to B4, B4 to A6,
>and B9 to A12 are NEVER USED for example.  You are
>sacrificing
>pointers to get to a binary tree, but the pointers you
>lose
>are the pointers you don't need anyway.
>
>In SkipList, you need those pointers only to copy
>their value to
>other pointers which will not be used.  The nodes
>can't shrink,
>because an insertion changes which pointers are used
>and which
>are not.
>
>If * is a wildcard, the rule is:
>
>No pointer from C* to B* or B* to A* is ever used.  If
>you were
>going to get to A6, you would have gotten there while
>traversing
>the "A" list, and if you are at the C list level, you
>have already left 
>the A and B lists behind.
>
>To convert a Skip List to a Skip Tree, note that every
>decision
>you need to make is based on a NODE->VALUE comparison.
>After each decision, processing can go in two
>directions, so there
>are two "edges" from that decision.
>
>Decisions become binary tree nodes.  EDGES become left
>and
>right pointers.
>
>The first decision in following the skip list is "Is
>the search
>value greater than "1" (i.e. node A1's value is 1). 
>Thus the
>top node of the Skip Tree is A1.  If the value is less
>than 1,
>we look at C0.  Thus C0 is on the left hand side of
>A1.
>
>Just traverse the skip list, and wherever you make a
>decision
>based on a value, there is a node.  Note that this
>skip list is
>not really balanced.  Due to the extra pointers, the
>policy is
>normally to have FEWER high-level nodes in a Skip List
>than
>would be predicted by the (1/2, 1/4, 1/8) progression
>from the
>bottom up.  Usually 3/4 on the bottom level, then 3/4
>of the
>remaining on the next level, etc.
>
>With a skip tree, we actually want the balanced
>version, i.e.
>ratios of 1/2 on each level, although other ratios can
>be used.
>
>Kevin
>
>--- Hans Reiser <reiser@namesys.com> wrote:
>  
>
>>Alexander G. M. Smith wrote:
>>
>>    
>>
>>>Hans Reiser wrote on Thu, 22 May 2003 19:30:16
>>>      
>>>
>>+0400:
>>    
>>
>>> 
>>>
>>>      
>>>
>>>>Forgive me for asking some bonehead questions.....
>>>>
>>>>Are skip lists height balanced?  (All paths to the
>>>>        
>>>>
>>leaves are equal?)
>>    
>>
>>>>   
>>>>
>>>>        
>>>>
>>>Only on the average, at least in the original skip
>>>      
>>>
>>list algorithm.  The
>>    
>>
>>>height is determined randomly when the node is
>>>      
>>>
>>created; there is no
>>    
>>
>>>rebalancing.  The random distribution is defined as
>>>      
>>>
>>you would expect,
>>    
>>
>>>50% of the nodes have 1 level, 25% have 2 levels,
>>>      
>>>
>>... 0.5**n of the
>>    
>>
>>>nodes have n levels.  Surprisingly, this works
>>>      
>>>
>>fairly well.
>>    
>>
>>>- Alex
>>>
>>>
>>> 
>>>
>>>      
>>>
>>To have a level means to be on that level or lower?
>>
>>-- 
>>Hans
>>
>>
>>    
>>
>
>
>__________________________________
>Do you Yahoo!?
>The New Yahoo! Search - Faster. Easier. Bingo.
>http://search.yahoo.com
>
>
>  
>


-- 
Hans



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-06-02 17:33               ` Hans Reiser
@ 2003-06-04  4:54                 ` Kevin Bealer
  0 siblings, 0 replies; 24+ messages in thread
From: Kevin Bealer @ 2003-06-04  4:54 UTC (permalink / raw)
  To: Hans Reiser, ReiserFS


Sorry, I misspoke.  A SkipTree contains two pointers
down, a number from 1 to L, plus the data.  Fanout is
two, the 'third pointer' is really L, which probably
won't have to be larger than one byte (but would be
aligned to pointer size in practice.)

Normally, N would be no more than the log based 2 of
the max number of elements.  One byte should therefore
be enough for 2^256 elements.

Kevin

--- Hans Reiser <reiser@namesys.com> wrote:
> Kevin Bealer wrote:
> 
> >As Alexander said, data can be in the node or
> >elsewhere in
> >either a skip list or skip tree.  Skip List nodes
> are
> >variable
> >sized; skip tree nodes are uniform, three pointers
> +
> >data.
> >(Unless the data is variable sized).
> >
> >Skip Lists look like:
> >
> >XX-----X-----X
> >X--X--X--X--X--X--X--X
> >
> >
> >--- "Alexander G. M. Smith" <agmsmith@rogers.com>
> >wrote:
> >  
> >
> >>Hans Reiser wrote on Fri, 23 May 2003 02:48:05
> >>+0400:
> >>    
> >>
> >>>Do nodes contain both pointers and data?
> >>>      
> >>>
> >>Yes, that's a common way of doing skip lists.  Or
> >>the node could contain
> >>the level pointers and a data pointer.  The nodes
> >>are also awkwardly
> >>variable sized due to the random number of levels.
> 
> >>That leads to
> >>allocation fragmentation unless extra steps are
> >>taken.
> >>
> >>I don't know how the split trees approach does it.
> >>
> >>- Alex
> >>    
> >>
> >
> >
> >__________________________________
> >Do you Yahoo!?
> >The New Yahoo! Search - Faster. Easier. Bingo.
> >http://search.yahoo.com
> >
> >
> >  
> >
> So the fanout of a skip tree is 3?  (Just got back
> from Italy.....)
> 
> -- 
> Hans
> 
> 


__________________________________
Do you Yahoo!?
Yahoo! Calendar - Free online calendar with sync to Outlook(TM).
http://calendar.yahoo.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-06-03 17:49         ` Hans Reiser
@ 2003-06-04  5:17           ` Enrique Perez-Terron
  2003-06-04  9:40             ` Hans Reiser
  2003-06-04  5:22           ` Kevin Bealer
  1 sibling, 1 reply; 24+ messages in thread
From: Enrique Perez-Terron @ 2003-06-04  5:17 UTC (permalink / raw)
  To: Hans Reiser; +Cc: Kevin Bealer, Alexander G. M. Smith, reiserfs-list

On Tue, 2003-06-03 at 19:49, Hans Reiser wrote:
> Kevin Bealer wrote:

> >Skip lists (turned 90 degrees) look like:
> >
> >topnode--x------x
> >C0
> >A1-----A1-----A1
> >C2
> >C3
> >B4-----B4
> >C5
> >A6-----A6-----A6
> >C7
> >C8
> >B9-----B9
> >C11
> >A12----A12----A12
> >
> >With pointers vertically between all aligned letters
> >(conceptually at least).

> I don't understand the diagram above, which means I don't understand the 
> rest.  I think you are explaining something you understand too well to 
> explain....;-)

This is a skip list. 

Each line in the diagram represents a single node.

Each node is given a randomly chosen "level", a small number. A node
never changes level in its lifetime. Diagram lines with three items,
like A6---A6---A6, are level three nodes. All level three nodes are here
shown with the letter A, level two nodes with B, etc.

The vertical order of the node is that of the keys, i.e., the nodes are
shown sorted by key. The number 6 in "A6" corresponds to key number 6.

There is potentially no limit to the number of levels. Practically, it
is limited by the implementors expectation of maximal number of nodes.
(If the list grows larger than expected the skip list will still work,
but perform gradually worse than it would with a higher number of
levels.)

The columns of the diagram represent linked lists. The rightmost linked
list links only the A nodes. The middle linked list links the A and the
B nodes. Nodes of level n are members of n distinct lists. The order of
the nodes in the lists is that of the keys.

By the way the levels are chosen, there will normally be just 1-3 nodes
in the rightmost list. This list could be compared to the root node of a
B-tree. The next lower level list has on average twice as many nodes.
(Actually, this is a design parameter.) This means that walking down the
second list, starting from an A node, there are on average 1 B-node
before the next A node. Since the assignment of levels is random there
is no upper limit, but more than three happens only once in 16 cases,
etc.

To locate a particular node, say C5, by key, you could scan the leftmost
list linearly, but that would be O(N). Instead you can start scanning
the rightmost list. When you reach A6 you notice that you are too far,
so you back up to A1. Then you continue down the middle list, etc. This
traversal is actually quite similar to B-tree traversal, where scanning
the B nodes between A1 and A6 corresponds to scanning a B-tree node
below the root, and scanning the Cs between two Bs corresponds to
scanning a B-tree node two levels below the root.

> >
> >Now here is the reason why SkipTrees do NOT need
> >variable sized nodes:
> >
> >The Pointer from A1 to A6 is used, so is the pointer
> >from A1 to B4 and from B4 to C5.
> >
> >However, the pointers from C2 and C3 to B4, B4 to A6,
> >and B9 to A12 are NEVER USED for example.  You are

Well, from C2 to C3 _is_ used, since there is no B node between them.

> >sacrificing
> >pointers to get to a binary tree, but the pointers you
> >lose
> >are the pointers you don't need anyway.
> >
> >In SkipList, you need those pointers only to copy
> >their value to
> >other pointers which will not be used.  The nodes
> >can't shrink,
> >because an insertion changes which pointers are used
> >and which
> >are not.
> >
> >If * is a wildcard, the rule is:
> >
> >No pointer from C* to B* or B* to A* is ever used.  If
> >you were
> >going to get to A6, you would have gotten there while
> >traversing
> >the "A" list, and if you are at the C list level, you
> >have already left 
> >the A and B lists behind.
> >
> >To convert a Skip List to a Skip Tree, note that every
> >decision
> >you need to make is based on a NODE->VALUE comparison.
> >After each decision, processing can go in two
> >directions, so there
> >are two "edges" from that decision.
> >
> >Decisions become binary tree nodes.  EDGES become left
> >and
> >right pointers.
> >
> >The first decision in following the skip list is "Is
> >the search
> >value greater than "1" (i.e. node A1's value is 1). 
> >Thus the
> >top node of the Skip Tree is A1.  If the value is less
> >than 1,
> >we look at C0.  Thus C0 is on the left hand side of
> >A1.
> >
> >Just traverse the skip list, and wherever you make a
> >decision
> >based on a value, there is a node.  Note that this
> >skip list is
> >not really balanced.  Due to the extra pointers, the
> >policy is
> >normally to have FEWER high-level nodes in a Skip List
> >than
> >would be predicted by the (1/2, 1/4, 1/8) progression
> >from the
> >bottom up.  Usually 3/4 on the bottom level, then 3/4
> >of the
> >remaining on the next level, etc.
> >
> >With a skip tree, we actually want the balanced
> >version, i.e.
> >ratios of 1/2 on each level, although other ratios can
> >be used.
> >
> >Kevin

Regards, Enrique


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-06-03 17:49         ` Hans Reiser
  2003-06-04  5:17           ` Enrique Perez-Terron
@ 2003-06-04  5:22           ` Kevin Bealer
  2003-06-04  9:44             ` Hans Reiser
  1 sibling, 1 reply; 24+ messages in thread
From: Kevin Bealer @ 2003-06-04  5:22 UTC (permalink / raw)
  To: Hans Reiser; +Cc: Alexander G. M. Smith, reiserfs-list


>Hans Reiser <reiser@namesys.com> wrote:
> Kevin Bealer wrote:
> 
> >Sorry, last message was accidentally sent
> prematurely.
> >
> >To continue:
> >
> >Skip lists (turned 90 degrees) look like:
> >
> >topnode--x------x
> >C0
> >A1-----A1-----A1
> >C2
> >C3
> >B4-----B4
> >C5
> >A6-----A6-----A6
> >C7
> >C8
> >B9-----B9
> >C11
> >A12----A12----A12
> >
> >With pointers vertically between all aligned
> letters
> >(conceptually at least).
> >
> I don't understand the diagram above, which means I
> don't understand the 
> rest.  I think you are explaining something you
> understand too well to 
> explain....;-)


Yes, probably.  Sorry about that;  I was trying to
make a diagram that works with variable sized type.

Each line of the diagram is a node of the skip list.

The 'topnode' is the header of the skip list, which
typically looks like a skip node of the maximum
node size with no data.

Nodes with one pointer are 'C#' here, nodes with
two pointers are 'B#', nodes with three are 'A#'.
The '#' is the data value of the node (or the key,
if it is a multiset).

In the skip list, node A1 is a node with three
pointers, to C1, B2, and A6.  Each of these must
have a value greater or equal to A1, to preserve
the invariant, which is that the list at each
level is an ordered list.  In this case the list
at level 3 is the list containing A's and chained
in the third pointer.  The list using the second 
pointer contains A's, and B's.  The list at the
first level, represented here as character column
1 in the diagram, is the first level list, it 
contains all the nodes.

The argument I am making is not essential, it is
only that some of these pointers are unnecessary,
which leads to the Split Tree.

A different organization of pointers, and we have
the same search ORDER, but with slightly different
internal connections; plus all nodes are the same
size, and all normal 'binary tree' based algorithms
work as expected.

If you understand the Skip List, you can see every
location where a decision is made by comparing the
search value to the value of a node.  Running through 
these by hand, I was able to use these decisions as
binary tree traversal decisions, and create a binary
tree that has the same traversal behavior as a skip
list.

In doing so, I realized that the pointers which were
from a low level node to a high level node are not
consulted.  It looks good to have them because then
we have a set of ordered lists at each level, but
they don't actually get traversed in searches.

Anyway, its sort of a 'theory' argument to explain
why Split Tree is possible even though it seems like
you can't safely do this to a Skip List.

Does that help or am I still babbling? ;)

Kevin

> 
> >
> >Now here is the reason why SkipTrees do NOT need
> >variable sized nodes:
> >
> >The Pointer from A1 to A6 is used, so is the
> pointer
> >from A1 to B4 and from B4 to C5.
> >
> >However, the pointers from C2 and C3 to B4, B4 to
> A6,
> >and B9 to A12 are NEVER USED for example.  You are
> >sacrificing
> >pointers to get to a binary tree, but the pointers
> you
> >lose
> >are the pointers you don't need anyway.
> >
> >In SkipList, you need those pointers only to copy
> >their value to
> >other pointers which will not be used.  The nodes
> >can't shrink,
> >because an insertion changes which pointers are
> used
> >and which
> >are not.
> >
> >If * is a wildcard, the rule is:
> >
> >No pointer from C* to B* or B* to A* is ever used. 
> If
> >you were
> >going to get to A6, you would have gotten there
> while
> >traversing
> >the "A" list, and if you are at the C list level,
> you
> >have already left 
> >the A and B lists behind.
> >
> >To convert a Skip List to a Skip Tree, note that
> every
> >decision
> >you need to make is based on a NODE->VALUE
> comparison.
> >After each decision, processing can go in two
> >directions, so there
> >are two "edges" from that decision.
> >
> >Decisions become binary tree nodes.  EDGES become
> left
> >and
> >right pointers.
> >
> >The first decision in following the skip list is
> "Is
> >the search
> >value greater than "1" (i.e. node A1's value is 1).
> 
> >Thus the
> >top node of the Skip Tree is A1.  If the value is
> less
> >than 1,
> >we look at C0.  Thus C0 is on the left hand side of
> >A1.
> >
> >Just traverse the skip list, and wherever you make
> a
> >decision
> >based on a value, there is a node.  Note that this
> >skip list is
> >not really balanced.  Due to the extra pointers,
> the
> >policy is
> >normally to have FEWER high-level nodes in a Skip
> List
> >than
> >would be predicted by the (1/2, 1/4, 1/8)
> progression
> >from the
> >bottom up.  Usually 3/4 on the bottom level, then
> 3/4
> >of the
> >remaining on the next level, etc.
> >
> >With a skip tree, we actually want the balanced
> >version, i.e.
> >ratios of 1/2 on each level, although other ratios
> can
> >be used.
> >
> >Kevin
> >
> >--- Hans Reiser <reiser@namesys.com> wrote:
> >  
> >
> >>Alexander G. M. Smith wrote:
> >>
> >>    
> >>
> >>>Hans Reiser wrote on Thu, 22 May 2003 19:30:16
> >>>      
> >>>
> >>+0400:
> >>    
> >>
> >>> 
> >>>
> >>>      
> >>>
> >>>>Forgive me for asking some bonehead
> questions.....
> >>>>
> >>>>Are skip lists height balanced?  (All paths to
> the
> >>>>        
> >>>>
> >>leaves are equal?)
> >>    
> >>
> >>>>   
> >>>>
> >>>>        
> >>>>
> >>>Only on the average, at least in the original
> skip
> >>>      
> >>>
> >>list algorithm.  The
> >>    
> >>
> >>>height is determined randomly when the node is
> >>>      
> >>>
> >>created; there is no
> >>    
> >>
> >>>rebalancing.  The random distribution is defined
> as
> >>>      
> >>>
> >>you would expect,
> >>    
> >>
> >>>50% of the nodes have 1 level, 25% have 2 levels,
> >>>      
> >>>
> >>... 0.5**n of the
> >>    
> >>
> >>>nodes have n levels.  Surprisingly, this works
> >>>      
> >>>
> >>fairly well.
> >>    
> >>
> >>>- Alex
> >>>
> >>>
> >>> 
> >>>
> >>>      
> >>>
> >>To have a level means to be on that level or
> lower?
> >>
> >>-- 
> >>Hans
> >>
> 
=== message truncated ===


__________________________________
Do you Yahoo!?
Yahoo! Calendar - Free online calendar with sync to Outlook(TM).
http://calendar.yahoo.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-06-04  5:17           ` Enrique Perez-Terron
@ 2003-06-04  9:40             ` Hans Reiser
  2003-06-05 22:34               ` Enrique Perez-Terron
  2003-06-08  5:20               ` Kevin Bealer
  0 siblings, 2 replies; 24+ messages in thread
From: Hans Reiser @ 2003-06-04  9:40 UTC (permalink / raw)
  To: Enrique Perez-Terron; +Cc: Kevin Bealer, Alexander G. M. Smith, reiserfs-list

So if I understand right, the level is determined by what the key is.  
Suppose that for key K the determined level is 3, but there are no other 
records in the tree?  Is K then stored at a node at level 1 until such 
time as a level 1 key is created for it to be attached to, or does one 
create empty level 1 and level 2 nodes?

-- 
Hans



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-06-04  5:22           ` Kevin Bealer
@ 2003-06-04  9:44             ` Hans Reiser
  2003-06-08  5:17               ` Kevin Bealer
  0 siblings, 1 reply; 24+ messages in thread
From: Hans Reiser @ 2003-06-04  9:44 UTC (permalink / raw)
  To: Kevin Bealer; +Cc: Alexander G. M. Smith, reiserfs-list

Kevin Bealer wrote:

>>Hans Reiser <reiser@namesys.com> wrote:
>>Kevin Bealer wrote:
>>
>>    
>>
>>>Sorry, last message was accidentally sent
>>>      
>>>
>>prematurely.
>>    
>>
>>>To continue:
>>>
>>>Skip lists (turned 90 degrees) look like:
>>>
>>>topnode--x------x
>>>C0
>>>A1-----A1-----A1
>>>C2
>>>C3
>>>B4-----B4
>>>C5
>>>A6-----A6-----A6
>>>C7
>>>C8
>>>B9-----B9
>>>C11
>>>A12----A12----A12
>>>
>>>With pointers vertically between all aligned
>>>      
>>>
>>letters
>>    
>>
>>>(conceptually at least).
>>>
>>>      
>>>
>>I don't understand the diagram above, which means I
>>don't understand the 
>>rest.  I think you are explaining something you
>>understand too well to 
>>explain....;-)
>>    
>>
>
>
>Yes, probably.  Sorry about that;  I was trying to
>make a diagram that works with variable sized type.
>
>Each line of the diagram is a node of the skip list.
>
>The 'topnode' is the header of the skip list, which
>typically looks like a skip node of the maximum
>node size with no data.
>
>Nodes with one pointer are 'C#' here, nodes with
>two pointers are 'B#', nodes with three are 'A#'.
>The '#' is the data value of the node (or the key,
>if it is a multiset).
>
>In the skip list, node A1 is a node with three
>pointers, to C1, B2, and A6.
>

C1 and B2 are not in your diagram....

>  Each of these must
>have a value greater or equal to A1, to preserve
>the invariant, which is that the list at each
>level is an ordered list.  In this case the list
>at level 3 is the list containing A's and chained
>in the third pointer.  The list using the second 
>pointer contains A's, and B's.  The list at the
>first level, represented here as character column
>1 in the diagram, is the first level list, it 
>contains all the nodes.
>
>The argument I am making is not essential, it is
>only that some of these pointers are unnecessary,
>which leads to the Split Tree.
>
>A different organization of pointers, and we have
>the same search ORDER, but with slightly different
>internal connections; plus all nodes are the same
>size, and all normal 'binary tree' based algorithms
>work as expected.
>
>If you understand the Skip List, you can see every
>location where a decision is made by comparing the
>search value to the value of a node.  Running through 
>these by hand, I was able to use these decisions as
>binary tree traversal decisions, and create a binary
>tree that has the same traversal behavior as a skip
>list.
>
>In doing so, I realized that the pointers which were
>from a low level node to a high level node are not
>consulted.  It looks good to have them because then
>we have a set of ordered lists at each level, but
>they don't actually get traversed in searches.
>
>Anyway, its sort of a 'theory' argument to explain
>why Split Tree is possible even though it seems like
>you can't safely do this to a Skip List.
>
>Does that help or am I still babbling? ;)
>
>Kevin
>
>  
>
>>>Now here is the reason why SkipTrees do NOT need
>>>variable sized nodes:
>>>
>>>The Pointer from A1 to A6 is used, so is the
>>>      
>>>
>>pointer
>>>from A1 to B4 and from B4 to C5.
>>    
>>
>>>However, the pointers from C2 and C3 to B4, B4 to
>>>      
>>>
>>A6,
>>    
>>
>>>and B9 to A12 are NEVER USED for example.  You are
>>>sacrificing
>>>pointers to get to a binary tree, but the pointers
>>>      
>>>
>>you
>>    
>>
>>>lose
>>>are the pointers you don't need anyway.
>>>
>>>In SkipList, you need those pointers only to copy
>>>their value to
>>>other pointers which will not be used.  The nodes
>>>can't shrink,
>>>because an insertion changes which pointers are
>>>      
>>>
>>used
>>    
>>
>>>and which
>>>are not.
>>>
>>>If * is a wildcard, the rule is:
>>>
>>>No pointer from C* to B* or B* to A* is ever used. 
>>>      
>>>
>>If
>>    
>>
>>>you were
>>>going to get to A6, you would have gotten there
>>>      
>>>
>>while
>>    
>>
>>>traversing
>>>the "A" list, and if you are at the C list level,
>>>      
>>>
>>you
>>    
>>
>>>have already left 
>>>the A and B lists behind.
>>>
>>>To convert a Skip List to a Skip Tree, note that
>>>      
>>>
>>every
>>    
>>
>>>decision
>>>you need to make is based on a NODE->VALUE
>>>      
>>>
>>comparison.
>>    
>>
>>>After each decision, processing can go in two
>>>directions, so there
>>>are two "edges" from that decision.
>>>
>>>Decisions become binary tree nodes.  EDGES become
>>>      
>>>
>>left
>>    
>>
>>>and
>>>right pointers.
>>>
>>>The first decision in following the skip list is
>>>      
>>>
>>"Is
>>    
>>
>>>the search
>>>value greater than "1" (i.e. node A1's value is 1).
>>>      
>>>
>>>Thus the
>>>top node of the Skip Tree is A1.  If the value is
>>>      
>>>
>>less
>>    
>>
>>>than 1,
>>>we look at C0.  Thus C0 is on the left hand side of
>>>A1.
>>>
>>>Just traverse the skip list, and wherever you make
>>>      
>>>
>>a
>>    
>>
>>>decision
>>>based on a value, there is a node.  Note that this
>>>skip list is
>>>not really balanced.  Due to the extra pointers,
>>>      
>>>
>>the
>>    
>>
>>>policy is
>>>normally to have FEWER high-level nodes in a Skip
>>>      
>>>
>>List
>>    
>>
>>>than
>>>would be predicted by the (1/2, 1/4, 1/8)
>>>      
>>>
>>progression
>>>from the
>>    
>>
>>>bottom up.  Usually 3/4 on the bottom level, then
>>>      
>>>
>>3/4
>>    
>>
>>>of the
>>>remaining on the next level, etc.
>>>
>>>With a skip tree, we actually want the balanced
>>>version, i.e.
>>>ratios of 1/2 on each level, although other ratios
>>>      
>>>
>>can
>>    
>>
>>>be used.
>>>
>>>Kevin
>>>
>>>--- Hans Reiser <reiser@namesys.com> wrote:
>>> 
>>>
>>>      
>>>
>>>>Alexander G. M. Smith wrote:
>>>>
>>>>   
>>>>
>>>>        
>>>>
>>>>>Hans Reiser wrote on Thu, 22 May 2003 19:30:16
>>>>>     
>>>>>
>>>>>          
>>>>>
>>>>+0400:
>>>>   
>>>>
>>>>        
>>>>
>>>>>     
>>>>>
>>>>>          
>>>>>
>>>>>>Forgive me for asking some bonehead
>>>>>>            
>>>>>>
>>questions.....
>>    
>>
>>>>>>Are skip lists height balanced?  (All paths to
>>>>>>            
>>>>>>
>>the
>>    
>>
>>>>>>       
>>>>>>
>>>>>>            
>>>>>>
>>>>leaves are equal?)
>>>>   
>>>>
>>>>        
>>>>
>>>>>>  
>>>>>>
>>>>>>       
>>>>>>
>>>>>>            
>>>>>>
>>>>>Only on the average, at least in the original
>>>>>          
>>>>>
>>skip
>>    
>>
>>>>>     
>>>>>
>>>>>          
>>>>>
>>>>list algorithm.  The
>>>>   
>>>>
>>>>        
>>>>
>>>>>height is determined randomly when the node is
>>>>>     
>>>>>
>>>>>          
>>>>>
>>>>created; there is no
>>>>   
>>>>
>>>>        
>>>>
>>>>>rebalancing.  The random distribution is defined
>>>>>          
>>>>>
>>as
>>    
>>
>>>>>     
>>>>>
>>>>>          
>>>>>
>>>>you would expect,
>>>>   
>>>>
>>>>        
>>>>
>>>>>50% of the nodes have 1 level, 25% have 2 levels,
>>>>>     
>>>>>
>>>>>          
>>>>>
>>>>... 0.5**n of the
>>>>   
>>>>
>>>>        
>>>>
>>>>>nodes have n levels.  Surprisingly, this works
>>>>>     
>>>>>
>>>>>          
>>>>>
>>>>fairly well.
>>>>   
>>>>
>>>>        
>>>>
>>>>>- Alex
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>     
>>>>>
>>>>>          
>>>>>
>>>>To have a level means to be on that level or
>>>>        
>>>>
>>lower?
>>    
>>
>>>>-- 
>>>>Hans
>>>>
>>>>        
>>>>
>=== message truncated ===
>
>
>__________________________________
>Do you Yahoo!?
>Yahoo! Calendar - Free online calendar with sync to Outlook(TM).
>http://calendar.yahoo.com
>
>
>  
>


-- 
Hans



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-06-04  9:40             ` Hans Reiser
@ 2003-06-05 22:34               ` Enrique Perez-Terron
  2003-06-08  5:26                 ` Kevin Bealer
  2003-06-08  5:20               ` Kevin Bealer
  1 sibling, 1 reply; 24+ messages in thread
From: Enrique Perez-Terron @ 2003-06-05 22:34 UTC (permalink / raw)
  To: reiserfs-list

On Wed, 2003-06-04 at 11:40, Hans Reiser wrote:
> So if I understand right, the level is determined by what the key is.  

Hans, I am afraid this discussion is getting confusing, because we are
actually discussing three different data structures, and with you
traveling around attention gets spotty and concepts get mixed up. :)

I will try to sum up:

First there were the "skip list", invented by Puig in 1991, I think.

Skip lists are interesting because they need no re-balancing. Their
structure is completely independent of the history of insertions and
deletions. Operations are fast and very elegant. It is claimed they beat
AVL-trees and many other structures by constant factors.

However, skip lists are not easy to use in a massively parallel
algorithms. One has to lock a large portion of the skip list before
updating it, and keep this lock until finished. Also, the nodes have a
varying number of pointers in them (constant for a given node, though).
This leads to some allocation issues.

Then came the skip trees. Somebody (forgot his name) discovered that
every skip list could be transformed into an equivalent skip tree, and
vice versa.

Skip trees are rather similar to B-trees. However there is no upper
bound to the number of keys in a node, so the node might have to occupy
multiple disk blocks. Probability laws will keep the vast majority of
the nodes small. (Just how small is tunable.)

The Skip tree algorithms have the nice feature that you can lock a node
to operate on it, then lock some of its children, release the parent,
etc, proceeding toward the leafs. This is nice because two processes
could work on the tree at the same time without risking deadlocks. This
makes skip trees interesting for parallel algorithms.

Now Kevin has observed that rather than converting a skip list into a
skip tree, one can convert it into what he calls a "split tree". Split
trees are binary trees where every node has an attribute "level", a
small integer. Thus, nodes are of fixed size (provided keys are). 

Besides the usual key-ordering invariants, split trees obey the law that
the children of a node have no higher level than the node itself. The
level is assigned the same way as in skip lists: at random when the node
is created, with low levels chosen more often. It is not necessarily a
function of the key, but your question made me think that was another
interesting idea.

Split trees have the same downward lock propagation as skip trees,
making them interesting for parallel processing applications.

However, the last few mails have been describing the skip list to you.
Originally I think the skip lists were only mentioned as a supposedly
known reference when describing the split tree. 

A skip list is at first a singly lined list containing all nodes and
ordered by ascending keys. There are additionally two dummy nodes Head
and Tail (or Nil in the literature), with suitable dummy keys. Scanning
this list for a given key is O(N).

But then there is a second list, which includes on average some fraction
of all nodes, typically half of them. These nodes are then members of
both lists at once. They must have multiple "next" pointers one for each
list. Scanning this list for a given key is faster than the first list,
but you might not find the key. However, if you don't find the node with
key K, you can locate consecutive nodes with keys J and L in this list
such that J < K < L.  Since node(J) is member of list one too, you can
switch to scanning list one starting from node(J) . That gives you the
speed of list two, yet the completeness of list one.

But just as list two is a fast lane compared to list one, there is a
list three whose members is a subset of those of list two, and further
lists, each a faster lane to get quickly at any point in the previous
list.

Notice that Head and Nil are members of all lists. The following search
procedure is O(lnN): Start at Head and scan the fastest list and drop
subsequently down to lower-level (slower/more complete) lists whenever
you would otherwise step into nodes with larger keys than the one you
are looking for.

When a node is created, a random number "level" is assigned to it, and
then then node is inserted into the first "level" lists in its correct
place according to the key ordering.  A node never changes its level. It
remains a member of the same lists until it is eventually removed from
all of them.

> Suppose that for key K the determined level is 3, but there are no 
> other 
> records in the tree?  Is K then stored at a node at level 1 until such 
> time as a level 1 key is created for it to be attached to, or does one 
> create empty level 1 and level 2 nodes?

If we are still describing the skip list, no. K is stored at level 3,
and no empty nodes of level 1 or 2 are created. However, node(K)
is simultaneously member of three lists. One list holds nodes with level
>= 1, i.e. all nodes. Another is for nodes with level >= 2, and that is
usually about half the nodes. The third list contains all nodes with
levels 3 and higher.

Using a variation of Kevin's diagram notation, we could depict the list
with a single node with key K and level three: Horizontally repeated
letters are the same node, but the node is member of multiple lists.
Vertical lines are pointers, 'v' are arrowheads.

A----A----A----A...  (This is a single node called Head and with a dummy
|    |    |    |      key smaller than any legal key. It is member of
|    |    |    |      all lists. )
v    v    v    |
K----K----K    |     (K is simultaneously member of three lists. It is 
|    |    |    |      not member of the fourth list (or any higher
|    |    |    |      list.)
v    v    v    v
Z----Z----Z----Z...  (This is the final node, a dummy node of infinite
                      level, and thus (final) member of all lists. Its
                      key is a dummy key larger than any legal key.)

Regards, Enrique


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-06-04  9:44             ` Hans Reiser
@ 2003-06-08  5:17               ` Kevin Bealer
  0 siblings, 0 replies; 24+ messages in thread
From: Kevin Bealer @ 2003-06-08  5:17 UTC (permalink / raw)
  To: Hans Reiser; +Cc: Alexander G. M. Smith, reiserfs-list


--- Hans Reiser <reiser@namesys.com> wrote:
> Kevin Bealer wrote:
> 
> >>Hans Reiser <reiser@namesys.com> wrote:
> >>Kevin Bealer wrote:
> >>
> >>    
> >>
> >>>Sorry, last message was accidentally sent
> >>>      
> >>>
> >>prematurely.
> >>    
> >>
> >>>To continue:
> >>>
> >>>Skip lists (turned 90 degrees) look like:
> >>>
> >>>topnode--x------x
> >>>C0
> >>>A1-----A1-----A1
> >>>C2
> >>>C3
> >>>B4-----B4
> >>>C5
> >>>A6-----A6-----A6
> >>>C7
> >>>C8
> >>>B9-----B9
> >>>C11
> >>>A12----A12----A12
> >>>
> >>>With pointers vertically between all aligned
> >>>      
> >>>
> >>letters
> >>    
> >>
> >>>(conceptually at least).
> >>>
> >>>      
> >>>
> >>I don't understand the diagram above, which means
> I
> >>don't understand the 
> >>rest.  I think you are explaining something you
> >>understand too well to 
> >>explain....;-)
> >>    
> >>
> >
> >
> >Yes, probably.  Sorry about that;  I was trying to
> >make a diagram that works with variable sized type.
> >
> >Each line of the diagram is a node of the skip
> list.
> >
> >The 'topnode' is the header of the skip list, which
> >typically looks like a skip node of the maximum
> >node size with no data.
> >
> >Nodes with one pointer are 'C#' here, nodes with
> >two pointers are 'B#', nodes with three are 'A#'.
> >The '#' is the data value of the node (or the key,
> >if it is a multiset).
> >
> >In the skip list, node A1 is a node with three
> >pointers, to C1, B2, and A6.
> >
> 
> C1 and B2 are not in your diagram....
> 

Sorry, it should read C2, B4, and A6.

> >  Each of these must
> >have a value greater or equal to A1, to preserve
> >the invariant, which is that the list at each
> >level is an ordered list.  In this case the list
> >at level 3 is the list containing A's and chained
> >in the third pointer.  The list using the second 
> >pointer contains A's, and B's.  The list at the
> >first level, represented here as character column
> >1 in the diagram, is the first level list, it 
> >contains all the nodes.
> >
> >The argument I am making is not essential, it is
> >only that some of these pointers are unnecessary,
> >which leads to the Split Tree.
> >
> >A different organization of pointers, and we have
> >the same search ORDER, but with slightly different
> >internal connections; plus all nodes are the same
> >size, and all normal 'binary tree' based algorithms
> >work as expected.
> >
> >If you understand the Skip List, you can see every
> >location where a decision is made by comparing the
> >search value to the value of a node.  Running
> through 
> >these by hand, I was able to use these decisions as
> >binary tree traversal decisions, and create a
> binary
> >tree that has the same traversal behavior as a skip
> >list.
> >
> >In doing so, I realized that the pointers which
> were
> >from a low level node to a high level node are not
> >consulted.  It looks good to have them because then
> >we have a set of ordered lists at each level, but
> >they don't actually get traversed in searches.
> >
> >Anyway, its sort of a 'theory' argument to explain
> >why Split Tree is possible even though it seems
> like
> >you can't safely do this to a Skip List.
> >
> >Does that help or am I still babbling? ;)
> >
> >Kevin
> >
> >  
> >
> >>>Now here is the reason why SkipTrees do NOT need
> >>>variable sized nodes:
> >>>
> >>>The Pointer from A1 to A6 is used, so is the
> >>>      
> >>>
> >>pointer
> >>>from A1 to B4 and from B4 to C5.
> >>    
> >>
> >>>However, the pointers from C2 and C3 to B4, B4 to
> >>>      
> >>>
> >>A6,
> >>    
> >>
> >>>and B9 to A12 are NEVER USED for example.  You
> are
> >>>sacrificing
> >>>pointers to get to a binary tree, but the
> pointers
> >>>      
> >>>
> >>you
> >>    
> >>
> >>>lose
> >>>are the pointers you don't need anyway.
> >>>
> >>>In SkipList, you need those pointers only to copy
> >>>their value to
> >>>other pointers which will not be used.  The nodes
> >>>can't shrink,
> >>>because an insertion changes which pointers are
> >>>      
> >>>
> >>used
> >>    
> >>
> >>>and which
> >>>are not.
> >>>
> >>>If * is a wildcard, the rule is:
> >>>
> >>>No pointer from C* to B* or B* to A* is ever
> used. 
> >>>      
> >>>
> >>If
> >>    
> >>
> >>>you were
> >>>going to get to A6, you would have gotten there
> >>>      
> >>>
> >>while
> >>    
> >>
> >>>traversing
> >>>the "A" list, and if you are at the C list level,
> >>>      
> >>>
> >>you
> >>    
> >>
> >>>have already left 
> >>>the A and B lists behind.
> >>>
> >>>To convert a Skip List to a Skip Tree, note that
> >>>      
> >>>
> >>every
> >>    
> >>
> >>>decision
> >>>you need to make is based on a NODE->VALUE
> >>>      
> >>>
> >>comparison.
> >>    
> 
=== message truncated ===


__________________________________
Do you Yahoo!?
Yahoo! Calendar - Free online calendar with sync to Outlook(TM).
http://calendar.yahoo.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-06-04  9:40             ` Hans Reiser
  2003-06-05 22:34               ` Enrique Perez-Terron
@ 2003-06-08  5:20               ` Kevin Bealer
  1 sibling, 0 replies; 24+ messages in thread
From: Kevin Bealer @ 2003-06-08  5:20 UTC (permalink / raw)
  To: Hans Reiser, Enrique Perez-Terron
  Cc: Kevin Bealer, Alexander G. M. Smith, reiserfs-list


In this case you would have a tree with only a level 3
node.  The levels are only used during insertion.  If
a level 2 node was later added, it would be added
under the level 3 node.

The level is not determined by the key, but chosen
randomly.  Half of the nodes are given level 0, half
of the remaining are given level 1, etc.

(I am talking about my algorithm here.)

Kevin

--- Hans Reiser <reiser@namesys.com> wrote:
> So if I understand right, the level is determined by
> what the key is.  
> Suppose that for key K the determined level is 3,
> but there are no other 
> records in the tree?  Is K then stored at a node at
> level 1 until such 
> time as a level 1 key is created for it to be
> attached to, or does one 
> create empty level 1 and level 2 nodes?
> 
> -- 
> Hans
> 
> 


__________________________________
Do you Yahoo!?
Yahoo! Calendar - Free online calendar with sync to Outlook(TM).
http://calendar.yahoo.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-06-05 22:34               ` Enrique Perez-Terron
@ 2003-06-08  5:26                 ` Kevin Bealer
  2003-06-09 15:33                   ` Enrique Perez-Terron
  0 siblings, 1 reply; 24+ messages in thread
From: Kevin Bealer @ 2003-06-08  5:26 UTC (permalink / raw)
  To: Enrique Perez-Terron, reiserfs-list


I should mention that I have never heard of "skip
tree" however.  The names I have been using are:

1. skip list
2. binary treap
3. split tree (mine)

The binary treap is very close to my split tree (it
has the same invariants but slightly different 
algorithms).  I did not know about binary treaps
until I had already designed split tree, and was
looking to see if it was a new invention.

I may have accidentally called my version a skip
tree.  If skip tree is another version, I'm not
sure how it is different from mine or what the
details are.

Kevin

--- Enrique Perez-Terron
<enrique.perez-terron@norway.online.no> wrote:
> On Wed, 2003-06-04 at 11:40, Hans Reiser wrote:
> > So if I understand right, the level is determined
> by what the key is.  
> 
> Hans, I am afraid this discussion is getting
> confusing, because we are
> actually discussing three different data structures,
> and with you
> traveling around attention gets spotty and concepts
> get mixed up. :)
> 
> I will try to sum up:
> 
> First there were the "skip list", invented by Puig
> in 1991, I think.
> 
> Skip lists are interesting because they need no
> re-balancing. Their
> structure is completely independent of the history
> of insertions and
> deletions. Operations are fast and very elegant. It
> is claimed they beat
> AVL-trees and many other structures by constant
> factors.
> 
> However, skip lists are not easy to use in a
> massively parallel
> algorithms. One has to lock a large portion of the
> skip list before
> updating it, and keep this lock until finished.
> Also, the nodes have a
> varying number of pointers in them (constant for a
> given node, though).
> This leads to some allocation issues.
> 
> Then came the skip trees. Somebody (forgot his name)
> discovered that
> every skip list could be transformed into an
> equivalent skip tree, and
> vice versa.
> 
> Skip trees are rather similar to B-trees. However
> there is no upper
> bound to the number of keys in a node, so the node
> might have to occupy
> multiple disk blocks. Probability laws will keep the
> vast majority of
> the nodes small. (Just how small is tunable.)
> 
> The Skip tree algorithms have the nice feature that
> you can lock a node
> to operate on it, then lock some of its children,
> release the parent,
> etc, proceeding toward the leafs. This is nice
> because two processes
> could work on the tree at the same time without
> risking deadlocks. This
> makes skip trees interesting for parallel
> algorithms.
> 
> Now Kevin has observed that rather than converting a
> skip list into a
> skip tree, one can convert it into what he calls a
> "split tree". Split
> trees are binary trees where every node has an
> attribute "level", a
> small integer. Thus, nodes are of fixed size
> (provided keys are). 
> 
> Besides the usual key-ordering invariants, split
> trees obey the law that
> the children of a node have no higher level than the
> node itself. The
> level is assigned the same way as in skip lists: at
> random when the node
> is created, with low levels chosen more often. It is
> not necessarily a
> function of the key, but your question made me think
> that was another
> interesting idea.
> 
> Split trees have the same downward lock propagation
> as skip trees,
> making them interesting for parallel processing
> applications.
> 
> However, the last few mails have been describing the
> skip list to you.
> Originally I think the skip lists were only
> mentioned as a supposedly
> known reference when describing the split tree. 
> 
> A skip list is at first a singly lined list
> containing all nodes and
> ordered by ascending keys. There are additionally
> two dummy nodes Head
> and Tail (or Nil in the literature), with suitable
> dummy keys. Scanning
> this list for a given key is O(N).
> 
> But then there is a second list, which includes on
> average some fraction
> of all nodes, typically half of them. These nodes
> are then members of
> both lists at once. They must have multiple "next"
> pointers one for each
> list. Scanning this list for a given key is faster
> than the first list,
> but you might not find the key. However, if you
> don't find the node with
> key K, you can locate consecutive nodes with keys J
> and L in this list
> such that J < K < L.  Since node(J) is member of
> list one too, you can
> switch to scanning list one starting from node(J) .
> That gives you the
> speed of list two, yet the completeness of list one.
> 
> But just as list two is a fast lane compared to list
> one, there is a
> list three whose members is a subset of those of
> list two, and further
> lists, each a faster lane to get quickly at any
> point in the previous
> list.
> 
> Notice that Head and Nil are members of all lists.
> The following search
> procedure is O(lnN): Start at Head and scan the
> fastest list and drop
> subsequently down to lower-level (slower/more
> complete) lists whenever
> you would otherwise step into nodes with larger keys
> than the one you
> are looking for.
> 
> When a node is created, a random number "level" is
> assigned to it, and
> then then node is inserted into the first "level"
> lists in its correct
> place according to the key ordering.  A node never
> changes its level. It
> remains a member of the same lists until it is
> eventually removed from
> all of them.
> 
> > Suppose that for key K the determined level is 3,
> but there are no 
> > other 
> > records in the tree?  Is K then stored at a node
> at level 1 until such 
> > time as a level 1 key is created for it to be
> attached to, or does one 
> > create empty level 1 and level 2 nodes?
> 
> If we are still describing the skip list, no. K is
> stored at level 3,
> and no empty nodes of level 1 or 2 are created.
> However, node(K)
> is simultaneously member of three lists. One list
> holds nodes with level
> >= 1, i.e. all nodes. Another is for nodes with
> level >= 2, and that is
> usually about half the nodes. The third list
> contains all nodes with
> levels 3 and higher.
> 
> Using a variation of Kevin's diagram notation, we
> could depict the list
> with a single node with key K and level three:
> Horizontally repeated
> letters are the same node, but the node is member of
> multiple lists.
> Vertical lines are pointers, 'v' are arrowheads.
> 
> A----A----A----A...  (This is a single node called
> Head and with a dummy
> |    |    |    |      key smaller than any legal
> key. It is member of
> |    |    |    |      all lists. )
> v    v    v    |
> K----K----K    |     (K is simultaneously member of
> three lists. It is 
> |    |    |    |      not member of the fourth list
> (or any higher
> |    |    |    |      list.)
> v    v    v    v
> Z----Z----Z----Z...  (This is the final node, a
> dummy node of infinite
>                       level, and thus (final) member
> of all lists. Its
>                       key is a dummy key larger than
> any legal key.)
> 
> Regards, Enrique
> 


__________________________________
Do you Yahoo!?
Yahoo! Calendar - Free online calendar with sync to Outlook(TM).
http://calendar.yahoo.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: Split Trees (my design, similar to binary treaps)
  2003-06-08  5:26                 ` Kevin Bealer
@ 2003-06-09 15:33                   ` Enrique Perez-Terron
  0 siblings, 0 replies; 24+ messages in thread
From: Enrique Perez-Terron @ 2003-06-09 15:33 UTC (permalink / raw)
  To: Kevin Bealer; +Cc: reiserfs-list

On Sun, 2003-06-08 at 07:26, Kevin Bealer wrote:

> I may have accidentally called my version a skip
> tree.  If skip tree is another version, I'm not

I won't discard completely the possibility that it was me that
short-circuited to skip trees when seeing "split tree" some lines below
"skip list"...

In any case, this is my description of a skip tree:

A skip tree is just like a B-tree except that the number of keys in a
node may be zero, and has no upper bound. Keys are not repeated at lower
levels, and "payload data" associated with a key is stored with the key,
usually in the form of a pointer. 

These data pointers are not further mentioned. In what follows all
pointers are pointers to skip tree nodes.

Thus a skip tree of 

   height 0     is empty,
   height 1     is a node with zero or more keys in ascending order, 
   height h > 1 is a node with zero or more keys, k_1,...,k_n, in
                ascending order, and n+1 pointers p_0,...p_n to height
                h-1 skip trees. 

The keys accessible directly or indirectly through pointer p_i in a
node, have values between the keys k_{i-1} and k_i in the node.

On insertion, a level h is randomly assigned to the new key. 

If the skip tree already has height h (sub)trees, the key is inserted
into the root node of the unique height h (sub)tree where the key is
permitted by the ordering constraints. If the new key becomes k_i in the
node, the node pointed to by p_{i-1} is split in two, one node becomes
the new p_{i-1}, the other becomes the new p_i. Former keys k_i,...,k_n
are renumbered k_{i+1},...,k_{n+1}, and the former pointers p_i,..,p_n
are renumbered p_{i+1},...,p{n+1}. Nodes two levels below h are not
changed.

If no level-l node exists, one is created with the new key, and as many
empty nodes are created as needed to make the tree have two subtrees of
height l-1. The original tree's root node is split in two if required
and the parts used instead of empty nodes at the appropriate place in
the subtrees below the new root node.

Converting a skip list into a skip tree is straightforward.

The head and nil nodes of the skip list are not included in the skip
tree.

A skip tree whose highest level with nonzero population is L, is
converted to a skip tree of height L.

The elements in the top-level list are placed in the root node of the
skip tree.

In a skip list, if a and b are level l nodes that are consecutive in the
level l list, then the nodes between a and b in the lower level lists
form a skip list with a and b as head and nil respectively.

This (sub)skip list is converted in the same way as the original skip
list, so the keys of the level l-1 nodes between a and b form the root
node of a skip (sub)tree. Notice that there may be zero keys in this
(subtree) root node, since there may be no level l-1 nodes between a and
b.

The skip tree is a structure where the power-of-two  distribution of the
levels is often not optimal. Using a block size that can accommodate N
keys per one-block node, I guess something near 3N/4 keys of level l-1
for each level l key is optimal. The trade-off is between the cost of
having a linear list of blocks to constitute a single logical node when
there are too many keys (and most of the time the second block will have
very few keys in it), against the cost of having more levels if each
node has few keys. 3N/4 corresponds to a p value of 4/(3N). Then level 1
must be chosen (1-p) of the time, level 2 (1-p)*p of the time, etc. If
you expect your data to have less than MAX keys over the lifetime of the
tree, you would clamp the level to be no more than log_{3N/4}(MAX) + 1.

Regards, Enrique


^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2003-06-09 15:33 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-05-08  4:22 Split Trees (my design, similar to binary treaps) Kevin Bealer
2003-05-22 15:30 ` Hans Reiser
2003-05-22 16:09   ` Alexander G. M. Smith
2003-05-22 17:16     ` Hans Reiser
2003-05-22 20:21       ` Alexander G. M. Smith
2003-05-22 22:48         ` Hans Reiser
2003-05-22 23:27           ` Alexander G. M. Smith
2003-05-23 18:56             ` Kevin Bealer
2003-06-02 17:33               ` Hans Reiser
2003-06-04  4:54                 ` Kevin Bealer
2003-05-23 19:24       ` Kevin Bealer
2003-06-03 17:49         ` Hans Reiser
2003-06-04  5:17           ` Enrique Perez-Terron
2003-06-04  9:40             ` Hans Reiser
2003-06-05 22:34               ` Enrique Perez-Terron
2003-06-08  5:26                 ` Kevin Bealer
2003-06-09 15:33                   ` Enrique Perez-Terron
2003-06-08  5:20               ` Kevin Bealer
2003-06-04  5:22           ` Kevin Bealer
2003-06-04  9:44             ` Hans Reiser
2003-06-08  5:17               ` Kevin Bealer
2003-05-27  1:38   ` Enrique Perez-Terron
2003-05-27 20:47     ` Hans Reiser
2003-05-28 16:44     ` Kevin Bealer

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.