在Ruby中实现二叉树

在Ruby中实现二叉树,ruby,binary-tree,stack-overflow,Ruby,Binary Tree,Stack Overflow,我一直在尝试在Ruby中实现BinaryTree类,但我发现堆栈级别太深了错误,尽管我似乎没有在特定的代码段中使用任何递归: 1. class BinaryTree 2. include Enumerable 3. 4. attr_accessor :value 5. 6. def initialize( value = nil ) 7. @value = value 8. @left = BinaryTre

我一直在尝试在Ruby中实现BinaryTree类,但我发现
堆栈级别太深了
错误,尽管我似乎没有在特定的代码段中使用任何递归:

1.  class BinaryTree
2.    include Enumerable
3.      
4.      attr_accessor :value
5.      
6.      def initialize( value = nil )
7.          @value = value
8.          @left = BinaryTree.new  # stack level too deep here
9.          @right = BinaryTree.new # and here
10.     end
11.     
12.     def empty?
13.         ( self.value == nil ) ? true : false
14.     end
15.         
16.         def <<( value )
17.           return self.value = value if self.empty?
18. 
19.           test = self.value <=> value
20.           case test
21.             when -1, 0 
22.                 self.right << value
23.             when 1 
24.                 self.left << value
25.           end
26.         end     # <<
27.     
28.  end
然后是

虽然我似乎没有在这段代码中使用任何递归:

1.  class BinaryTree
2.    include Enumerable
3.      
4.      attr_accessor :value
5.      
6.      def initialize( value = nil )
7.          @value = value
8.          @left = BinaryTree.new  # stack level too deep here
9.          @right = BinaryTree.new # and here
10.     end
11.     
12.     def empty?
13.         ( self.value == nil ) ? true : false
14.     end
15.         
16.         def <<( value )
17.           return self.value = value if self.empty?
18. 
19.           test = self.value <=> value
20.           case test
21.             when -1, 0 
22.                 self.right << value
23.             when 1 
24.                 self.left << value
25.           end
26.         end     # <<
27.     
28.  end
然而

def initialize( value = nil )
    @value = value
    @left = BinaryTree.new  # this calls initialize again
    @right = BinaryTree.new # and so does this, but you never get there
end
这就是无限递归。您调用
initilize
,后者依次调用
new
,后者依次调用
initialize
。。。我们四处走走

您需要在其中添加一个保护,以检测您已经初始化了主节点,现在正在初始化leafs,在这种情况下,
@left
@right
应该设置为
nil

def initialize( value=nil, is_sub_node=false )
    @value = value
    @left = is_sub_node ? nil : BinaryTree.new(nil, true)
    @right = is_sub_node ? nil : BinaryTree.new(nil, true)
end

不过说实话。。。为什么不从一开始就将left和right初始化为nil呢?他们还没有价值观,所以你得到了什么?它在语义上更有意义;创建一个包含一个元素的新列表,即左元素和右元素都不存在。我只想使用:

def initialize(value=nil)
    @value = value
    @left = @right = nil
end
1。类二叉树
2.包括可枚举的
3.
4.属性存取器:值
5.
6.def初始化(值=零)
7.          @价值=价值
8.结束
9
10定义每次访问
11如果self.nil返回?
12
13屈服自我价值
14self.left.如果self.left,则每个(&block)
15self.right.如果self.right,则每个(&block)
16结束
17
18def是空的吗?
19.         # 代码在这里
20结束
21

22def您可能需要修复代码中的无限递归。下面是一个二叉树的工作示例。您需要有一个基本条件来在某个地方终止递归,否则它将是一个无限深的堆栈

# Example of Self-Referential Data Structures - A Binary Tree

class TreeNode
    attr_accessor :value, :left, :right

    # The Tree node contains a value, and a pointer to two children - left and right 
    # Values lesser than this node will be inserted on its left
    # Values greater than it will be inserted on its right
    def initialize val,left,right
        @value = val
        @left = left
        @right = right
    end
end

class BinarySearchTree

    # Initialize the Root Node
    def initialize val
        puts "Initializing with: " + val.to_s
        @root = TreeNode.new(val,nil,nil)   
    end

    # Pre-Order Traversal
    def preOrderTraversal(node= @root)
        return if (node == nil)
        preOrderTraversal(node.left)
        preOrderTraversal(node.right)
        puts node.value.to_s
    end

    # Post-Order Traversal
    def postOrderTraversal(node = @root)
        return if (node == nil)
        puts node.value.to_s
        postOrderTraversal(node.left)
        postOrderTraversal(node.right)
    end

    # In-Order Traversal : Displays the final output in sorted order
    # Display smaller children first (by going left)
    # Then display the value in the current node 
    # Then display the larger children on the right
    def inOrderTraversal(node = @root)
        return if (node == nil)
        inOrderTraversal(node.left)
        puts node.value.to_s
        inOrderTraversal(node.right)
    end


    # Inserting a value
    # When value > current node, go towards the right
    # when value < current node, go towards the left
    # when you hit a nil node, it means, the new node should be created there
    # Duplicate values are not inserted in the tree
    def insert(value)
        puts "Inserting :" + value.to_s
        current_node = @root
        while nil != current_node
            if (value < current_node.value) && (current_node.left == nil)
                current_node.left = TreeNode.new(value,nil,nil)
            elsif  (value > current_node.value) && (current_node.right == nil)
                current_node.right = TreeNode.new(value,nil,nil)
            elsif (value < current_node.value)
                current_node = current_node.left
            elsif (value > current_node.value)
                current_node = current_node.right
            else
                return
            end
        end
    end
end

bst = BinarySearchTree.new(10)
bst.insert(11)
bst.insert(9)
bst.insert(5)
bst.insert(7)
bst.insert(18)
bst.insert(17)
# Demonstrating Different Kinds of Traversals
puts "In-Order Traversal:"
bst.inOrderTraversal
puts "Pre-Order Traversal:"
bst.preOrderTraversal
puts "Post-Order Traversal:"
bst.postOrderTraversal

=begin

Output :
Initializing with: 10
Inserting :11
Inserting :9
Inserting :5
Inserting :7
Inserting :18
Inserting :17
In-Order Traversal:
5
7
9
10
11
17
18
Pre-Order Traversal:
7
5
9
17
18
11
10
Post-Order Traversal:
10
9
5
7
11
18
17

=end
自引用数据结构示例-二叉树 三烯类 属性访问器:值,:左,:右 #树节点包含一个值和一个指向两个子节点(左和右)的指针 #小于此节点的值将插入其左侧 #将在其右侧插入大于该值的值 def初始化val,左,右 @值=val @左=左 @右=右 结束 结束 类二进制搜索树 #初始化根节点 def初始化val 将“初始化为:”+val.to_s @root=TreeNode.new(val,nil,nil) 结束 #预序遍历 def preOrderTraversal(节点=@root) 如果(节点==nil)返回 预订单行程(节点左) 预订单行程(右节点) 将node.value.to_ 结束 #后序遍历 def postOrderTraversal(节点=@root) 如果(节点==nil)返回 将node.value.to_ postOrderTraversal(node.left) postOrderTraversal(node.right) 结束 #按顺序遍历:按排序顺序显示最终输出 #先显示较小的孩子(向左) #然后在当前节点中显示该值 #然后在右侧显示较大的子对象 def inOrderTraversal(节点=@root) 如果(节点==nil)返回 inOrderTraversal(node.left) 将node.value.to_ inOrderTraversal(node.right) 结束 #插入值 #当值>当前节点时,向右移动 #当值<当前节点时,向左移动 #当您点击一个nil节点时,这意味着应该在那里创建新节点 #不会在树中插入重复的值 def插入(值) 将“插入:”+值添加到 当前_节点=@root 而零!=当前节点 如果(值current\u node.value)&&(current\u node.right==nil) 当前_node.right=TreeNode.new(值,nil,nil) elsif(值<当前节点值) 当前节点=当前节点。左 elsif(值>当前节点值) 当前节点=当前节点。右 其他的 返回 结束 结束 结束 结束 bst=BinarySearchTree.new(10) bst.insert(11) bst.insert(9) bst.insert(5) bst.insert(7) bst.insert(18) bst.insert(17) #演示不同类型的遍历 将“按顺序遍历:” bst.inOrderTraversal 放置“预顺序遍历:” bst.preOrderTraversal 放置“后序遍历:” bst.postOrderTraversal 开始 输出: 初始化时间:10 插入:11 插入:9 插入:5 插入:7 插入:18 插入:17 按顺序遍历: 5. 7. 9 10 11 17 18 预顺序遍历: 7. 5. 9 17 18 11 10 后序遍历: 10 9 5. 7. 11 18 17 =结束

Ref:

@pranshantb1984-您给出的Ref很好,但我认为代码中有一个小改动。需要更新订单前和订单后代码,如下所示

# Post-Order Traversal
def postOrderTraversal(node= @root)
    return if (node == nil)
    postOrderTraversal(node.left)
    postOrderTraversal(node.right)
    puts node.value.to_s
end 

# Pre-Order Traversal
def preOrderTraversal(node = @root)
    return if (node == nil)
    puts node.value.to_s
    preOrderTraversal(node.left)
    preOrderTraversal(node.right)
end
预顺序遍历

10->9->5->7->11->18->17

后序遍历


7->5->9->17->18->11->10

我想再问一个问题。这是初始化属性的标准方法吗?这些属性属于它们出现的类的类型?我不确定我问的方法是否正确。@Maputo:是的,你定义了一个名为
initialize
的方法,当有人调用
YourType.new
时就会调用这个方法。你应该把左和右设置为零。这更有意义,它解决了无限递归问题。如果我这样做,我得到的是@Maputo的其他问题:好的,那么你的代码中有另一个错误,这并不意味着你最初的方法是正确的。您永远不会分配
,只需一次又一次地递归调用该方法即可。如果要使用递归,则需要一个保护程序来确定何时停止,即何时分配
并退出该过程。@Maputo:将它们初始化为
nil
。变量不是在Ruby中键入的,而是值
# Post-Order Traversal
def postOrderTraversal(node= @root)
    return if (node == nil)
    postOrderTraversal(node.left)
    postOrderTraversal(node.right)
    puts node.value.to_s
end 

# Pre-Order Traversal
def preOrderTraversal(node = @root)
    return if (node == nil)
    puts node.value.to_s
    preOrderTraversal(node.left)
    preOrderTraversal(node.right)
end