二叉排序树和平衡二叉树(AVL树)Java实现

二叉排序树和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();
		}
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值