ツリーはリスト構造の延長線上として考えればいい。
データの追加、削除、検索が効率よく行える。バイナリサーチであった「予めデータをソートしなければならない」「配列を使うので、データの頻繁な追加と削除を行うのに向かない」という欠点をクリアしている。
# Node Class class Node attr_reader :value, :left, :right def initialize( val ) @value = val # このノードが保持する値 @left = nil # 左側のノード @right = nil # 右側のノード end # ノードの値を設定 def setValue( val ) @value = val end # 左側のノードの設定 def setLeft( node ) @left = node end # 右側のノードの設定 def setRight( node ) @right = node end end # Tree Class class TreeNode attr_reader :treeRoot def initialize() @treeRoot = nil # ツリーのルート end # ----- ノードの追加 def insertNode( num, node = nil ) # 1つも挿入されていない場合 if node == nil @treeRoot = createNewNode( num ) return end # num が現在の node の値よりも小さい場合は左側に追加する if node.value > num if node.left != nil insertNode(num, node.left) else node.setLeft( createNewNode( num ) ) end # num が現在の node の値以上の場合は右側に追加する else if node.right != nil insertNode(num, node.right) else node.setRight( createNewNode( num ) ) end end end # ----- ノードの検索 def findValue( val, node = nil ) # 自node よりも小さい値なら左側を検索 if node.value > val if node.left == nil return nil end return findValue( node.left, val ) end # 自node よりも大きい値なら右側を検索 if node.value < val if node.right == nil return nil end return findValue( node.right, val ) end return node end # ----- ノードの削除 def deleteNode( val ) node = @treeRoot parentNode = nil direction = 0 # 削除すべき対象を発見する while (node != nil && node.value != val) if node.value > val parentNode = node node = node.left direction = -1 else parentNode = node node = node.right direction = 1 end end if node == nil return false end if (node.left == nil || node.right == nil) if node.left == nil if direction == -1 # 親のポインタを変更する parentNode.setLeft( node.right ) elsif direction == 1 parentNode.setRight( node.right ) elsif direciton == 0 @treeRoot = node.right end else if direction == -1 # 親のポインタを変更する parentNode.setLeft( node.left ) elsif direction == 1 parentNode.setRight( node.left ) elsif direction == 0 @treeRoot = node.left end end else # node の左側の最も大きい値を取得する leftBiggest = node.left parentNode = node direction = -1 while leftBiggest.right != nil parentNode = leftBiggest leftBiggest = leftBiggest.right direction = -1 end # node の入れ替え node.setValue( leftBiggest.value ) if direction == -1 parentNode.setLeft( leftBiggest.left ) else parentNode.setRight( leftBiggest.left ) end end return true end def printNode( depth, node = nil ) if node == nil return end printNode( depth + 1, node.left ) i = 0 while i < depth printf " " i += 1 end printf "#{node.value}¥n" printNode( depth + 1, node.right ) end def main action = nil while action != 0 printNode( 0, @treeRoot ) puts "実行する操作のタイプを入力して下さい" puts "1:追加 2:検索 3:削除 0:終了 >" action = gets.chomp.to_i case action when 1 puts "1〜100までの範囲で追加する数値を入力して下さい" i = gets.chomp.to_i if (i < 1 || i > 100) continue end insertNode( i, @treeRoot ) when 2 puts "検索する数字を入力して下さい" i = gets.chomp.to_i if findValue( i, @treeRoot ) != nil puts "#{i}を発見しました" else puts "#{i}は見つかりませんでした" end when 3 puts "削除する数字を入力して下さい" i = gets.chomp.to_i if deleteNode(i) puts "#{i}を削除しました" else puts "#{i}は見つかりませんでした" end end end end private # ノードを生成する def createNewNode( val ) newNode = Node.new( val ) newNode.setLeft( nil ) newNode.setRight( nil ) return newNode end end # Main tree = TreeNode.new tree.main
# Node Class class Node attr_reader :value, :left, :right def initialize( val ) @value = val # このノードが保持する値 @left = nil # 左側のノード @right = nil # 右側のノード end # ノードの値を設定 def setValue( val ) @value = val end # 左側のノードの設定 def setLeft( node ) @left = node end # 右側のノードの設定 def setRight( node ) @right = node end end # Tree Class class TreeNode attr_reader :treeRoot def initialize() @treeRoot = nil # ツリーのルート end # ----- ノードの追加 def insertNode( val, node = @treeRoot ) # 1つも挿入されていない場合 if node == nil @treeRoot = createNewNode( num ) return end # num が現在の node の値よりも小さい場合は左側に追加する if node.value > val if node.left != nil insertNode(val, node.left) else node.setLeft( createNewNode( val ) ) end # num が現在の node の値以上の場合は右側に追加する else if node.right != nil insertNode(val, node.right) else node.setRight( createNewNode( val ) ) end end end # ----- ノードの検索 def findValue( val, node = @treeRoot ) # 自node よりも小さい値なら左側を検索 if node.value > val if node.left == nil return nil end return findValue( val, node.left ) end # 自node よりも大きい値なら右側を検索 if node.value < val if node.right == nil return nil end return findValue( val, node.right ) end return node end # ----- ノードの削除 def deleteNode( val ) node = @treeRoot parentNode = nil direction = 0 # 削除すべき対象を発見する while (node != nil && node.value != val) if node.value > val parentNode = node node = node.left direction = -1 else parentNode = node node = node.right direction = 1 end end if node == nil return false end if (node.left == nil || node.right == nil) if node.left == nil if direction == -1 # 親のポインタを変更する parentNode.setLeft( node.right ) elsif direction == 1 parentNode.setRight( node.right ) elsif direciton == 0 @treeRoot = node.right end else if direction == -1 # 親のポインタを変更する parentNode.setLeft( node.left ) elsif direction == 1 parentNode.setRight( node.left ) elsif direction == 0 @treeRoot = node.left end end else # node の左側の最も大きい値を取得する leftBiggest = node.left parentNode = node direction = -1 while leftBiggest.right != nil parentNode = leftBiggest leftBiggest = leftBiggest.right direction = -1 end # node の入れ替え node.setValue( leftBiggest.value ) if direction == -1 parentNode.setLeft( leftBiggest.left ) else parentNode.setRight( leftBiggest.left ) end end return true end def printNode( depth, node = @treeRoot ) if node == nil return end printNode( depth + 1, node.left ) i = 0 while i < depth printf " " i += 1 end printf "#{node.value}¥n" printNode( depth + 1, node.right ) end private # ノードを生成する def createNewNode( val ) newNode = Node.new( val ) newNode.setLeft( nil ) newNode.setRight( nil ) return newNode end end # Main tree = TreeNode.new action = nil while action != 0 tree.printNode( 0 ) puts "実行する操作のタイプを入力して下さい" puts "1:追加 2:検索 3:削除 0:終了 >" action = gets.chomp.to_i case action when 1 puts "1〜100までの範囲で追加する数値を入力して下さい" i = gets.chomp.to_i if (i < 1 || i > 100) continue end tree.insertNode( i ) when 2 puts "検索する数字を入力して下さい" i = gets.chomp.to_i if tree.findValue( i ) != nil puts "#{i}を発見しました" else puts "#{i}は見つかりませんでした" end when 3 puts "削除する数字を入力して下さい" i = gets.chomp.to_i if tree.deleteNode(i) puts "#{i}を削除しました" else puts "#{i}は見つかりませんでした" end end end
# Node Class class Node attr_reader :value, :key, :left, :right def initialize( num, val ) @value = val # このノードが保持する値 @key = num # このノードのキー @left = nil # 左側のノード @right = nil # 右側のノード end # ノードのキーを設定 def setKey( num ) @key = key end # ノードの値を設定 def setValue( val ) @value = val end # 左側のノードの設定 def setLeft( node ) @left = node end # 右側のノードの設定 def setRight( node ) @right = node end end # Tree Class class TreeNode attr_reader :treeRoot def initialize() @treeRoot = nil # ツリーのルート end # ----- ノードの追加 def insertNode( key, val, node = @treeRoot ) if node == nil @treeRoot = createNewNode( key, val ) return end if node.key > key if node.left != nil insertNode( key, val, node.left ) else node.setLeft( createNewNode( key, val ) ) end else if node.right != nil insertNode( key, val, node.right ) else node.setRight( createNewNode( key, val ) ) end end end # ----- ノードの検索 def findValue( key, node = @treeRoot ) # 自node よりも小さい値なら左側を検索 if node.key > key if node.left == nil return nil end return findValue( key, node.left ) end # 自node よりも大きい値なら右側を検索 if node.key < key if node.right == nil return nil end return findValue( key, node.right ) end return node end # ----- ノードの削除 def deleteNode( key ) node = @treeRoot parentNode = nil direction = 0 # 削除すべき対象を発見する while (node != nil && node.key != key) if node.key > key parentNode = node node = node.left direction = -1 else parentNode = node node = node.right direction = 1 end end if node == nil return false end if (node.left == nil || node.right == nil) if node.left == nil if direction == -1 # 親のポインタを変更する parentNode.setLeft( node.right ) elsif direction == 1 parentNode.setRight( node.right ) elsif direction == 0 @treeRoot = node.right end else if direction == -1 # 親のポインタを変更する parentNode.setLeft( node.left ) elsif direction == 1 parentNode.setRight( node.left ) elsif direction == 0 @treeRoot = node.left end end else # node の左側の最も大きい値を取得する leftBiggest = node.left parentNode = node direction = -1 while leftBiggest.right != nil parentNode = leftBiggest leftBiggest = leftBiggest.right direction = -1 end # node の入れ替え node.setValue( leftBiggest.value ) if direction == -1 parentNode.setLeft( leftBiggest.left ) else parentNode.setRight( leftBiggest.left ) end end return true end def printNode( depth, node = @treeRoot ) if node == nil return end printNode( depth + 1, node.left ) i = 0 while i < depth printf " " i += 1 end printf "#{node.key} : #{node.value}¥n" printNode( depth + 1, node.right ) end private # ノードを生成する def createNewNode( key, val ) newNode = Node.new( key, val ) newNode.setLeft( nil ) newNode.setRight( nil ) return newNode end end # Main tree = TreeNode.new action = nil while action != 0 tree.printNode( 0 ) puts "実行する操作のタイプを入力して下さい" puts "1:追加 2:検索 3:削除 0:終了 >" action = gets.chomp.to_i case action when 1 puts "追加するキー(数値)を入力して下さい" key = gets.chomp.to_i puts "対応する文字列を入力してください" value = gets.chomp tree.insertNode( key, value ) when 2 puts "検索するキー(数字)を入力して下さい" i = gets.chomp.to_i found = tree.findValue( i ) if found != nil puts "#{found.value}を発見しました" else puts "#{i}は見つかりませんでした" end when 3 puts "削除するキー(数字)を入力して下さい" i = gets.chomp.to_i if tree.deleteNode(i) puts "#{i}を削除しました" else puts "#{i}は見つかりませんでした" end end end