平衡二叉树构造和递归遍历

平衡二叉树

1.构造平衡二叉树  

  • 插入数据
  • 计算深度和平衡因子
  • 左右旋转调整深度和平衡因子
  • 找到根节点

2.遍历

节点结构

class Node(var data: Int) {
    var leftChild: Node? = null
    var rightChild: Node? = null
    var parent: Node? = null

    var balance: Int = 0
    var depth: Int = 1
}

二叉树遍历

  1. 先序 
    fun traversePre(root: Node?) {
    
        if (root== null) {
            return
        }
        print(" ${root.data} \t")
        traversePre(root?.leftChild)
        traversePre(root?.rightChild)
    }
    
    
    //非递归
    fun traversePreNR(root: Node?) {
        if (root == null) return
        val nodes = Stack<Node>()
        nodes.push(root)
        while(!nodes.isEmpty()) {
            var node = nodes.pop()
            print("${node.data}\t")
            node.rightChild?.apply{
                nodes.push(this)
            }
            node.leftChild?.apply{
                nodes.push(this)
            }
        }
    }
  2. 中序
    fun traversMiddle(root: Node?) {
        if (root == null)
        return
        traversMiddle(root.leftChild)
        print("${root.data} \t")
        traversMiddle(root.rightChild)
    }
    
    fun traversMiddleNR(root: Node) {
        var nodes = Stack<Node>()
        var currentNode :Node? = root
        while (!nodes.isEmpty() || currentNode!= null) {
            while (currentNode!=null) {
                nodes.push(currentNode)
                currentNode = currentNode.leftChild
            }
            var node = nodes.pop()
            print("${node.data} \t")
            currentNode = node.rightChild
    
        }
    
    }

  3. 后续

    fun traversPost(root: Node?) {
        if (root == null)
            return
        traversPost(root.leftChild)
        traversPost(root.rightChild)
        print("${root.data} \t")
    }
    
    
    

  4. 层遍历
    fun traverseLayer(root: Node?) {
        if (root == null) return
        val queue: Queue<Node> = LinkedList()
        queue.offer(root)
        while (!queue.isEmpty()) {
            val node = queue.poll()
            if (node.leftChild!=null) {
                queue.offer(node.leftChild)
            }
            if (node.rightChild!=null) {
                queue.offer(node.rightChild)
            }
            print("${node.data} \t")
        }
    
    }

平衡二叉树构建

  1. 左旋转
    fun leftRotate(node: Node) {
        val parent = node.parent
        val rightSon = node.rightChild
        val leftGrandSon = rightSon?.leftChild
    
        //右子变父
        rightSon?.parent = parent
        parent?.apply {
            if (node == parent.rightChild) {
                parent.rightChild = rightSon
            } else if (node == parent.leftChild) {
                parent.leftChild = rightSon
            }
        }
        //添加左子
        rightSon?.leftChild = node
        node.parent = rightSon
        //原父添加右子
        node.rightChild = leftGrandSon
        leftGrandSon?.parent = node
        //自己计算深度回合平衡因子
        node.depth = caculateDepath(node)
        node.balance = caculateBalance(node)
        //新父计算深度和平衡因子
        rightSon?.depth = caculateDepath(node)
        rightSon?.balance = caculateBalance(node)
    
    }

    需要左旋转存在两种

    初始状态中间最终备注
    左旋转 右子提上,变根节点;自身变右子左节点
    需要先形成线性的右子树

  2. 右旋转
    fun rightRotate(node: Node) {
        val parent = node.parent
        val leftSon = node.leftChild
        val rightGrandSon = leftSon?.rightChild
    
        //左子变父
        leftSon?.parent = parent
        parent?.apply {
            if (node == parent.rightChild) {
                parent.rightChild = leftSon
            } else if (node == parent.leftChild) {
                parent.leftChild = leftSon
            }
        }
    
        //添加右子
        leftSon?.rightChild = node
        node.parent = leftSon
    
        //添加左子
        node.leftChild = rightGrandSon
        rightGrandSon?.parent = node
    
        //自己计算深度回合平衡因子
        node.depth = caculateDepath(node)
        node.balance = caculateBalance(node)
        //新父计算深度和平衡因子
        leftSon?.depth = caculateDepath(node)
        leftSon?.balance = caculateBalance(node)
    
    }

  3. 计算节点深度
    fun caculateDepath(root: Node): Int {
        var depath = root.leftChild?.depth ?: 0
        if (root.rightChild != null && depath < root.rightChild?.depth ?: 0) {
            depath = root.rightChild?.depth ?: depath
        }
    
        depath++
        return depath
    
    }

  4. 计算节点平衡因子
    fun caculateBalance(root: Node): Int {
    
        val leftDepth = root.leftChild?.depth ?: 0
        val rightDepth = root.rightChild?.depth ?: 0
    
        return leftDepth - rightDepth
    }

  5. 插入数据
    fun insert(root: Node, data: Int) {
    
        if (data < root.data) {
            root.leftChild?.apply {
                insert(this, data)
            } ?: run {
                root.leftChild = Node(data)
                root.leftChild?.parent = root
            }
        } else {
            root.rightChild?.apply {
                insert(this, data)
            } ?: run {
                root.rightChild = Node(data)
                root.rightChild?.parent = root
            }
        }
    
        root.balance = caculateBalance(root)
    
        if (root.balance >= 2) {
            if (root.leftChild?.balance == -1) {
                leftRotate(root.leftChild!!)
            }
            rightRotate(root)
        }
    
        if (root.balance <= -2) {
            if (root.leftChild?.balance == 1) {
                rightRotate(root.leftChild!!)
            }
            leftRotate(root)
        }
        root.balance = caculateBalance(root)
        root.depth = caculateDepath(root)
    
    }

  6. 每次插入数据找到根节点
    fun main() {
        var value = 1
        var root = Node(value)
        for( i in 2..8) {
            insert(root, i)
            while (root.parent!=null) {
                val temp = root.parent
                root = temp!!
                print("${root.data} \t")
            }
        }
        println("\n遍历 先序===============================")
        traversePre(root)
        println("\n遍历 中序===============================")
        traversMiddle(root)
        println("\n遍历 后序===============================")
        traversPost(root)
        println("\n层遍历 ===========")
        traverseLayer(root)
    
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值