Class TaskJuggler::TernarySearchTree
In: lib/taskjuggler/TernarySearchTree.rb
Parent: Object

Classical ternary search tree implementation. It can store any list objects who‘s elements are comparable. These are usually String or Array objects. Common elements (by value and index) are only stored once which makes it fairly efficient for large lists that have similar start sequences. It also provides a fast find method.

Methods

<<   []   balance!   balanced   collect   find   insert   insertList   inspect   length   maxDepth   new   to_a  

Public Class methods

Create a new TernarySearchTree object. The optional arg can be an element to store in the new tree or a list of elements to store.

[Source]

# File lib/taskjuggler/TernarySearchTree.rb, line 27
    def initialize(arg = nil)
      clear

      if arg.nil?
        return
      elsif arg.is_a?(Array)
        sortForBalancedTree(arg).each { |elem| insert(elem) }
      else
        insert(arg) if arg
      end
    end

Public Instance methods

<<(str, index = 0)

Alias for insert

[](str, partialMatch = false, index = 0)

Alias for find

Balance the tree for more effective data retrieval.

[Source]

# File lib/taskjuggler/TernarySearchTree.rb, line 146
    def balance!
      list = sortForBalancedTree(to_a)
      clear
      list.each { |x| insert(x) }
    end

Return a balanced version of the tree.

[Source]

# File lib/taskjuggler/TernarySearchTree.rb, line 153
    def balanced
      TernarySearchTree.new(to_a)
    end

Invokes block for each element and returns the results as an Array.

[Source]

# File lib/taskjuggler/TernarySearchTree.rb, line 127
    def collect(str = nil, &block)
      result = []

      result += @smaller.collect(str, &block) if @smaller
      # The strange looking ('' << val) is for Ruby 1.8 compatibility.
      newStr = str.nil? ? ('' << @value) : str + ('' << @value)
      result << yield(newStr) if @last
      result += @equal.collect(newStr, &block) if @equal
      result += @larger.collect(str, &block) if @larger

      result
    end

if str is stored in the tree it returns str. If partialMatch is true, it returns all items that start with str. index is for internal use only. If nothing is found it returns either nil or an empty list.

[Source]

# File lib/taskjuggler/TernarySearchTree.rb, line 77
    def find(str, partialMatch = false, index = 0)
      return nil if str.nil? || index > (maxIdx = str.length - 1)

      if str[index] < @value
        return @smaller.find(str, partialMatch, index) if @smaller
      elsif str[index] > @value
        return @larger.find(str, partialMatch, index) if @larger
      else
        if index == maxIdx
          # We've reached the end of the search pattern.
          if partialMatch
            # The strange looking ('' << val) is for Ruby 1.8 compatibility.
            return collect { |v| str[0..-2] + ('' << v) }
          else
            return str if @last
          end
        end

        return @equal.find(str, partialMatch, index + 1) if @equal
      end
      nil
    end

Stores str in the tree. index is for internal use only.

[Source]

# File lib/taskjuggler/TernarySearchTree.rb, line 40
    def insert(str, index = 0)
      if str.nil? || str.empty?
        raise ArgumentError, "Cannot insert nil or empty lists"
      end
      if index > (maxIdx = str.length - 1) || index < 0
        raise ArgumentError, "index out of range [0..#{maxIdx}]"
      end

      @value = str[index] unless @value

      if str[index] < @value
        @smaller = TernarySearchTree.new unless @smaller
        @smaller.insert(str, index)
      elsif str[index] > @value
        @larger = TernarySearchTree.new unless @larger
        @larger.insert(str, index)
      else
        if index == maxIdx
          @last = true
        else
          @equal = TernarySearchTree.new unless @equal
          @equal.insert(str, index + 1)
        end
      end
    end

Insert the elements of list into the tree.

[Source]

# File lib/taskjuggler/TernarySearchTree.rb, line 69
    def insertList(list)
      list.each { |val| insert(val) }
    end

[Source]

# File lib/taskjuggler/TernarySearchTree.rb, line 157
    def inspect(prefix = ' ', indent = 0)
      puts "#{' ' * indent}#{prefix} #{@value} #{@last ? '!' : ''}"
      @smaller.inspect('<', indent + 2) if @smaller
      @equal.inspect('=', indent + 2) if @equal
      @larger.inspect('>', indent + 2) if @larger
    end

Returns the number of elements in the tree.

[Source]

# File lib/taskjuggler/TernarySearchTree.rb, line 103
    def length
      result = 0

      result += @smaller.length if @smaller
      result += 1 if @last
      result += @equal.length if @equal
      result += @larger.length if @larger

      result
    end

Return the maximum depth of the tree.

[Source]

# File lib/taskjuggler/TernarySearchTree.rb, line 115
    def maxDepth(depth = 0)
      depth += 1
      depths = []
      depths << @smaller.maxDepth(depth) if @smaller
      depths << @equal.maxDepth(depth) if @equal
      depths << @larger.maxDepth(depth) if @larger
      depths << depth if @last

      depths.max
    end

Return an Array with all the elements stored in the tree.

[Source]

# File lib/taskjuggler/TernarySearchTree.rb, line 141
    def to_a
      collect{ |x| x}
    end

[Validate]