二分查找树

//二叉查找树的定义,查询,插入,删除
public class BSTree<T extends Comparable<T>>{

private BSTNode<T> mRoot;//定义根节点
    //定义节点
    private class BSTNode<T extends Comparable<T>>{
        T key;
        BSTNode<T> left; //左节点
        BSTNode<T> right; //右节点
        BSTNode<T> parent; //父母节点
        
        public BSTNode(T key, BSTNode<T> left, BSTNode<T> right, BSTNode<T> parent){
            this.key = key;
            this.left = left;
            this.right = right;
            this.parent = parent;
        }
    }

//递归来遍历二叉查找树
    public BSTNode<T> recursionBSTSearch(BSTNode<T> x, T key){
        if(x == null) return x;
        
        int compare = key.compareTo(x.key);
        if(compare < 0)
            return recursionBSTSearch(x.left, key);
        else if(compare > 0)
            return recursionBSTSearch(x.right, key);
        else
            return x;
    }
    
    //迭代来遍历二叉查找树
    public BSTNode<T> iteratorBSTSearch(BSTNode<T> x, T key){
        while(x != null){
            int compare = key.compareTo(x.key);
            if(compare < 0)
                x = x.left;
            else if(compare > 0)
                x = x.right;
            else
                return x;
        }
        return x;
    }

//查找二叉树的最大值
    public BSTNode<T> maximun(BSTNode<T> x){
        if(x == null) return null;
        while(x.right != null)
            x = x.right;
        return x;
    }
    
    //查找二叉树的最小值
    public BSTNode<T> minimun(BSTNode<T> x){
        if(x == null) return null;
        while(x.left != null)
            x = x.left;
        return x;
    }

//查找二叉树中的某节点的前驱节点
    public BSTNode<T> predecessor(BSTNode<T> x){
        if(x == null) return null;
        /*
         * 找结点(x)的前驱结点。即,查找"二叉树中数据值小于该结点"的"最大结点"。
         */
        // 如果x存在左孩子,则"x的前驱结点"为 "以其左孩子为根的子树的最大结点"。
        while(x.left != null)
            return maximun(x.left);
        // 如果x没有左孩子。则x有以下两种可能:
        // (01) x是"一个右孩子",则"x的前驱结点"为 "它的父结点"。
        // (01) x是"一个左孩子",则查找"x的最低的父结点,并且该父结点要具有右孩子",找到的这个"最低的父结点"就是"x的前驱结点"。
        BSTNode<T> parent = x.parent;
        while(parent != null && x == parent.left){
            x =  parent;
            parent = parent.parent;
        }
        return parent;
    }

//查找二叉树中的某节点的后继节点
    public BSTNode<T> successor(BSTNode<T> x){
        /*
         * 找结点(x)的后继结点。即,查找"二叉树中数据值大于该结点"的"最小结点"。
         */
        if(x == null) return null;
        // 如果x存在右孩子,则"x的后继结点"为 "以其右孩子为根的子树的最小结点"。
        while(x.right != null)
            return minimun(x.right);
        // 如果x没有右孩子。则x有以下两种可能:
        // (01) x是"一个左孩子",则"x的后继结点"为 "它的父结点"。
        // (02) x是"一个右孩子",则查找"x的最低的父结点,并且该父结点要具有左孩子",找到的这个"最低的父结点"就是"x的后继结点"。
        BSTNode<T> parent = x.parent;
        while(parent != null && x == parent.right){
            x = parent;
            parent = parent.parent;
        }
        return parent;
    }

//插入节点
    public void insertBSTNode(BSTree<T> tree, BSTNode<T> x){
        int compare;
        BSTNode<T> y = null;
        BSTNode<T> node = tree.mRoot;
        while(node != null){
            y = node;
            compare = x.key.compareTo(node.key);
            if(compare > 0)
                node = node.right;
            else
                node = node.left;
        }
        x.parent = y;
        if(y == null)
            tree.mRoot = x;
        else{
            compare = x.key.compareTo(y.key);
            if(compare > 0)
                y.right =  x;
            else
                y.left = x;
        }
    }

//删除节点
    public void removeBSTNode(BSTree<T> bst, BSTNode<T> z){
        BSTNode<T> x = null;
        BSTNode<T> y = null;
        if(z.left == null || z.right ==  null)
            y =  z;
        else
            y = successor(z);
        
        if(y.left != null)
            x = y.left;
        else
            x = y.right;
        
        if(x != null)
            x.parent = y.parent;
        
        if(y.parent == null)
            bst.mRoot = x;
        else if(y == y.parent.left)
            y.parent.left = x;
        else
            y.parent.right = x;
        
        if(y != z)
            z.key = y.key;
    }
    
    /*
     * 打印"二叉查找树"
     *
     * key        -- 节点的键值
     * direction  --  0,表示该节点是根节点;
     *               -1,表示该节点是它的父结点的左孩子;
     *                1,表示该节点是它的父结点的右孩子。
     */
    public void print(BSTNode<T> tree, T key, int direction){
        if(tree == null) return ;
        if(direction == 0)
            System.out.println(key +" is root‘value");
        else{
            String s = direction== 1 ? "right" : "left";
            System.out.println(key + " is " + s);
        }
        print(tree.left, tree.key,-1);
        print(tree.right,tree.key,1);
    }

//销毁树
    public void destroy(BSTNode<T> tree){
        if(tree == null) return ;
        if(tree.left != null)
            destroy(tree.left);
        if(tree.right != null)
            destroy(tree.right);
        tree = null;
    }
}

时间: 2024-10-25 07:57:46

二分查找树的相关文章

数据结构之二分查找树总结

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 二分查找树BST(也叫二叉查找树.二叉排序树)的提出是为了提供查找效率,之所以称为二分查找树,因为该二叉树对应着二分查找算法,查找平均的时间复杂度为o(logn),所以该数据结构的提出是为了提高查找效率. 定义 二分查找树或者是一棵空树,或者具有下列性质: 1.若它的左子树不为空,则左子树上所有结点的值均小于根结点的值: 2.若它的右子树不为空,则右子树上所有结点的值均大于根结点的值: 3.它的左右子树均为二分查找树. 操作 二分查找树的操作主

排序列表转换为二分查找树

题目 给出一个所有元素以升序排序的单链表,将它转换成一棵高度平衡的二分查找树 解题 找到中间点,建立树的根结点 左右半边递归 注意: 右半边链表可以根据找到的中间节点进行递归 左半边要找到结束位置,这里我新建了一个链表 /** * Definition for ListNode. * public class ListNode { * int val; * ListNode next; * ListNode(int val) { * this.val = val; * this.next = n

lintcode——排序列表转换为二分查找树(链表,二叉排序树)

中等 排序列表转换为二分查找树查看运行结果 27% 通过 给出一个所有元素以升序排序的单链表,将它转换成一棵高度平衡的二分查找树 您在真实的面试中是否遇到过这个题? Yes 样例 标签 Expand 相关题目 Expand 思路: 这道题将排好序的链表转化为二叉排序树,即左子树<根节点<右子树 采用递归的方法,在链表上选取中间点作为根节点, 每次传入的参数为,需要创建的根节点的指针(这里由于要改变指针的值,所以要传入指针的指针),链表开始指针,结尾指针,链表结点个数( 这里传入了个数之后,就不

LintCode-排序列表转换为二分查找树

给出一个所有元素以升序排序的单链表,将它转换成一棵高度平衡的二分查找树 您在真实的面试中是否遇到过这个题? Yes 样例 标签 Expand 相关题目 Expand 分析:就是一个简单的递归,只是需要有些链表的操作而已 代码: /** * Definition of ListNode * class ListNode { * public: * int val; * ListNode *next; * ListNode(int val) { * this->val = val; * this->

SPOJ TEMPLEQ - Temple Queues(二分查找+树状数组)

题意: 有N个队伍(1 <= N <= 100,000),每个队伍开始有ai个人[0 <= ai<= 100,000,000],有Q个操作[0<=Q<= 500,000] 操作分为三种,1 A:表示在第A个队列加一个人. 2 X:表示求长度大于等于X队列数量.3 Y:表示所有长度大于等于Y的队列减去一个人. 题解: 把各个队列按长度排序 用差分数列来维护这个数组,这样求每个队列的长度就是求前缀和.每次求长度的复杂度是lgn,因为队列是按长度排序的,所以可以通过二分查找到

js二分查找树实现

function BinaryTree() { var Node = function(key) { this.key = key; this.left = null; this.right = null; } var root = null; var insertNode = function(node, newNode) { if (newNode.key < node.key){ if(node.left === null) { node.left = newNode; } else {

平衡查找树

一.2-3查找树 二叉查找树可以使用于大多数应用场景,但是最坏情况下性能太差. 本节将介绍一种二分查找树,它的运行时间可以保证在对数级别内. 1.定义 这里引进3-节点的概念,3-节点含有两个键和三个链接. 2-节点是标准二叉查找树中的节点,含有一个键和两个链接. Definition. A 2-3 search tree is a tree that either is empty or: A 2-node, with one key (and associated value) and tw

K-th Number 线段树(归并树)+二分查找

K-th Number 题意:给定一个包含n个不同数的数列a1, a2, ..., an 和m个三元组表示的查询.对于每个查询(i, j, k), 输出ai, ai+1, ... ,aj的升序排列中第k个数 . 题解:用线段树,每个节点维护一个区间并且保证内部升序,对于每次查询x,返回该区间小于x的数的个数.就这样不断二分,直到找到x为止. 线段树(归并树)+二分查找 1 #include <iostream> 2 #include <cstdio> 3 #include <

【bzoj4012】[HNOI2015]开店 动态树分治+二分查找

题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的想法当然非常好啦,但是她们也发现她们面临着一个问题,那就是店开在哪里,面向什么样的人群.很神奇的是,幻想乡的地图是一个树形结构,幻想乡一共有 n个地方,编号为 1 到 n,被 n-1 条带权的边连接起来.每个地方都住着一个妖怪,其中第 i 个地方的妖怪年龄是 x_i.妖怪都是些比较喜欢安静的家伙,所以它们并不希望和很多妖怪相邻.所以这个树所有顶点的