如何将新节点插入二叉树?

时间:2014-11-26 18:44:27

标签: scala binary-tree

如何将节点插入到与此代码相关的二叉树中:

import util.Random
import collection.mutable.ArrayBuffer
import scala.collection.mutable.Queue
import scala.collection.mutable.Stack

case class Node[K](value:K, var left:Option[Node[K]], 
                   var right:Option[Node[K]],var parent:Option[Node[K]]) {
    def hasLeft:Boolean = if (left!=None) true else false
    def hasRight:Boolean = if (right!=None) true else false
    def hasParent:Boolean = if (parent!=None) true else false
    def isLeaf:Boolean = !hasLeft && !hasRight
    def isParent(n:Node[K]):Boolean = {
        if (!isLeaf) {
            val l = if (hasLeft) left.get else null
            val r = if (hasRight) right.get else null
            l==n || r==n
        }
        else false
    }
}

abstract class BinaryTree[K] {
    def add(value:K)
    def remove(value:K):Boolean
    def height:Int
    def size:Int
}

class Tree[K](implicit ord:K=>Ordered[K]) extends BinaryTree[K] {
    var root:Option[Node[K]] = None
    private var count = 0
    override def add(value:K) {
        root match {
            case None => root = Some(new Node[K](value,None,None,None))
            case Some(node) => if(insert(node,value)) count+=1
        }
    }

    def insert(node:Node[K],newVal:K):Boolean= {
        if(newVal<node.value) {
            node match{
                case Node(_,None,_,_) => node.left = 
                    Some(new Node[K](newVal,None,None,Some(node))); true
                case Node(_,Some(left),_,_) => insert(left,newVal)
            }
        } else if(newVal>node.value) {
            node match{
                case Node(_,_,None,_) => node.right = 
                    Some(new Node[K](newVal,None,None,Some(node))); true
                case Node(_,_,Some(right),_) => insert(right,newVal)
            }
        } else false
    }

    override def remove(value:K):Boolean= {
        root match {
            case None => false
            case Some(node) => {
                binarySearch(value,node) match {
                    case None => false
                    case Some(node) => {
                        count-=1
                        delete(node)
                        true
                    }
                }
            }
        }
    }

    def delete(node:Node[K]) {
        node match {
            case Node(value,None,None,Some(parent)) => updateParent(parent,value,None)
            case Node(value,Some(child),None,Some(parent)) => {
                updateParent(parent,value,Some(child))
                child.parent = Some(parent)
            }
            case Node(value,None,Some(child),Some(parent)) => {
                updateParent(parent,value,Some(child))
                child.parent = Some(parent)
            }
            case Node(_,Some(child),None,None) => {
                root = Some(child)
                child.parent = None
            }
            case Node(_,None,Some(child),None) => {
                root = Some(child)
                child.parent = None
            }
            case Node(_,Some(left),Some(right),_) => {
                var child = right
                while(child.left!=None) {
                    child=child.left.get
                } 
                node.parent match {
                    case Some(parent) => updateParent(parent,node.value,Some(child))
                    case None => root = Some(child)
                }
                child.left = node.left
                child.right = node.right
                left.parent = Some(child)
                right.parent = Some(child)
                if (child.hasParent && child.parent.get.hasLeft && child.parent.get.left.get == child) 
                    child.parent.get.left=None
                else child.parent.get.right=None
                    child.parent = node.parent
                }
            case _ =>
        }

        def updateParent(parent:Node[K],value:K,newChild:Option[Node[K]]) {
            if(value<parent.value) parent.left = newChild
            else parent.right = newChild
        }
    }

    def binarySearch(value:K,node:Node[K]):Option[Node[K]]= {
        if (value==node.value) 
            Some(node)
        else if (value<=node.value) {
            node match {
                case Node(_,None,_,_) => None
                case Node(_,Some(left),_,_) => binarySearch(value,left)
            }
        } else {
            node match{
                case Node(_,_,None,_) => None
                case Node(_,_,Some(right),_) => binarySearch(value,right)
            }
        }
    }

    def inorder:Seq[K]= {
        val nodes = new ArrayBuffer[K]()
        val stack = new Stack[Node[K]]()
        if (size!=0) {
            var cur = root
            while(!stack.isEmpty || cur!=None) {
                cur match {
                    case Some(node) => {
                        stack.push(node)
                        cur = node.left
                    }
                    case None=> {
                        val tmp = stack.pop()
                        nodes += tmp.value
                        cur = tmp.right
                    }
                }
            }
        }
        nodes
    }

    def preorder:Seq[K]= {
        val nodes = new ArrayBuffer[K]()
        val stack = new Stack[Node[K]]()
        if (size!=0) {
            var cur = root
            while(!stack.isEmpty || cur!=None) {
                cur match {
                    case Some(node) => {
                        stack.push(node)
                        nodes += node.value
                       cur = node.left
                    }
                    case None=> {
                        val tmp = stack.pop()
                        cur = tmp.right
                    }
                }
            }
        }
        nodes
    }

    def postorder:Seq[K]= {
        val nodes = new ArrayBuffer[K]()
        val stack = new Stack[Node[K]]()
        if (size!=0) {
            var prev:Option[Node[K]] = None
            stack.push(root.get)
            while(!stack.isEmpty) {
                val cur = stack.top
                prev match {
                    case None=> if (cur.hasLeft) stack.push(cur.left.get) else if (cur.hasRight) stack.push(cur.right.get)
                    case Some(node)=>{
                        if(!cur.isParent(node) && cur.hasLeft) stack.push(cur.left.get)
                        else if (!cur.isParent(node) && cur.hasRight) stack.push(cur.right.get)
                        else if (cur.isParent(node) && cur.hasRight && cur.hasLeft && cur.left.get==node) stack.push(cur.right.get)
                        else {
                            stack.pop()
                             nodes+=cur.value
                        }
                    }
                }
                prev=Some(cur)
           }
        } 
        nodes
    }

    def postorder(node:Option[Node[K]]) {
        node match{
            case None=>
            case Some(n)=>{
                postorder(n.left)
                postorder(n.right)
                println(n.value)
            }
        } 
    }

    override def toString:String= {
        postorder.mkString(" : ")
    }

    override def height:Int= depth(root)

    def depth(node:Option[Node[K]]):Int = {
        node match {
            case None => 0
            case Some(n) => 1+ scala.math.max(depth(n.left),depth(n.right))
        } 
    }

    def prettyPrint(node:Option[Node[K]]):String= {
        if (node == None) ""
        else if(node.get.isLeaf) "\n\\t"+node.get.value.toString
        else node.get.value.toString+"\n\\t"+prettyPrint(node.get.left)+"\n\\t"+prettyPrint(node.get.right)
    }

    def bfs {
        val queue = new Queue[Option[Node[K]]]()
        queue.enqueue(root)
        while(!queue.isEmpty) {
            queue.dequeue match {
                case Some(node)=>{
                    println(node.value)
                    queue.enqueue(node.left)
                    queue.enqueue(node.right)
                }
                case None =>
            }
        }
    }   
    def size = count
}

object App {
    def main(args:Array[String]) {
        val generator = new Random()
        val tree = new Tree[Int]()
    //    (1 until 8).foreach(_=>tree.add(generator.nextInt(100)))
        tree.add(6)
        tree.add(3)
        tree.add(8)
        tree.add(2)
        tree.add(4)
        tree.add(8)
        tree.add(7)
        tree.add(9)
        tree.add(1)
        tree.add(5)
        tree.postorder(tree.root)
        println(tree)
        tree.bfs     
    }
}

1 个答案:

答案 0 :(得分:2)

如果你真的想使用&#39;插入&#39;主要方法&#39;你可以这样做:

tree.root match{
    case None => tree.root = Some(new Node[Int](10,None,None,None))
    case Some(node) => tree.insert(node,10)
}

此代码检查树是否具有root权限。如果有root,那么node是insertet。如果没有root,则创建root。

但你不应该这样做。你不应该称之为“插入&#39;方法直接。这个Tree类是巧妙设计的。它已添加&#39;方法易于使用,并且当您想要为树添加值时,您可以使用该方法。 &#39;插入&#39;方法只是辅助方法。这是&#39;添加&#39;使用的递归方法。在适当的位置插入值的方法。

因此,向这棵树添加内容的唯一正确方法是使用&#39; add&#39;方法。尝试通过调用&#39;插入&#39;来添加内容。方法就像试图在不使用钥匙的情况下开车。你可以做到,但如果你有钥匙在你面前的原因。