You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

195 lines
3.0 KiB
Ruby

# This file contains the Ruby code from book of
# "Data Structures and Algorithms
# with Object-Oriented Design Patterns in Ruby"
# by Bruno R. Preiss.
#
# Copyright (c) 2004 by Bruno R. Preiss, P.Eng. All rights reserved.
class PrePostVisitor < Visitor
abstractmethod :preVisit
abstractmethod :inVisit
abstractmethod :postVisit
alias_method :visit, :inVisit
end
class PreOrder < PrePostVisitor
def initialize(visitor)
super()
@visitor = visitor
end
def preVisit(obj)
@visitor.visit(obj)
end
def inVisit(obj)
end
def postVisit(obj)
end
def done?
@visitor.done?
end
end
class InOrder < PrePostVisitor
def initialize(visitor)
super()
@visitor = visitor
end
def preVisit(obj)
end
def inVisit(obj)
@visitor.visit(obj)
end
def postVisit(obj)
end
def done?
@visitor.done?
end
end
class PostOrder < PrePostVisitor
def initialize(visitor)
super()
@visitor = visitor
end
def preVisit(obj)
end
def inVisit(obj)
end
def postVisit(obj)
@visitor.visit(obj)
end
def done?
@visitor.done?
end
end
class Tree < Container
def initialize
super
end
abstractmethod :key
abstractmethod :getSubtree
abstractmethod :empty?
abstractmethod :leaf?
abstractmethod :degree
abstractmethod :height
PREVISIT = -1
INVISIT = 0
POSTVISIT = +1
def depthFirstTraversal(&block)
if not empty?
yield (key, PREVISIT)
for i in 0 ... degree
getSubtree(i).depthFirstTraversal(&block)
end
yield (key, POSTVISIT)
end
end
def depthFirstTraversalAccept(visitor)
assert { visitor.is_a?(PrePostVisitor) }
depthFirstTraversal do |obj, mode|
break if visitor.done?
case mode
when PREVISIT
visitor.preVisit(obj)
when INVISIT
visitor.inVisit(obj)
when POSTVISIT
visitor.postVisit(obj)
end
end
end
def breadthFirstTraversal
queue = QueueAsLinkedList.new
queue.enqueue(self) if not empty?
while not queue.empty?
head = queue.dequeue
yield head.key
for i in 0 ... head.degree
child = head.getSubtree(i)
queue.enqueue(child) if not child.empty?
end
end
end
def breadthFirstTraversalAccept(visitor)
breadthFirstTraversal do |obj|
break if visitor.done?
visitor.visit(obj)
end
end
def each(&block)
depthFirstTraversal do |obj, mode|
block.call(obj) if mode == PREVISIT
end
end
class Iterator < Opus8::Iterator
def initialize(tree)
@stack = StackAsLinkedList.new
@stack.push(tree) if not tree.empty?
end
def more?
not @stack.empty?
end
def succ
if more?
top = @stack.pop
i = top.degree - 1
while i >= 0
subtree = top.getSubtree(i)
@stack.push(subtree) if not subtree.empty?
i -= 1
end
result = top.key
else
result = nil
end
return result
end
end
def iter
Iterator.new(self)
end
end