class IntervalSkipList

Attributes

head[R]
probability[R]
ranges[R]

Public Class Methods

new() click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 4
def initialize
  @head = HeadNode.new(max_height)
  @ranges = {}
  @probability = 0.5
end

Public Instance Methods

containing(n) click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 36
def containing(n)
  containing_with_node(n).first
end
delete(marker) click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 64
def delete(marker)
  range = ranges[marker]
  path_to_first_node = make_path
  first_node = find(range.first, path_to_first_node)

  cur_node = first_node
  cur_level = first_node.top_level
  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)
  if first_node.endpoint_of.empty?
    first_node.delete(path_to_first_node)
  end

  last_node.endpoint_of.delete(marker)
  if last_node.endpoint_of.empty?
    path_to_last_node = make_path
    find(range.last, path_to_last_node)
    last_node.delete(path_to_last_node)
  end
end
empty?() click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 14
def empty?
  head.forward[0].nil?
end
expire(range, length_change) click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 18
def expire(range, length_change)
  expired_markers, first_node_after_range = overlapping(range)
  expired_markers.each { |marker| delete(marker) }
  first_node_after_range.propagate_length_change(length_change)    
end
insert(range, marker) click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 40
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)

  cur_node = first_node
  cur_level = first_node.top_level
  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 = mark_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 = mark_forward_path_at_level(cur_node, cur_level, marker)
  end
end
max_height() click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 10
def max_height
  3
end
overlapping(range) click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 24
def overlapping(range)
  markers, first_node = containing_with_node(range.first)

  cur_node = first_node
  begin
    markers.concat(cur_node.forward_markers.flatten)
    cur_node = cur_node.forward[0]
  end while cur_node.key < range.last

  return markers.uniq, cur_node
end

Protected Instance Methods

can_ascend_from?(node, level) click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 157
def can_ascend_from?(node, level)
  level < node.top_level
end
can_descend_from?(level) click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 161
def can_descend_from?(level)
  level > 0
end
containing_with_node(n) click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 112
def containing_with_node(n)
  containing = []
  cur_node = head
  (max_height - 1).downto(0) do |cur_level|
    while (next_node = cur_node.forward[cur_level]) && next_node.key <= n
      cur_node = next_node
      if cur_node.key == n
        return containing + (cur_node.markers - cur_node.endpoint_of), cur_node
      end
    end
    containing.concat(cur_node.forward_markers[cur_level])
  end

  return containing, cur_node
end
delete_node(key) click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 128
def delete_node(key)
  path = make_path
  found_node = find(key, path)
  found_node.delete(path) if found_node.key == key
end
find(key, path) click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 134
def find(key, path)
  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
  end
  cur_node.forward[0]
end
insert_node(key) click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 102
def insert_node(key)
  path = make_path
  found_node = find(key, path)
  if found_node && found_node.key == key
    return found_node
  else
    return Node.new(key, next_node_height, path)
  end
end
make_path() click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 145
def make_path
  Array.new(max_height, nil)
end
mark_forward_path_at_level(node, level, marker) click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 177
def mark_forward_path_at_level(node, level, marker)
  node.forward_markers[level].push(marker)
  next_node = node.forward[level]
  next_node.markers.push(marker)
  node = next_node
end
next_node_at_level_inside_range?(node, level, range) click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 169
def next_node_at_level_inside_range?(node, level, range)
  node.forward[level] && node.forward[level].key <= range.last
end
next_node_at_level_outside_range?(node, level, range) click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 173
def next_node_at_level_outside_range?(node, level, range)
  (node.forward[level].nil? || node.forward[level].key > range.last)
end
next_node_height() click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 149
def next_node_height
  height = 1
  while rand < probability && height < max_height
    height += 1
  end
  height
end
node_inside_range?(node, range) click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 165
def node_inside_range?(node, range)
  node.key < range.last
end
nodes() click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 191
def nodes
  nodes = []
  cur_node = head.forward[0]
  until cur_node.nil?
    nodes << cur_node
    cur_node = cur_node.forward[0]
  end
  nodes
end
unmark_forward_path_at_level(node, level, marker) click to toggle source
# File lib/treetop/runtime/interval_skip_list/interval_skip_list.rb, line 184
def unmark_forward_path_at_level(node, level, marker)
  node.forward_markers[level].delete(marker)
  next_node = node.forward[level]
  next_node.markers.delete(marker)
  node = next_node
end