平衡二叉树:又叫AVL树,是一种特殊的二叉查找树
题目
特点
1、是一棵二叉查找树
2、每一个结点的左子树和右子树的深度之差的绝对值不超过1
3、高度为h的AVL树,节点数N最多为2^h-1,最少为N(h)=N(h-1)+N(h-2)+1(初始化N(1)=1,N(2)=2,以此类推)
操作
1、插入
2、删除
3、查找(最大值、最小值、指定值)
4、遍历(先序遍历,层次遍历)
插入
插入结点可能会引起树不平衡,需要对插入结点所引起的最近的结点进行调整,根据插入结点的位置造成不平衡进行分类
(1)LL型,插入结点位于不平衡结点的左子树的左子树上
操作:不平衡结点进行右旋
(2)LR型,插入结点位于不平衡结点的左子树的右子树上
操作:不平衡结点的左子树进行左旋,变成LL型,然后对不平衡结点进行右旋
(3)RL型,插入结点位于不平衡结点的右子树的左子树上
操作:不平衡结点的右子树进行右旋,变成RR型,然后对不平衡结点进行左旋
(4)RR型,插入结点位于不平衡结点的右子树的右子树上
操作:不平衡结点进行左旋
具体左旋、右旋操作可参考下述Java实现部分的leftRotate函数和rightRotate函数
删除
删除操作比插入操作复杂一些,删除结点一样会引起树失衡,所以需要进行上述的调整,根据删除结点的位置进行分类
(1)待删除结点的左子树和右子树都不为空
操作:寻找左子树的最大值(即最右的结点),与待删除结点进行交换,然后删除最右的结点,这个最右结点可能会有一个左孩子结点,可参考下述的情况(2)
(2)待删除结点的左子树和右子树有一棵树为空
操作:不空的那一棵树一定只是一个结点,将该结点与待删除结点交换,然后删除该结点
(3)待删除结点的左子树和右子树都为空
操作:直接删除该结点就行
注意:删除调整会比插入调整多两种情况,可对比下列代码的insert函数和delete函数的调整部分
Java实现
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.LinkedList;
import java.util.Stack;
class TreeNode{
int data;
int height;
TreeNode left;
TreeNode right;
}
class BalanceTree{
TreeNode root=null;
int size = 0;
int getHeight(TreeNode node) {
if (null == node)
return 0;
return node.height;
}
int getBalanceFactor(TreeNode node) {
if (node == null)
return 0;
return getHeight(node.left) - getHeight(node.right);
}
private TreeNode rightRotate(TreeNode node) {
TreeNode centerNode = node.left;
node.left = centerNode.right;
centerNode.right = node;
node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;
centerNode.height = Math.max(getHeight(centerNode.left), getHeight(centerNode.right)) + 1;
return centerNode;
}
private TreeNode leftRotate(TreeNode node) {
TreeNode centerNode = node.right;
node.right = centerNode.left;
centerNode.left = node;
node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;
centerNode.height = Math.max(getHeight(centerNode.left), getHeight(centerNode.right)) + 1;
return centerNode;
}
public TreeNode insert(TreeNode node,int data) {
if (null == node) {
node = new TreeNode();
node.data = data;
node.height = 1;
node.left=node.right=null;
size++;
return node;
}
if (data < node.data)
node.left = insert(node.left, data);
else if (data > node.data)
node.right = insert(node.right, data);
node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;
int BF = getBalanceFactor(node);
if (BF > 1 && getBalanceFactor(node.left)>0) {//LL,rightRotate
return rightRotate(node);
}else if (BF > 1 && getBalanceFactor(node.left)<0) {//LR,leftRotate+rightRotate
node.left = leftRotate(node.left);
return rightRotate(node);
}else if (BF < -1 && getBalanceFactor(node.right)>0) {//RL,rightRotate+leftRotate
node.right = rightRotate(node.right);
return leftRotate(node);
}else if (BF < -1 && getBalanceFactor(node.right)<0) {//RR,leftRotate
return leftRotate(node);
}
return node;
}
public TreeNode delete(TreeNode node, int data) {
if (null == node)
return null;
if (data > node.data) //delete from right subtree
node.right = delete(node.right, data);
else if (data < node.data) //delete from left subtree
node.left = delete(node.left, data);
else {// succeed in finding this node
if (null != node.left && null != node.right) {
TreeNode maxNode = node.left;
while (null != maxNode.right)
maxNode = maxNode.right;
node.data=maxNode.data;
node.left = delete(node.left, maxNode.data);
} else if(null != node.left) {
TreeNode temp = node.left;
node=null;
size--;
return temp;
} else if (null != node.right) {
TreeNode temp = node.right;
node=null;
size--;
return temp;
} else {
node = null;
size--;
return null;
}
}
int BF = getBalanceFactor(node);
if(BF>1){//LL or LR
if(getBalanceFactor(node.left)==-1){//LR
node.left = leftRotate(node.left);
return rightRotate(node);
}else // ==0 or ==1
return rightRotate(node);
} else if(BF<-1){//RL or RR
if(getBalanceFactor(node.right) == 1){//RL
node.right = rightRotate(node.right);
return leftRotate(node);
} else // ==0 or ==-1
return leftRotate(node);
}else
return node;
}
public int findMax(){
if(null == root)
return -1;
TreeNode node = root;
while(null != node.right)
node = node.right;
return node.data;
}
public int findMin(){
if(null == root)
return -1;
TreeNode node = root;
while(null != node.left)
node = node.left;
return node.data;
}
public TreeNode find(int data){
if(null == root)
return null;
TreeNode node = root;
while(null != node){
if(data<node.data)
node = node.left;
else if(data > node.data)
node = node.right;
else
return node;
}
return null;
}
public void levelTraversal(){
if(null == root)
return ;
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
TreeNode node = root;
queue.add(node);
while (!queue.isEmpty()){
node = queue.pop();
System.out.print(node.data + " ");
if (null != node.left)
queue.add(node.left);
if(null != node.right)
queue.add(node.right);
}
System.out.println();
return ;
}
public void preorderTraversal(){
if(null == root)
return ;
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode node = root;
stack.push(node);
while(!stack.isEmpty()){
node = stack.pop();
System.out.print(node.data + " ");
if(null != node.right)
stack.push(node.right);
if (null != node.left)
stack.push(node.left);
}
System.out.println();
return ;
}
}
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Map<Integer,Integer> map = new HashMap<Integer, Integer>();
BalanceTree bt = new BalanceTree();
while (true){
int c = input.nextInt();
if(1 == c){
int num = input.nextInt();
bt.root = bt.insert(bt.root,num);
bt.levelTraversal();
bt.preorderTraversal();
}else if(2 == c){
int num = input.nextInt();
bt.root = bt.delete(bt.root,num);
bt.levelTraversal();
bt.preorderTraversal();
}else
break;
}
input.close();
}
}