平衡二叉树(AVL树)

平衡二叉树:又叫AVL树,是一种特殊的二叉查找树

题目

PAT甲级 1066 Root of AVL Tree

POJ 3481 Double Queue

特点

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();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值