zoukankan      html  css  js  c++  java
  • 二叉树

    二叉树  Binary Tree

    2019-06-27   20:52:02

    /**
     * @ClassName BinaryTree
     * @Author wangyudi
     * @Date 2019/6/27 17:51
     * @Version 1.0
     * @Description 二叉数数据结构
     * 成员变量:根结点 root 结点类 Node
     * 成员方法:大小 size、获取值 get、加入值 put、
     * 最大键 max、最小键 min、向下取整floor、向上取整ceiling、
     * 根据排名选择 select、排名 rank、
     * 删除最小键 deleteMin、删除任意键 delete;
     */
    
    public class BinaryTree<Key extends Comparable<Key>, Value> {
        public Node root;//根结点,二叉树只要一个根结点即可找到所有的结点
    
        //匿名内部类,用于表示二叉树的抽象数据结构--结点
        //结点一共含有5个成员变量
        private class Node {
            Key key; //必须是Comparable对象
            Value value;
            int count;//用于rank()
            Node left;
            Node right;
    
            public Node(Key key, Value value, int count, Node left, Node right) {
                this.key = key;
                this.value = value;
                this.count = count;
                this.left = left;
                this.right = right;
            }
        }
    
        public int size() {
            return size(root);
        }
    
        public int size(Node node) {
            if (node == null) return 0;  //不可缺少
            else return node.count;
        }
    
        public Value get(Key key) {
            return get(key, root);
        }
    
        public Value get(Key key, Node node) {
            if (node == null) return null; //没有找到
            int cmp = key.compareTo(node.key); //根据cmp的值确定是否为根结点或在左/右树寻找
            if (cmp > 0) {
                return get(key, node.right);
            } else if (cmp < 0) {
                return get(key, node.left);
            } else {
                return node.value;  //找到
            }
        }
    
        public void put(Key key, Value value) {
            root = put(key, value, root);
        }
    
        public Node put(Key key, Value value, Node node) {
            if (node == null) { //没有找到相同的键,则新键一个结点,并将自身的引用返回给上一结点(父结点)
                return new Node(key, value, 1, null, null);
            }
            int cmp = key.compareTo(node.key);//根据cmp的值确定是否为根结点或在左/右树寻找
            if (cmp > 0) {
                node.right = put(key, value, node.right);
            } else if (cmp < 0) {
                node.left = put(key, value, node.left);
            } else {  //找到相同的key
                node.value = value;
                return node;
            }
            node.count = size(node.left) + size(node.right) + 1; //该表大小
            return node;
        }
    
        public Node max(Node node) {
            if (node.right == null) return node; //直到某一结点的右结点为null,返回该结点
            return max(node.right);
        }
    
        public Node min(Node node) {  //直到某一结点的左结点为null,返回该结点
            if (node.left == null) return node;
            return min(node.left);
        }
    
        //向下取整
        //如果key比根节点小,则floor结点一定在左子树中(如果有)。
        //如果key比根节点大,则floor在右子树中或是根结点。
        //如果根节点为null,则没有找到
        public Node floor(Key key, Node node) {
            if (node == null) return null;
            int cmp = key.compareTo(node.key);
            if (cmp < 0) {
                return floor(key, node.left);
            } else if (cmp > 0) {
                Node temp = floor(key, node.right); //可能在右子树中
                if (temp != null) return temp; //存在,则floor结点为右子树中找到的结点
                return node;//如果右子数中不存在,则floor(key,node.right)返回null,floor结点为根结点
            } else {
                return node;
            }
        }
    
        //基本思路和floor相同
        //如果比根结点大,则在右树
        //如果比根结点小,则可能在左树或根结点
        //如果根节点为null,则没有找到
        public Node ceiling(Key key, Node node) {
            if (node == null) return null;
            int cmp = key.compareTo(node.key);
            if (cmp > 0) {
                return floor(key, node.right);
            } else if (cmp < 0) {
                Node temp = ceiling(key, node.left); //可能在左子树中
                if (temp != null) return temp;
                return node;
            } else {
                return node;
            }
        }
    
        //查找排名为k的键的值
        public Value select(int k) {
            return select(root, k).value;
        }
    
        public Node select(Node node, int k) {
            if (node == null) return null; //根结点为null,则表示没有找到
            if (size(node.left) == k) return node;
            else if (size(node.left) > k) {
                return select(node.left, k);
            } else {
                return select(node.right, k - 1 - size(node.left)); //在右数中寻找时,要调整排名
            }
        }
    
        //键值为key的结点在树中的排名
        public int rank(Node node, Key key) {
            if (node == null) return 0; //根结点为null,则返回0,表示排名为0
            int cmp = key.compareTo(node.key);
            if (cmp == 0) {
                return size(node.left);
            } else if (cmp > 0) {
                return size(node.left) + 1 + rank(node.right, key); //在右子树中查找时调整返回值
            } else {
                return rank(node.left, key);
            }
        }
    
        public void deleteMin() {
            root = deleteMin(root);
        }
    
        //删除最小的结点
        //思路:最小的结点是递归后,左子树为null的那个结点;删除的方法,是将该结点的右子树返回给上次递归调用的结点。
        public Node deleteMin(Node node) {
            if (node.left != null) {
                node.left = deleteMin(node.left);
                node.count = size(node.left) + size(node.right) + 1; //调整大小
                return node; //不是被删除的结点,返回自身结点给上次递归调用的结点。
            } else {
                return node.right;
            }
        }
    
        public void delete(Key key) {
            root = delete(key, root);
        }
    
        //删除某一结点
        //根据cmp的值,选择在左/右子树中删除结点
        //如果递归中,根结点为null,则表示没有找到该键,返回空
        //如果递归中找到,根结点便是需要删除的结点,有分为两种去情况
        //情况一:要求删除的结点没有左/右子树,返回右/左子树根结点,被删除的结点会被GC清理。
        //情况二:要求删除的结点右左和右子树,
        //              1.保存被删除的根结点temp  2.使用min()方法,在被删除结点的右自书中找到后记结点node  3.使用deleteMin()方法,在被删结点的右子树中删除后继结点
        //              4.返回右子树根结点给后继结点的右结点  5.被删结点的左子树结点给后继结点  6.返回后继结点给上一次的递归
        //调整大小,没有删除操作的结点,放回自身根结点
        public Node delete(Key key, Node node) {
            if (node == null) return null;//没找到
            int cmp = key.compareTo(node.key);
            if (cmp > 0) {
                node.right = delete(key, node.right);
            } else if (cmp < 0) {
                node.left = delete(key, node.left);
            } else {
                if (node.left == null) return node.right;
                if (node.right == null) return node.left;
                Node temp = node;  //为了获得left子树结点
                node = min(node.right);
                node.right = deleteMin(temp.right);
                node.left = temp.left;
            }
            node.count = size(node.right) + size(node.left) + 1;
            return node;
        }
    
        public void display() {
            display(root);
        }
    
        public void display(Node node) {
            if (node == null) return;
            display(node.left);
            System.out.print(node.value + "  ");
            display(node.right);
        }

      
    //返回支持迭代获取数据的数据结构
      public Iterable<Value> values() {
    return values(min().key, max().key);

    }

    public Iterable<Value> values(Key lo, Key hi) {
    ArrayList<Value> valueArrayList = new ArrayList<>();
    values(root, lo, hi, valueArrayList);
    return valueArrayList;
    }

    public void values(Node node, Key lo, Key hi, ArrayList<Value> arr) {
    if (node == null) return;
    int cmplo = lo.compareTo(node.key);
    int cmphi = hi.compareTo(node.key);
    if (cmplo < 0) {
    values(node.left, lo, hi, arr);
    }
    if (cmplo <= 0 && cmphi >= 0) {
    arr.add(node.value);
    }
    if (cmphi > 0) {
    values(node.right, lo, hi, arr);
    }
    }
    }
    /**
     * @ClassName TestCase
     * @Author wangyudi
     * @Date 2019/6/27 20:11
     * @Version 1.0
     * @Description  测试用例
     */
    public class TestCase {
        public static void main(String[] args) {
            BinaryTree<Integer, String> tree = new BinaryTree<>();
            tree.put(12,"12..");
            tree.put(2,"2..");
            tree.put(34,"34..");
            tree.put(17,"17..");
            tree.put(55,"55..");
            tree.put(214,"214..");
            tree.display();
            System.out.println();
            tree.deleteMin();
            tree.delete(12);
            tree.delete(222);
            tree.delete(214);
            tree.display();
    
            System.out.println();
            System.out.println(tree.select(0));
            System.out.println(tree.rank(tree.root,55));
    
        }
    }
    
    
    //结果
    2..  12..  17..  34..  55..  214..  
    17..  34..  55..  
    17..
    2
  • 相关阅读:
    vue 数字滚动的插件 vue-count-to
    ASP.NET Core EF 查询获取导航属性值,使用Include封装
    nginx在asp.net mvc项目中 配置 初步快速入门
    JQuery EasyUI 扩展方法 日期控件 设置时间段函数
    JQueryEasyUI easyui-combobox 单击文本区域显示下拉菜单
    Jquery Easy UI Datagrid 上下移动批量保存数据
    ASP.NET MVC BundleConfig介绍和使用
    ASP.NET MVC5 视图相关学习
    SqlDependency数据库同步+signalr 推送消息
    T4 模板自动生成带注释的实体类文件
  • 原文地址:https://www.cnblogs.com/youzoulalala/p/11099561.html
Copyright © 2011-2022 走看看