zoukankan      html  css  js  c++  java
  • 常见的查找算法(五):树表查找之一 ---- 二叉查找树

    二叉查找树英语:Binary Search Tree),也称为二叉搜索树有序二叉树ordered binary tree)或排序二叉树sorted binary tree),是指一棵空树或者具有下列性质的二叉树

    1. 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
    2. 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
    3. 任意节点的左、右子树也分别为二叉查找树;
    4. 没有键值相等的节点。

    二叉查找树的节点

     1     //二叉树节点
     2     static class BSTNode<T> {
     3         T data;
     4         BSTNode<T> parent;
     5         BSTNode<T> left;
     6         BSTNode<T> right;
     7 
     8         public BSTNode() {
     9             this.data = null;
    10             this.left = left;
    11             this.right= right;
    12         }
    13 
    14         public BSTNode(T data) {
    15             this(data,null, null);
    16         }
    17 
    18         public BSTNode(T data, BSTNode<T> left, BSTNode<T> right) {
    19             this.data = data;
    20             this.left = left;
    21             this.right = right;
    22         }
    23     }

    查找操作

     1     /******************************* 查找 start *******************************/
     2 
     3     /**
     4      * 从根节点查找
     5      *
     6      * @param data 要查找的元素
     7      * @return
     8      */
     9     public boolean searchBST(T data) {
    10         return searchBST(data, root);
    11     }
    12 
    13     /**
    14      * 递归查找指定元素是否在树中
    15      *
    16      * @param node 树中节点
    17      * @param data 要查找的元素
    18      * @return
    19      */
    20     public boolean searchBST(T data, BSTNode<T> node) {
    21         if (node == null)
    22             return false;
    23 
    24         count++;
    25         int result = data.compareTo(node.data);
    26 
    27         if (result > 0) {
    28             return searchBST(data, node.right);//往右子树查询
    29         } else if (result < 0) {
    30             return searchBST(data, node.left);//往左子树查询
    31         } else {
    32             return true;
    33         }
    34     }
    35 
    36     /**
    37      * 寻找二叉树中最大的元素
    38      *
    39      * @return
    40      */
    41     public T findMax() {
    42         if (isEmpty()) {
    43             System.out.println("二叉树为空");
    44             return null;
    45         } else {
    46             return findMax(root).data;
    47         }
    48     }
    49 
    50     /**
    51      * 寻找二叉树中最大的元素
    52      *
    53      * @param node 当前的结点
    54      * @return
    55      */
    56     public BSTNode<T> findMax(BSTNode<T> node) {
    57         if (node == null) {
    58             return null;
    59         } else if (node.right == null) {
    60             return node;
    61         } else {
    62             //迭代
    63             while (node.right != null) {
    64                 node = node.right;
    65             }
    66             return node;
    67         }
    68     }
    69 
    70     /**
    71      * 寻找二叉树中最小的元素
    72      *
    73      * @return
    74      */
    75     public T findMin() {
    76         if (isEmpty()) {
    77             System.out.println("二叉树为空");
    78             return null;
    79         } else {
    80             return findMin(root).data;
    81         }
    82     }
    83 
    84     /**
    85      * 寻找二叉树中最小的元素
    86      *
    87      * @param node 当前节点
    88      * @return
    89      */
    90     public BSTNode<T> findMin(BSTNode<T> node) {
    91         if (node == null)
    92             return null;
    93         else if (node.left == null)
    94             return node;
    95         return findMin(node.left);
    96     }
    97 
    98     /******************************* 查找 end *******************************/

    时间复杂度分析:根据二叉查找树的性质,给定一个元素,去查找树中的元素,是从根节点那开始一层层比较节点的值,从而选定在树中查找的方向。当查找到该元素时,已经比较了n层,也就是元素在树中的层数(根节点为第一层),每层比较一个节点,然而二叉树的高度与它的节点数量有关,为log₂(n+1),所以二叉查找树的朝招时间复杂度为O(log₂n)。

    插入操作

    1. 此树是空树,则直接将插入的结点作为根结点插入。
    2. 插入的值等于插入的值的根结点的数据的值,则直接返回,否则。
    3. 插入的值小于此树根结点的数据的值,则将要插入的结点的位置改变为此树左子树,否则4。
    4. 插入的值的结点的位置改变为此树右子树
     1     /******************************* 插入 start *******************************/
     2     //插入元素
     3     public void insert(T t) {
     4         root = insert(t, root);
     5     }
     6 
     7     /**
     8      * 构建一个二叉查找树
     9      *
    10      * @param t    插入元素
    11      * @param node 插入结点
    12      * @return
    13      */
    14     public BSTNode<T> insert(T t, BSTNode<T> node) {
    15         if (node == null)
    16             return new BSTNode<T>(t, null, null);
    17         int result = t.compareTo(node.data);
    18         if (result < 0) {
    19             node.left = insert(t, node);
    20         } else if (result > 0) {
    21             node.right = insert(t, node);
    22         } else {
    23             System.out.println("插入失败");
    24         }
    25         return node;
    26     }
    27     /******************************* 插入 end *******************************/

    删除操作

    对于二叉查找树的删除操作(这里根据值删除,而非结点)分三种情况:

    1. 如果结点为叶子结点(没有左、右子树),此时删除该结点不会破坏树的结构,直接删除即可,并修改其父结点指向它的引用为null
    2. 如果其结点只包含左子树,或者右子树的话,此时直接删除该结点,并将其左子树或者右子树设置为其父结点的左子树或者右子树即可,此操作不会破坏树结构
    3. 当结点的左、右子树都不空的时候,一般的删除策略是用其右子树的最小数据(容易找到)代替 要删除的结点数据递归删除该结点(此时为null)
     1     /******************************* 删除 start *******************************/
     2     /**
     3      * 删除元素
     4      * @param t
     5      */
     6     public void remove(T t) {
     7         root = remove(t, root);
     8     }
     9 
    10     /**
    11      * 删除某个位置的结点
    12      * @param t
    13      * @param node
    14      * @return
    15      */
    16     public BSTNode<T> remove(T t, BSTNode<T> node) {
    17         if (node == null) {
    18             System.out.println("删除失败");
    19             return node;
    20         }
    21         int result = t.compareTo(node.data);
    22         if (result > 0) {
    23             node.right = remove(t, node.right);
    24         } else if (result < 0) {
    25             node.left = remove(t, node.left);
    26         } else if (node.left != null && node.right != null) {
    27             node.data = findMin(node.right).data;
    28             node.right = remove(node.data, node.right);
    29         } else {
    30             node = (node.left != null) ? node.left : node.right;
    31         }
    32         return node;
    33     }
    34     /******************************* 删除 end *******************************/

    遍历二叉查找树(先序遍历):

    1     public void preOrder(BSTNode node) {
    2         if (node != null) {
    3             System.out.print(node.data + " ");
    4             preOrder(node.left);
    5             preOrder(node.right);
    6         }
    7     }

    测试代码:

     1     public static void main(String[] args) {
     2         BSTNode<Integer> node3 = new BSTNode<>(3);
     3         BSTNode<Integer> node1 = new BSTNode<>(1);
     4         BSTNode<Integer> node4 = new BSTNode<>(4, node3, null);
     5         BSTNode<Integer> node2 = new BSTNode<>(2, node1, node4);
     6         BSTNode<Integer> node8 = new BSTNode<>(8);
     7         BSTNode<Integer> root = new BSTNode<>(6, node2, node8);
     8 
     9         BSTree bsTree = new BSTree<>();
    10         bsTree.root = root;
    11         bsTree.preOrder(bsTree.root);
    12         //bsTree.remove(4);
    13         //System.out.println();
    14         //bsTree.preOrder(bsTree.root);
    15         bsTree.searchBST(3);
    16         System.out.println("查找次数:" + count);
    17     }
  • 相关阅读:
    阿里DatatX mysql8往 Elasticsearch 7 插入时间数据 时区引发的问题
    通俗易懂 k8s (3):kubernetes 服务的注册与发现
    ReplicaSet 和 ReplicationController 的区别
    使用Go module导入本地包
    k8s之statefulset控制器
    终于成功部署 Kubernetes HPA 基于 QPS 进行自动伸缩
    Atitit drmmr outline org stat vb u33.docx Atitit drmmr outline org stat v0 taf.docx Atitit drmmr out
    Atitit all diary index va u33 #alldiary.docx Atitit alldiaryindex v1 t717 目录 1. Fix 1 2. Diary deta
    Atitit path query 路径查询语言 数据检索语言 目录 1.1. List map >> spel 1 1.2. Html数据 》》Css选择符 1 1.3. Json 》map》
    Atitit prgrmlan topic--express lan QL query lan表达式语言 目录 1. 通用表达语言(CEL) 1 1.1. 8.2 功能概述 1 1.2. Ongl
  • 原文地址:https://www.cnblogs.com/magic-sea/p/11386085.html
Copyright © 2011-2022 走看看