二叉排序树和AVL树
1、基本概念
1)二叉排序树BST:对于任何一个非叶子节点,要求其左子节点的值比当前值小,其右子节点的值比当前值大。
2)中序遍历二叉排序树会得到一个升序序列。
2、二叉排序树的创建
1)创建节点和二叉排序树
2)递归添加节点
3、二叉排序树的删除节点
0)预先判断:判断二叉排序树是否存在;判断删除节点是否存在
1)删除节点为叶子节点
(1)首先判断该叶子节点的父节点是否为空
(2)若为空,则说明删除节点为根节点,且根节点为叶子节点,即:二叉排序树只有一个根节点,将根节点置为空,即可删除。
(3)若不为空,则再判断删除节点为父节点的左子节点还是右子节点;
(4)若为左子节点,则把父节点的左子节点置为空,即可删除;
(5)若为右子节点,则把父节点的右子节点置为空,即可删除。
2)删除节点为只有一个子节点的非叶子节点
(1)首先判断删除节点的唯一子节点是左子节点还是右子节点;
(2)若为左子节点,则再判断删除节点的父节点是否为空;
(3)若为空,则把删除节点的左子节点赋给根节点,即可删除;
(3)若不为空,则判断删除节点是父节点的左子节点还是右子节点;
(4)若为左子节点,则把删除节点的左子节点赋给父节点的左子节点,即可删除;
(4)若为右子节点,则把删除节点的左子节点赋给父节点的右子节点,即可删除;
(2)若为右子节点,则再判断删除节点的父节点是否为空;
(3)若为空,则把删除节点的左子节点赋给根节点,即可删除;
(3)若不为空,则判断删除节点是父节点的左子节点还是右子节点;
(4)若为左子节点,则把删除节点的右子节点赋给父节点的左子节点,即可删除;
(4)若为右子节点,则把删除节点的右子节点赋给父节点的右子节点,即可删除;
注:标号相同的步骤表示选择结构的两个分支
3)删除节点为有两个子节点的非叶子节点
(1)找到删除节点的右子树最小节点,删除,并把最小值赋给删除节点的;
(2)或者:找到删除节点的左子树最大节点,删除,并把最大值赋给删除节点;
4、AVL树
1)定义:是空树或者它的左右子树高度差的绝对值 <= 1,且左右子树都为平衡二叉树
2)左旋转(右子树高度 - 左子树高度 > 1)
(1)创建和当前节点值相同的新节点;
(2)设置新节点的左子节点为当前节点的左子节点;
(3)设置新节点的右子节点为当前节点的右子节点的左子节点;
(4)把当前节点的值设为当前节点的右子节点的值;
(5)设置当前节点的右子节点为它原来的右子节点的右子节点;
(6)设置当前节点的左子节点为新节点。
3)右旋转(左子树高度 - 左子树高度 > 1)
(1)创建和当前节点值相同的新节点;
(2)设置新节点的右子节点为当前节点的右子节点;
(3)设置新节点的左子节点为当前节点的左子节点的右子节点;
(4)把当前节点的值设为当前节点的左子节点的值;
(5)设置当前节点的左子节点为它原来的左子节点的左子节点;
(6)设置当前节点的右子节点为新节点。
4)左旋转-双旋转
(1)满足左旋转的条件:右子树高度 - 左子树高度 > 1
(2)若当前节点的右子节点不为空,且当前节点的右子节点的左子树高度 > 当前节点的右子节点的右子树高度;
(3)先让当前节点的右子节点进行右旋转,再让当前节点左旋转;
5)右旋转-双旋转
(1)满足右旋转的条件:左子树高度 - 右子树高度 > 1
(2)若当前节点的左子节点不为空,且当前节点的左子节点的右子树高度 > 当前节点的左子节点的左子树高度;
(3)先让当前节点的左子节点进行左旋转,再让当前节点右旋转;
class BinarySortTree {
Node root;
// 查找删除节点
public Node search(int value) {
if(root == null) {
return null;
}else {
return root.search(value);
}
}
// 查找删除节点的父节点
public Node searchParent(int value) {
if(root == null) {
return null;
}else {
return root.searchParent(value);
}
}
// 删除以node为根节点的最小节点,并返回其值
public int deleteRightMin(Node node) {
Node min = node;
while(min.left != null) {
min = min.left;
}
deleteNode(min.value);
return min.value;
}
// 删除以node为根节点的最大节点,并返回其值
public int deleteLeftMax(Node node) {
Node max = node;
while(max.right != null) {
max = max.right;
}
deleteNode(max.value);
return max.value;
}
// 删除节点
public void deleteNode(int value) {
// 判断二叉树是否存在
if(root == null) {
return;
}
Node targetNode = search(value);
// 判断删除节点是否存在
if(targetNode == null) {
return;
}
Node parent = searchParent(value);
// 情况1:删除节点为叶子节点
if(targetNode.left == null && targetNode.right == null) {
// 判断父节点是否为空
if(parent == null) {// root.left == null && root.right == null
root = null;
return;
}
// 判断叶子节点是父节点的左子节点还是右子节点
if(parent.left != null && parent.left.value == value) {
parent.left = null;
}else if(parent.right != null && parent.right.value == value) {
parent.right = null;
}
}else if(targetNode.left != null && targetNode.right != null) {
// 情况3:删除节点有2个子节点
// 找到删除节点的右子树的最小值,删除,并把值赋给删除节点
// 或者找到删除节点的左子树的最大值,删除,并把值赋给删除节点
int min = deleteRightMin(targetNode.right);
targetNode.value = min;
}else {
// 情况2:删除节点只有一个子节点
// 判断删除节点有右子节点还是左子节点
if(targetNode.left != null) {
// 判断父节点是否为空
if(parent == null) {
root = targetNode.left;
}else {
// 判断删除节点是父节点的左子节点还是右子节点
if(parent.left != null && parent.left.value == value) {
parent.left = targetNode.left;
}else if(parent.right != null && parent.right.value == value) {
parent.right = targetNode.left;
}
}
}else {
// 判断父节点是否为空
if(parent == null) {
root = targetNode.right;
}else {
// 判断删除节点是父节点的左子节点还是右子节点
if(parent.left != null && parent.left.value == value) {
parent.left = targetNode.right;
}else if(parent.right != null && parent.right.value == value) {
parent.right = targetNode.right;
}
}
}
}
}
// 添加节点
public void addNode(Node node) {
if(root == null) {
root = node;
}else {
root.addNode(node);
}
}
// 中序遍历
public void midOrder() {
if(root != null) {
root.midOrder();
}else {
System.out.println("二叉排序树为空");
}
}
}
class Node {
int value;
Node left;
Node right;
public Node(int value) {
this.value = value;
}
// 当前节点的左子树高度
public int leftHeight() {
return left.height();
}
// 当前节点的右子树高度
public int rightHeight() {
return right.height();
}
// 左旋转
public void leftRotate() {
Node newNode = new Node(value);
newNode.left = left;
newNode.right = right.left;
value = right.value;
right = right.right;
left = newNode;
}
// 右旋转
public void rightRotate() {
Node newNode = new Node(value);
newNode.right = right;
newNode.left = left.right;
value = left.value;
left = left.left;
right = newNode;
}
// 以当前节点为根节点的树的高度
public int height() {
int leftHeight = 0;
Node tmpLeft = left;
while(tmpLeft != null) {
leftHeight++;
tmpLeft = tmpLeft.left;
}
int rightHeight = 0;
Node tmpRight = right;
while(tmpRight != null) {
rightHeight++;
tmpRight = tmpRight.right;
}
return Math.max(leftHeight, rightHeight);
}
// 查找删除节点
public Node search(int value) {
if(value == this.value) {
return this;
}
if(value < this.value) {
if(this.left != null) {
return this.left.search(value);
}else {
return null;
}
}else {
if(this.right != null) {
return this.right.search(value);
}else {
return null;
}
}
}
// 查找删除节点的父节点
public Node searchParent(int value) {
if((this.left != null && this.left.value == value) || (this.right != null && this.right.value == value)) {
return this;
}
if(this.left != null && value < this.value) {
return this.left.searchParent(value);
}else if(this.right != null && value >= this.value) {
return this.right.searchParent(value);
}else {
return null;
}
}
// 添加节点
public void addNode(Node node) {
if(node == null) {
return;
}else {
if(node.value < this.value) {
if(this.left == null) {
this.left = node;
}else {
this.left.addNode(node);
}
}else {
if(this.right == null) {
this.right = node;
}else {
this.right.addNode(node);
}
}
// 双旋转调整为AVL树
if(rightHeight() - leftHeight() > 1) {
if(right != null && right.leftHeight() > right.rightHeight()) {
right.rightRotate();
leftRotate();
}else {
leftRotate();
}
}
if(leftHeight() - rightHeight() > 1) {
if(left != null && left.rightHeight() > left.leftHeight()) {
left.leftRotate();
rightRotate();
}else {
rightRotate();
}
}
}
}
// 中序遍历
public void midOrder() {
if(this.left != null) {
this.left.midOrder();
}
System.out.println(this);
if(this.right != null) {
this.right.midOrder();
}
}
}