(四)区间树

136 阅读1分钟
public class TNode {
    public Color color;
    public int[] interval;
    public int low;
    public int max;
    public TNode left;
    public TNode right;
    public TNode p;

    public TNode(int[] interval) {
        this.interval = interval;
        this.low=interval[0];
    }
}
public class IntervalTree{
    public TNode NIL;
    public TNode root;
    public IntervalTree() {
        this.NIL=new TNode();
        this.NIL.color=Color.BLACK;
        this.NIL.max=Integer.MIN_VALUE;
        this.root=this.NIL;
    }
    public static void main(String[] args) {
        IntervalTree intervalTree = new IntervalTree();
        TNode T=intervalTree.root;
        List<int[]> interval=new ArrayList<>();
        int len=getData(interval);

        for(int k=0;k<len;k++){
            TNode tNode = new TNode(interval.get(k));
            intervalTree.IntervalInsert(T,tNode);
        }
        T= intervalTree.root;
        intervalTree.levelOrder(T);
        Scanner scanner = new Scanner(System.in);
        while (true){
            int[] i=new int[2];
            i[0]=scanner.nextInt();
            if(i[0]<0)
                break;
            i[1]=scanner.nextInt();
            List<TNode> list=new ArrayList<>();
            intervalTree.intervalSearchAll(T,i,list);
            System.out.println("查询所有结果:");
            for(TNode t:list){
                System.out.println(t);
            }
            System.out.println("total:"+list.size());
            System.out.println("查询一个的结果:");
            System.out.println(intervalTree.intervalSearch(T,i));
        }
        intervalTree.levelOrder(T);
    }
    public TNode intervalSearch(TNode T,int[] i){
        TNode x=T;
        while(x!=NIL&&!overlaps(x,i)){
            if(x.left!=NIL&&x.left.max>=i[0])
                x=x.left;
            else
                x=x.right;
        }
        return x;
    }
    public boolean overlaps(TNode x,int[] i){
        if(i[1]<x.interval[0]||i[0]>x.interval[1])
            return false;
        else
            return true;
    }
    public void intervalSearchAll(TNode root, int[] i, List<TNode> list){
        if(overlaps(root,i))
            list.add(root);
        //1、当左子树的max值>=区间i的左端点时左子树可能存在符合条件的节点,否则左子树不存在符合的条件
        if(root.left!=NIL&&root.left.max>=i[0])
            intervalSearchAll(root.left,i,list);
        //当右子树max值>=区间i的左端且根节点的low值<=区间i的右端点
        // (右子树区间low值都<=根节点的low值,所以当根节点<=区间i的右端点时,右子树就可能存在符合条件的节点) 反之右子树不存在符合条件的节点
        if(root.right!=NIL&&root.right.max>=i[0]&&root.low<=i[1])
            intervalSearchAll(root.right,i,list);
    }
    public void levelOrder(TNode T){
        Deque<TNode> queue=new LinkedList<>();
        queue.addLast(T);
        while(!queue.isEmpty()) {
            int size = queue.size();
            while (size > 0) {
                TNode t = queue.pollFirst();
                if(t==NIL)
                {
                    System.out.println("NIL");
                }
                else
                    System.out.println(t);
                if (t.left != null)
                    queue.addLast(t.left);
                if (t.right != null)
                    queue.addLast(t.right);
                size--;
            }
        }
    }
    public   void IntervalInsert(TNode T,TNode z){
        TNode y=NIL;
        TNode x=root;
        while(x!=NIL){
            y=x;
            if(z.low<x.low)
                x=x.left;
            else
                x=x.right;
        }
        z.p=y;
        if(y==NIL)
            root=z;
        else if(z.low<y.low)
            y.left=z;
        else
            y.right=z;
        z.left=NIL;
        z.right=NIL;
        z.color=Color.RED;
        IntervalMaxFixup(T,z);
        RBInsertFixup(T,z);
    }
    public void  IntervalMaxFixup(TNode T,TNode z){
        z.max=z.interval[1];
        TNode x=z.p;
        while(x!=NIL&&(x.max<x.left.max||x.max<x.right.max)){  //调整到根节点或者当x的最大值不小于左、右孩子的最大值时停止调整。
            x.max=Math.max(x.left.max,x.right.max);
            x=x.p;
        }
    }
    public void RBInsertFixup(TNode T,TNode z){
        while (z.p.color==Color.RED){
            if(z.p==z.p.p.left) //case1-3
            {
                TNode y=z.p.p.right;
                if(y.color==Color.RED)  //case1
                {
                    z.p.color=Color.BLACK;
                    y.color=Color.BLACK;
                    z.p.p.color=Color.RED;
                    z=z.p.p;
//                    System.out.println("case1");
                }else if(z==z.p.right)  //case2
                {
                    z=z.p;
                    leftRotate(T,z);
//                    System.out.println("case2");
                }else                   //case3
                {
                    z.p.color= Color.BLACK;
                    z.p.p.color=Color.RED;
                    rightRotate(T,z.p.p);
//                    System.out.println("case3");
                }
            }else               //case4-6
            {
                TNode y=z.p.p.left;
                if(y.color==Color.RED){ //case4
                    z.p.color=Color.BLACK;
                    y.color=Color.BLACK;
                    z.p.p.color=Color.RED;
                    z=z.p.p;
//                    System.out.println("case4");
                }else if(z==z.p.left){ //case5
                    z=z.p;
                    rightRotate(T,z);
//                    System.out.println("case5");
                }else                   //case6
                {
                    z.p.color=Color.BLACK;
                    z.p.p.color=Color.RED;
                    leftRotate(T,z.p.p);
//                    System.out.println("case6");
                }
            }
        }
        root.color=Color.BLACK;
    }
    public void leftRotate(TNode T,TNode x){
        TNode y=x.right;
        x.right=y.left;
        if(y.left!=NIL){
            y.left.p=x;
        }
        y.p=x.p;
        if(x.p==NIL)
            root=y;
        else if(x==x.p.left)
            x.p.left=y;
        else
            x.p.right=y;
        y.left=x;
        x.p=y;

        //旋转后x和y的max值需要调整维护,y的值依赖于x的值,因此先调整x后调整y
        x.max=Math.max(x.left.max,Math.max(x.right.max,x.interval[1]));
        y.max=Math.max(y.left.max,Math.max(y.right.max,y.interval[1]));
    }
    public void rightRotate(TNode T,TNode x){
        TNode y=x.left;
        x.left=y.right;
        if(y.right!=NIL)
            y.right.p=x;
        y.p=x.p;
        if(x.p==NIL)
            root=y;
        else if(x==x.p.left)
            x.p.left=y;
        else
            x.p.right=y;
        y.right=x;
        x.p=y;
        //旋转后x和y的max值需要调整维护,y的值依赖于x的值,因此先调整x后调整y
        x.max=Math.max(x.left.max,Math.max(x.right.max,x.interval[1]));
        y.max=Math.max(y.left.max,Math.max(y.right.max,y.interval[1]));
    }
    //从文件中读取数据
    public static int getData(List<int[]> interval) {
        //将稀疏矩阵从文件中读取出来
        BufferedReader bufferedReader = null;
        int num=0;
        //为保存的数组分配空间
        try {

            InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(new File("F:\java\leetcode\src\algorithm\project4\insert.txt")));
            bufferedReader = new BufferedReader(inputStreamReader);
            String line = null;
            int i=0;
            //按行读取
            while ((line = bufferedReader.readLine()) != null) {
                if (null != line) {
                    //将按行读取的字符串按空格分割,得到一个string数组
                    String[] strings = line.split("\s+");
                    //依次转换为int类型存入到分配好空间的数组
                    if(i==0)
                        num=Integer.valueOf(strings[0]);
                    else{
                        interval.add(new int[]{Integer.valueOf(strings[0]),Integer.valueOf(strings[1])});
                    }
                    i++;
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return num;
    }
}