Skip to content

Commit

Permalink
Endpoint markers on start in addition to end of ranges
Browse files Browse the repository at this point in the history
  • Loading branch information
nathansobo committed Jan 21, 2008
1 parent bf36384 commit 7f089cb
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 21 deletions.
42 changes: 37 additions & 5 deletions lib/treetop/runtime/interval_skip_list.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class IntervalSkipList
def initialize
@head = HeadNode.new(max_height)
@ranges = {}
end

def max_height
Expand All @@ -27,7 +28,9 @@ def containing(n)
end

def insert(range, marker)
ranges[marker] = range
first_node = insert_node(range.first)
first_node.endpoint_of.push(marker)
last_node = insert_node(range.last)
last_node.endpoint_of.push(marker)

Expand All @@ -48,8 +51,37 @@ def insert(range, marker)
end
end

def delete(marker)
range = ranges[marker]
first_node = find(range.first)

cur_node = first_node
cur_level = first_node.height - 1
while next_node_at_level_inside_range?(cur_node, cur_level, range)
while can_ascend_from?(cur_node, cur_level) && next_node_at_level_inside_range?(cur_node, cur_level + 1, range)
cur_level += 1
end
cur_node = unmark_forward_path_at_level(cur_node, cur_level, marker)
end

while node_inside_range?(cur_node, range)
while can_descend_from?(cur_level) && next_node_at_level_outside_range?(cur_node, cur_level, range)
cur_level -= 1
end
cur_node = unmark_forward_path_at_level(cur_node, cur_level, marker)
end
last_node = cur_node


first_node.endpoint_of.delete(marker)
delete_node(first_node) if first_node.endpoint_of.empty?

last_node.endpoint_of.delete(marker)
delete_node(first_node) if first_node.endpoint_of.empty?
end

protected
attr_reader :head
attr_reader :head, :ranges

def insert_node(key)
path = make_path
Expand All @@ -61,19 +93,19 @@ def insert_node(key)
end
end

def delete(key)
def delete_node(key)
path = make_path
found_node = find(key, path)
found_node.remove(path) if found_node.key == key
end
end

def find(key, path)
def find(key, path = nil)
cur_node = head
(max_height - 1).downto(0) do |cur_level|
while (next_node = cur_node.forward[cur_level]) && next_node.key < key
cur_node = next_node
end
path[cur_level] = cur_node
path[cur_level] = cur_node if path
end
cur_node.forward[0]
end
Expand Down
121 changes: 105 additions & 16 deletions spec/runtime/interval_skip_list_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
require File.expand_path("#{File.dirname(__FILE__)}/interval_skip_list_spec_helper")

class IntervalSkipList
public :insert_node, :delete, :head, :nodes
public :insert_node, :delete_node, :head, :nodes
end

describe "#next_node_height is deterministic", :shared => true do
Expand Down Expand Up @@ -90,8 +90,8 @@ def confirm_containing_intervals(range, *markers)
node.markers.should be_empty
end

it "is not an endpoint of any interval" do
node.endpoint_of.should be_empty
it "is not an endpoint of only :a" do
node.endpoint_of.should have_marker(:a)
end
end

Expand Down Expand Up @@ -162,8 +162,8 @@ def confirm_containing_intervals(range, *markers)
node.markers.should be_empty
end

it "is not an endpoint of any interval" do
node.endpoint_of.should be_empty
it "is an endpoint of only :a and :b" do
node.endpoint_of.should have_markers(:a, :b)
end
end

Expand All @@ -177,7 +177,7 @@ def confirm_containing_intervals(range, *markers)
node.height.should == 2
end

it "has :a as its only marker at level 1" do
it "has :a as its only forward marker at level 1" do
node.forward_markers[1].should have_marker(:a)
end

Expand Down Expand Up @@ -265,8 +265,8 @@ def confirm_containing_intervals(range, *markers)
node.markers.should be_empty
end

it "is not an endpoint of any interval" do
node.endpoint_of.should be_empty
it "is an endpoint of only :a, :b, :c" do
node.endpoint_of.should have_markers(:a, :b, :c)
end
end

Expand All @@ -280,11 +280,11 @@ def confirm_containing_intervals(range, *markers)
node.height.should == 3
end

it "has :a as its only marker at level 2" do
it "has :a as its only forward marker at level 2" do
node.forward_markers[2].should have_marker(:a)
end

it "has :b as its only marker at level 1" do
it "has :b as its only forward marker at level 1" do
node.forward_markers[1].should have_marker(:b)
end

Expand Down Expand Up @@ -406,8 +406,8 @@ def confirm_containing_intervals(range, *markers)
node.markers.should be_empty
end

it "is not an endpoint of any interval" do
node.endpoint_of.should be_empty
it "is an endpoint of only :a, :b, :c, and :d" do
node.endpoint_of.should have_markers(:a, :b, :c, :d)
end
end

Expand Down Expand Up @@ -516,6 +516,95 @@ def confirm_containing_intervals(range, *markers)
node.endpoint_of.should have_marker(:d)
end
end

# describe ", and then :d is deleted" do
# before do
# list.delete(:d)
# end
#
# it "has only 4 nodes" do
# list.nodes.size.should == 4
# end
#
# describe " #nodes[0]" do
# before do
# @node = list.nodes[0]
# end
#
# it "has :a, :b, and :c as its only forward markers at level 1" do
# node.forward_markers[1].should have_markers(:a, :b, :c)
# end
#
# it "has no forward markers at level 0" do
# node.forward_markers[0].should be_empty
# end
# end
#
# describe " #nodes[1]" do
# before do
# @node = list.nodes[1]
# end
#
# it "has :a as its only forward marker at level 2" do
# node.forward_markers[2].should have_marker(:a)
# end
#
# it "has :b as its only forward marker at level 1" do
# node.forward_markers[1].should have_marker(:b)
# end
#
# it "has no forward markers at level 0" do
# node.forward_markers[0].should be_empty
# end
#
# it "has :a, :b, and :c as its only markers" do
# node.markers.should have_markers(:a, :b, :c)
# end
#
# it "is the endpoint of only :c" do
# node.endpoint_of.should have_marker(:c)
# end
# end
#
# describe " #nodes[2]" do
# before do
# @node = list.nodes[2]
# end
#
# it "has no forward markers at any level" do
# node.forward_markers[0].should be_empty
# node.forward_markers[1].should be_empty
# end
#
# it "has :b as its only marker" do
# node.markers.should have_marker(:b)
# end
#
# it "is the endpoint of only :b" do
# node.markers.endpoint_of.should have_marker(:b)
# end
# end
#
# describe " #nodes[3]" do
# before do
# @node = list.nodes[3]
# end
#
# it "has no forward markers at any level" do
# node.forward_markers[0].should be_empty
# node.forward_markers[1].should be_empty
# node.forward_markers[2].should be_empty
# end
#
# it "has :a as its only marker" do
# node.markers.should have_marker(:a)
# end
#
# it "is the endpoint of only :a" do
# node.markers.endpoint_of.should have_marker(:a)
# end
# end
# end
end
end
end
Expand Down Expand Up @@ -602,7 +691,7 @@ def expected_node_heights

describe "and subsequently deleted" do
before do
list.delete(1)
list.delete_node(1)
end

specify "#empty? returns true" do
Expand Down Expand Up @@ -669,7 +758,7 @@ def expected_node_heights

describe "and 1 is subsequently deleted" do
before do
list.delete(1)
list.delete_node(1)
end

describe "the remaining node" do
Expand All @@ -689,7 +778,7 @@ def expected_node_heights

describe "and 3 is subsequently deleted" do
before do
list.delete(3)
list.delete_node(3)
end

describe "the remaining node" do
Expand Down Expand Up @@ -791,7 +880,7 @@ def expected_node_heights

describe "and 3 is subsequently deleted" do
before do
list.delete(3)
list.delete_node(3)
end

specify "#head points at nil at levels 1 and 2" do
Expand Down

0 comments on commit 7f089cb

Please sign in to comment.