平衡二叉树
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
}
二叉树遍历
- 先序
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) } } }
- 中序
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 } }
-
后续
fun traversPost(root: Node?) { if (root == null) return traversPost(root.leftChild) traversPost(root.rightChild) print("${root.data} \t") }
- 层遍历
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") } }
平衡二叉树构建
- 左旋转
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) }
需要左旋转存在两种
初始状态 中间 最终 备注 左旋转 右子提上,变根节点;自身变右子左节点 需要先形成线性的右子树 - 右旋转
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) }
- 计算节点深度
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 }
- 计算节点平衡因子
fun caculateBalance(root: Node): Int { val leftDepth = root.leftChild?.depth ?: 0 val rightDepth = root.rightChild?.depth ?: 0 return leftDepth - rightDepth }
- 插入数据
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) }
- 每次插入数据找到根节点
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) }