Day584&585.平衡二叉树 -数据结构和算法Java
Posted 阿昌喜欢吃黄桃
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Day584&585.平衡二叉树 -数据结构和算法Java相关的知识,希望对你有一定的参考价值。
平衡二叉树
一、出现的原因
解决二叉排序树的问题
二、介绍
三、平衡思路
1、左旋转
-
左旋转思路分析
因为左子树高度为1,右子树高度为3,所以要将左侧进行调整,所以进行左旋转
-
代码实现
package com.achang.avl;
/**
* 平衡二叉树
*/
public class AVLTreeDemo
public static void main(String[] args)
int[] arr = 4,3,6,5,7,8;
AVLTree avlTree = new AVLTree();
for (int i : arr)
avlTree.add(new Node(i));
System.out.println("中序遍历:");
avlTree.midOrder();
System.out.println("树的高度为【"+avlTree.getRoot().height()+"】");
System.out.println("树的左子树高度为【"+avlTree.getRoot().leftHeight()+"】");
System.out.println("树的右子树高度为【"+avlTree.getRoot().rightHeight()+"】");
//平衡二叉树
class AVLTree
private Node root;
public Node getRoot()
return root;
public void add(Node addNode)
if (root != null)
this.root.add(addNode);
else
this.root = addNode;
/**
* @param node 传入Node节点,当做一颗二叉排序数的根节点
* @return 以node为根节点的二叉排序树的最小节点的值,并同时删除这个最小节点
*/
public int deleteRightTreeMin(Node node)
Node temp = node;
//循环的查找左节点,最会找到最小值
while (temp.left != null)
temp = temp.left;
//这时temp就指向了最小节点
deleteNodeByValue(temp.value);
return temp.value;
public void deleteNodeByValue(int value)
if (root == null)
return;
else
Node targetNode = findNodeByValue(value);
if (targetNode == null) //找不到要删除的节点
return;
if (root.left == null && root.right == null) //没有父节点,只有一个节点的情况或当前节点的left和right同时都等于null
root = null;
return;
//找父节点
Node parent = findParentNodeByValue(value);
//第一种情况:叶子节点的情况
if (targetNode.left == null && targetNode.right == null)
//判断targetNode是父节点的左子节点还是右子节点
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)
targetNode.value = deleteRightTreeMin(targetNode.right);
//第三种情况:只有一颗子树的情况
else
//如果targetNode有左子节点
if (targetNode.left != null)
if (parent != null)
//如果targetNode是parent的左子节点
if (value == parent.left.value)
parent.left = targetNode.left;
else
//targetNode是parent的右子节点
parent.right = targetNode.left;
else
root = targetNode.left;
else
if (parent != null)
//如果targetNode有右子节点
if (value == parent.left.value)
//如果targetNode是parent的左子节点
parent.left = targetNode.right;
else
//targetNode是parent的右子节点
parent.right = targetNode.right;
else
root = targetNode.right;
public void midOrder()
if (root != null)
this.root.midOrder();
else
System.out.println("当前二叉排序树为空树,请添加节点");
public Node findParentNodeByValue(int value)
if (root != null)
return root.findParentNodeByValue(value);
else
return null;
public Node findNodeByValue(int value)
if (root != null)
return root.findNodeByValue(value);
else
return null;
//节点
class Node
int value;
Node left;
Node right;
public Node(int vale)
this.value = vale;
/**
* 返回左子树的高度
*/
public int leftHeight()
return left == null ? 0 : left.height();
/**
* 返回右子树的高度
*/
public int rightHeight()
return right == null ? 0 : right.height();
/**
* 返回当前节点为根节点,树的高度
*/
public int height()
return Math.max(left == null ? 0 :left.height(),right == null ? 0 : right.height()) + 1;
//查找要删除节点的父节点
public Node findParentNodeByValue(int value)
if ((this.left != null && this.left.value == value)
|| (this.right != null && this.right.value == value))
return this;
else
if (this.left != null && value < this.value)
return this.left.findParentNodeByValue(value);
else if (this.right != null && value >= this.value)
return this.right.findParentNodeByValue(value);
else
//没有找到父节点
return null;
/**
* 查找要删除的节点,如果找到返回Node,不然就返回null
*
* @param value 希望删除的节点的value值
*/
public Node findNodeByValue(int value)
if (value == this.value)
return this;
else if (value < this.value)
if (this.left != null)
return this.left.findNodeByValue(value);
else
return null;
else
if (this.right != null)
return this.right.findNodeByValue(value);
else
return null;
//添加节点
public void add(Node node)
if (node == null)
return;
if (node.value < this.value)
if (this.left == null)
this.left = node;
else
this.left.add(node);
else
if (this.right == null)
this.right = node;
else
this.right.add(node);
//当添加完一个节点后,需要去判断是否需要平衡,采用哪一种平衡方式
//当前出现需要平衡的情况
if (rightHeight() - leftHeight() > 1)
//左旋转
leftRotate();
//中序遍历
public void midOrder()
if (this.left != null)
this.left.midOrder();
System.out.println(this);
if (this.right != null)
this.right.midOrder();
//平衡左旋转
public void leftRotate()
//创建一个新节点,值为当前根节点
Node newRootNode = new Node(value);
newRootNode.left = left;
newRootNode.right = right.left;
value = right.value;
right = right.right;
left = newRootNode;
@Override
public String toString()
return "Node【" + value + "】";
2、右旋转
- 右旋转思路分析
- 代码实现
package com.achang.avl;
/**
* 平衡二叉树
*/
public class AVLTreeDemo
public static void main(String[] args)
// int[] arr = 4,3,6,5,7,8;
int[] arr = 10,12,8,9,7,6;
AVLTree avlTree = new AVLTree();
for (int i : arr)
avlTree.add(new Node(i));
System.out.println("中序遍历:");
avlTree.midOrder();
System.out.println("树的高度为【"+avlTree.getRoot().height()+"】");
System.out.println("树的左子树高度为【"+avlTree.getRoot().leftHeight()+"】");
System.out.println("树的右子树高度为【"+avlTree.getRoot().rightHeight()+"】");
//平衡二叉树
class AVLTree
private Node root;
public Node getRoot()
return root;
public void add(Node addNode)
if (root != null)
this.root.add(addNode);
else
this.root = addNode;
/**
* @param node 传入Node节点,当做一颗二叉排序数的根节点
* @return 以node为根节点的二叉排序树的最小节点的值,并同时删除这个最小节点
*/
public int deleteRightTreeMin(Node node)
Node temp = node;
//循环的查找左节点,最会找到最小值
while (temp.left != null)
temp = temp.left;
//这时temp就指向了最小节点
deleteNodeByValue(temp.value);
return temp.value;
public void deleteNodeByValue(int value)
if (root == null)
return;
else
Node targetNode = findNodeByValue(value);
if (targetNode == null) //找不到要删除的节点
return;
if (root.left == null && root.right == null) //没有父节点,只有一个节点的情况或当前节点的left和right同时都等于null
root = null;
return;
//找父节点
Node parent = findParentNodeByValue(value);
//第一种情况:叶子节点的情况
if (targetNode.left == null && targetNode.right == null)
//判断targetNode是父节点的左子节点还是右子节点
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)
targetNode.value = deleteRightTreeMin(targetNode.right);
//第三种情况:只有一颗子树的情况
else
//如果targetNode有左子节点
if (targetNode.left != null)
if (parent != null)
//如果targetNode是parent的左子节点
if (value == parent.left.value)
parent.left = targetNode.left;
else
//targetNode是parent的右子节点
parent.right 平衡二叉树&B-树