数据结构-树-源码分析(二叉查找树, 平衡二叉树)
二叉查找树
所有子树满足 : 左子树上所有结点的值 < 根结点的值 < 右子树上所有结点的值
public class QBST<K extends Comparable<K>, V> {
//树结点
class QNode {
K key;
V value;
QNode left;//左子树
QNode right;//右子树
//构造根结点 若树或子树为空时,创建根节点
QNode(K key, V value) {
this.key = key;
this.value = value;
this.left = null;
this.right = null;
}
}
private QNode root;//根结点 树的唯一标识
private int count;//结点个数
//构造空二叉树
public QBST() {
root = null;
count = 0;
}
//获取结点个数
public int size() {
return count;
}
//判断二叉树是否为空
public boolean isEmpty() {
return count == 0;
}
//插入结点
// 1.树为空则创建根结点
// 2.key==根节点key, 更新value
// 3.key<根节点key/key>根节点key 插入左子树/右子树
public void insert(K key, V value) {
root = insert(root, key, value);
}
//向以node为根的树中插入结点(key, value)
//返回新的根节点
private QNode insert(QNode node, K key, V value) {
//检查key是否为空
//node为空 创建根节点
if (node == null) {
count++;
return new QNode(key, value);
}
//key > 根节点的key
if (key.compareTo(node.key) == 1) {
node.right = insert(node.right, key, value);
//key < 根节点的key
} else if (key.compareTo(node.key) == -1) {
node.left = insert(node.left, key, value);
//key == 根节点的key
} else {
node.value = value;
}
return null;
}
}
缺点
会出现以下四种不平衡的情况:
LL型
LR型
RL型
RR型
平衡二叉树
在二叉查找树的基础上:
所有子树满足 : 左右两个子树的高度差的绝对值不超过1
解决方案 : 通过左旋或则右旋让二叉树平衡
- LL :右旋 左子变父, 左边的右孙变右边的左孙
-
RR : 左旋 右子变父, 右边的左孙变左边的右孙
-
LR : 先对左子树左旋, 再整体右旋
- RL : 先对右子树右旋, 再整体左旋
public class BalancedBinaryTree<K extends Comparable<K>, V> {
private AVLNode root;//根结点 树的唯一标识
private int count;//结点个数
//定义二叉树结点
class AVLNode {
K key;
V value;
public int depth;//结点深度/高度
public int balance;//平衡度 1:左子树更深; -1:右子树更深; 0:左右平衡
public AVLNode parent;//父节点 (根节点会发生改变, 需要用到父节点, 类似双向链表)
public AVLNode left;//左子树
public AVLNode right;//右子树
//创建根节点
public AVLNode(K key, V value) {
this.key = key;
this.value = value;
depth = 1;
balance = 0;
left = null;
right = null;
}
}
//计算结点的深度
public int cDepth(AVLNode root) {
int depth = 0;
if (root.left != null) {
depth = root.left.depth;
}
if (root.right != null && root.right.depth > depth) {
depth = root.right.depth;
}
depth++;
return depth;
}
//计算平衡度
public int cBalance(AVLNode root) {
int left_depth = root.left == null ? 0 : root.left.depth;
int right_depth = root.left == null ? 0 : root.right.depth;
return left_depth - right_depth;
}
//左旋: 右子变父, 右边的左孙 -> 左边的右孙
public void left_rotate(AVLNode p) {
AVLNode pParent = p.parent;
AVLNode pRightSon = p.right;//右子
AVLNode pGrandLeftSon = p.right.left;//右边的左孙
//右子变父
pRightSon.parent = p.parent;
//判断p是左子树还是右子树
if (pParent != null) {
if (pParent.left == p) {
pParent.left = pRightSon;
} else {
pParent.right = pRightSon;
}
}
pRightSon.left = p;
p.parent = pRightSon;
//右边的左孙 -> 左边的右孙
p.right = pGrandLeftSon;
if (pGrandLeftSon != null) {
pGrandLeftSon.parent = p;
}
//左旋后重新计算结点的深度和平衡度
// p和pRightSon受到影响
p.depth = cDepth(p);
p.balance = cBalance(p);
pRightSon.depth = cDepth(pRightSon);
pRightSon.balance = cBalance(pRightSon);
}
//右旋: 左子变父, 左边的右孙 -> 右边的左孙
public void right_rotate(AVLNode p) {
AVLNode pParent = p.parent;
AVLNode pLeftSon = p.left;//左子
AVLNode pGrandRightSon = p.left.right;//左边的右孙
//左子变父
pLeftSon.parent = p.parent;
//判断p是左子树还是右子树
if (pParent != null) {
if (pParent.left == p) {
pParent.left = pLeftSon;
} else {
pParent.right = pLeftSon;
}
}
pLeftSon.right = p;
p.parent = pLeftSon;
//左边的右孙 -> 右边的左孙
p.left = pGrandRightSon;
if (pGrandRightSon != null) {
pGrandRightSon.parent = p;
}
//右旋后重新计算结点的深度和平衡度
// p和pLeftSon受到影响
p.depth = cDepth(p);
p.balance = cBalance(p);
pLeftSon.depth = cDepth(pLeftSon);
pLeftSon.balance = cBalance(pLeftSon);
}
//插入结点
public void insert(K key, V value) {
insert(root, key, value);
}
public void insert(AVLNode node, K key, V value) {
//判断key是否为空
//key > root.key
if (key.compareTo(node.key) == 1){
if (node.right != null ) {
insert(node.right, key, value);
} else {
root.right = new AVLNode(key, value);
root.right.parent = root;
}
//key < root.key
} else if(key.compareTo(node.key) == -1) {
if (root.left != null) {
insert(root.left, key, value);
} else {
root.left = new AVLNode(key, value);
root.left.parent = root;
}
//key == root.key
} else {
node.value = value;
return;
}
//插入结点后修改结点的平衡度
node.balance = cBalance(node);
//左树深度大于右树2层, 树不平衡了需要旋转
//分为两种 1.LL型 2.LR型
if (node.balance == 2) {
if (node.left.balance == 1) {
//LL型 对node右旋
right_rotate(node);
} else if(node.left.balance == -1) {
//LR型 先对左子树左旋, 在对node右旋
left_rotate(node.left);
right_rotate(node);
}
}
//右树深度大于左树2层, 树不平衡了需要旋转
//分为两种 1.RR型 2.RL型
if (node.balance == -2) {
if (node.right.balance == -1) {
//RR型 对node左旋
left_rotate(node);
} else if(node.right.balance == 1) {
//RL型 先对右子树右旋, 在对node左旋
right_rotate(node.right);
left_rotate(node);
}
}
//修改深度和平衡度
node.depth = cDepth(node);
node.balance = cBalance(node);
}
}
- 参考文章链接
https://blog.csdn.net/qq_42419025/article/details/105915670
https://www.cnblogs.com/start1225/p/10182710.html