平衡二叉树的插入操作(java)

平衡二叉树

 1.平衡二叉树是特殊的二叉查找树,为了解决二叉查找树查找时间复杂度变大的问题
 2.平衡二叉树AVL:该树的每个节点的左子树与右子树的高度差的绝对值为1(-1,0,1) 该差值也称为平衡因子(BF)
 3. 插入和删除节点都有可能导致平衡二叉树失衡,这里只讨论插入操作使AVL失衡的情况,

插入节点导致平衡二叉树失衡的情况有4种:(x节点为失衡点)

  1.  在节点X的左孩子节点的左子树中插入元素
  2.  在节点X的左孩子节点的右子树插入元素;
  3.  在节点X的右孩子节点的左子树插入元素;
  4.  在节点X的右孩子节点的右子树插入元素;

补充:高度:指当前节点到其叶子节点的最长路径;所有叶子节点的高度都为0,空树的高度为-1; 深度:根节点到当前节点的最长路径,根节点的深度为0;

public class AVL_Tree {

	/**
	 * 情况一:在节点X的左孩子节点的左子树中插入元素 返回旋转后的根节点 把 x(B(A)) ==> B(A,X)
	 */
	public static BsNode situationOne(BsNode x) {
		System.out.println("===============>> 失衡:情况一");
		BsNode B = x.left;
		x.left = null;
		B.right = x;
		B.parent = x.parent;

		if (x.parent != null) {
			if (x.parent.left == x) {
				x.parent.left = B;
			} else {
				x.parent.right = B;
			}
		}

		x.parent = B;

		return B;
	}

	/**
	 * 情况二:在节点X的左孩子节点的右子树插入元素;
	 * 
	 * @return 返回旋转后的节点 把 x(B(A)) ==> A(B,X)
	 */
	public static BsNode situationTwo(BsNode x) {
		System.out.println("===============>> 失衡:情况二");
		BsNode B = x.left;
		BsNode A = B.right;
		B.right = null;
		B.parent = A;
		A.left = B;
		x.left = null;
		A.right = x;
		A.parent = x.parent;

		if (x.parent != null) {
			if (x.parent.left == x) {
				x.parent.left = A;

			} else {
				x.parent.right = A;
			}
		}
		x.parent = A;
		return A;
	}

	/**
	 * 情况三:在节点X的右孩子节点的左子树插入元素;
	 * 
	 * @return 返回旋转后的节点 把 x(B(A)) ==> A(X,B)
	 */
	public static BsNode situationThree(BsNode x) {
		System.out.println("===============>> 失衡:情况三");
		BsNode B = x.right;
		BsNode A = B.left;
		B.left = null;
		B.parent = A;
		A.right = B;

		x.right = null;
		A.left = x;
		A.parent = x.parent;

		if (x.parent != null) {
			if (x.parent.left == x) {
				x.parent.left = A;
			} else {
				x.parent.right = A;
			}
		}
		x.parent = A;
		return B;
	}

	/**
	 * 情况四:在节点X的右孩子节点的右子树插入元素;
	 * 
	 * @return 返回旋转后的节点 把 x(B(A)) ==> B(X,A)
	 */
	public static BsNode situationFour(BsNode x) {
		System.out.println("===============>> 失衡:情况四");
		BsNode B = x.right;
		x.right = null;
		B.left = x;
		B.parent = x.parent;

		if (x.parent != null) {
			if (x.parent.left == x) {
				x.parent.left = B;
			} else {
				x.parent.right = B;
			}
		}
		x.parent = B;
		return B;
	}

	/**
	 * 计算节点的高度
	 */
	public static int getNodeHei(BsNode node) {
		if (node == null) {
			return 0;
		}
		int h = Math.max(getNodeHei(node.left), getNodeHei(node.right)) + 1;
		return h;
	}

	/**
	 * 获取节点的平衡因子BF
	 */
	public static int getNodeBf(BsNode node) {
		if (node == null) {
			return 0;
		}
		return Math.abs(getNodeHei(node.left) - getNodeHei(node.right));
	}

	/**
	 * 插入节点 1. 如果二叉查找树为空,根节点的key为data 2.二叉查找树不为空: 2.1 比较data与root的键值 2.2
	 * 若大于,则判断右子树是否为空,如为空,插入,不为空,继续执行2.1 -- 递归 2.2 若小于,判断左子树是否为空,为空,插入,不为空,继续执行2.1
	 * -- 递归 2.3若相等,return;
	 */
	public static void insert(BsNode root, int data) {
		if (root == null) {
			root = new BsNode(data);
		}

		if (data < root.key) {
			if (root.left == null) {
				root.left = new BsNode(data, null, null, root);
			} else {
				insert(root.left, data);
				// 计算该树的平衡因子
				int bf = getNodeBf(root);
				System.out.println("1:插入后的Bf = " + bf);
				if (bf == 2) {
					// 判断是情况一还是情况二?
					if (data < root.left.key) { // 情况一
						situationOne(root);
					} else { // 情况二
						situationTwo(root);
					}
				}
			}
		} else if (data > root.key) {
			if (root.right == null) {
				root.right = new BsNode(data, null, null, root);
			} else {
				insert(root.right, data);
				// 计算平衡因子
				int bf = getNodeBf(root);
				System.out.println("2:插入后的Bf = " + bf);
				if (bf == 2) {
					// 判断是情况三还是情况四?
					if (data < root.right.key) { // 情况三
						situationThree(root);
					} else { // 情况四
						situationFour(root);
					}
				}
			}
		} else {
			return;
		}

	}
	
	//测试
	public static void main(String[] args) {
		// 叶子节点
		Binary_Search_Tree bst = new Binary_Search_Tree();
		
		BsNode root = new BsNode(9);
		insert(root, 5);
		insert(root, 13);
		
		//insert(root, 7);
		//insert(root, 6);// 右-左 -> 情况三
		//insert(root, 8); // 右-右 -> 情况四
		
		//insert(root, 12);
		//insert(root, 10); //左左 -> 情况一
		
		insert(root, 11);
		insert(root, 12); //左右 -> 情况二
		bst.LevelTree(root); //层次遍历
		
	}
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值