数据结构与算法(十一)二叉搜索树

简介: 数据结构与算法(十一)二叉搜索树

特点

  • 左子树的每个结点的值都比根节点小,右子树的每个结点的值都比根节点大
  • 中序遍历为一个有序序列

二叉搜索树.png

时间复杂度

  • 查找 O(logn)
  • 插入 O(1)
  • 删除 O(logn) 寻找前继结点或者后继结点 替换删除的结点

前继结点:第一个比根节点小的数

后继结点:第一个比根节点大的数

代码实现

public class TreeNode<E> {
    private TreeNode<E> leftNode;
    private Integer key;
    private E data;
    private TreeNode<E> rightNode;
    private TreeNode<E> parentNode;
    public TreeNode(Integer key, E data) {
        this.key = key;
        this.data = data;
    }
    public TreeNode(TreeNode<E> leftNode, E data, TreeNode<E> rightNode) {
        this.leftNode = leftNode;
        this.data = data;
        this.rightNode = rightNode;
    }
    public TreeNode<E> getLeftNode() {
        return leftNode;
    }
    public void setLeftNode(TreeNode<E> leftNode) {
        this.leftNode = leftNode;
    }
    public E getData() {
        return data;
    }
    public void setData(E data) {
        this.data = data;
    }
    public TreeNode<E> getRightNode() {
        return rightNode;
    }
    public void setRightNode(TreeNode<E> rightNode) {
        this.rightNode = rightNode;
    }
    public Integer getKey() {
        return key;
    }
    public void setKey(Integer key) {
        this.key = key;
    }
    public void setParentNode(TreeNode<E> parentNode) {
        this.parentNode = parentNode;
    }
    public TreeNode<E> getParentNode() {
        return parentNode;
    }
}
public class BinarySelectTree<E> {
    private int size;
    private TreeNode<E> rootNode;
    public void insert(Integer key, E data) {
        if (rootNode == null) {
            rootNode = new TreeNode<>(key, data);
            size++;
            return;
        }
        insert(rootNode, key, data);
        size++;
    }
    private void insert(TreeNode<E> treeNode, Integer key, E data) {
        Integer rootKey = treeNode.getKey();
        TreeNode<E> leafNode = new TreeNode<>(key, data);
        if (rootKey >= key) {
            if (treeNode.getLeftNode() != null) {
                insert(treeNode.getLeftNode(), key, data);
            } else {
                treeNode.setLeftNode(leafNode);
                leafNode.setParentNode(treeNode);
            }
        } else {
            if (treeNode.getRightNode() != null) {
                insert(treeNode.getRightNode(), key, data);
            } else {
                treeNode.setRightNode(leafNode);
                leafNode.setParentNode(treeNode);
            }
        }
    }
    public E find(Integer key) {
        if (rootNode != null) {
            TreeNode<E> eTreeNode = find(rootNode, key);
            if (eTreeNode != null)
                return eTreeNode.getData();
        }
        return null;
    }
    private TreeNode<E> find(TreeNode<E> treeNode, Integer key) {
        Integer rootKey = treeNode.getKey();
        if (rootKey > key) {
            if (treeNode.getLeftNode() != null) {
                return find(treeNode.getLeftNode(), key);
            }
        } else if (rootKey < key) {
            if (treeNode.getRightNode() != null) {
                return find(treeNode.getRightNode(), key);
            }
        } else
            return treeNode;
        return null;
    }
    public int size() {
        return size;
    }
    public void print(TreeNode<E> treeNode) {
        System.out.print(treeNode.getData());
    }
    public void pre() {
        if (rootNode != null)
            pre(rootNode);
    }
    //前序遍历 根 左 右
    public void pre(TreeNode<E> treeNode) {
        print(treeNode);
        if (treeNode.getLeftNode() != null)
            pre(treeNode.getLeftNode());
        if (treeNode.getRightNode() != null)
            pre(treeNode.getRightNode());
    }
    public void mid() {
        if (rootNode != null)
            mid(rootNode);
    }
    //中序遍历 左 根 右
    private void mid(TreeNode<E> treeNode) {
        if (treeNode.getLeftNode() != null) {
            mid(treeNode.getLeftNode());
        }
        print(treeNode);
        if (treeNode.getRightNode() != null)
            mid(treeNode.getRightNode());
    }
    public void post() {
        if (rootNode != null)
            post(rootNode);
    }
    //后序遍历 左 右 根
    public void post(TreeNode<E> treeNode) {
        if (treeNode.getLeftNode() != null) {
            post(treeNode.getLeftNode());
        }
        if (treeNode.getRightNode() != null) {
            post(treeNode.getRightNode());
        }
        print(treeNode);
    }
    //层序遍历
    public void level(TreeNode<E> treeNode) {
        MyQueue<TreeNode<E>> queue = new MyQueue<>(20);
        levelRecursion(queue, treeNode);
    }
    private void levelRecursion(MyQueue<TreeNode<E>> queue, TreeNode<E> treeNode) {
        print(treeNode);
        if (treeNode.getLeftNode() != null) {
            queue.push(treeNode.getLeftNode());
        }
        if (treeNode.getRightNode() != null) {
            queue.push(treeNode.getRightNode());
        }
        while (!queue.isEmpty()) {
            levelRecursion(queue, queue.pop());
        }
    }
    public void remove(Integer key) {
        //1.找到该key
        //2.找到该key的后继结点
        //3.替换
        TreeNode<E> node = find(rootNode, key);
        if (node == null) return;
        TreeNode<E> postNode ;
        if (node.getLeftNode() != null && node.getRightNode() != null) {
            //此时需寻找后继结点 右子树的最小结点
            postNode = findPostNode(node.getRightNode());
            TreeNode<E> postParentNode = postNode.getParentNode();
            postParentNode.setLeftNode(postNode.getRightNode());
            postNode.setLeftNode(node.getLeftNode());
            postNode.setRightNode(node.getRightNode());
        }else {
            //至少有一个为空
            postNode = node.getLeftNode() != null ? node.getLeftNode() : node.getRightNode();
        }
        //判断删除的是左结点还是右结点
        TreeNode<E> parentNode = node.getParentNode();
        if(parentNode==null){
            //删除的是根结点
            rootNode = postNode;
            rootNode.setParentNode(null);
            return;
        }
        TreeNode<E> leftNode = parentNode.getLeftNode();
        if (leftNode != null && leftNode == node) {
            parentNode.setLeftNode(postNode);
        } else {
            parentNode.setRightNode(postNode);
        }
        postNode.setParentNode(parentNode);
    }
    public TreeNode<E> findPostNode(TreeNode<E> node) {
        if (node.getLeftNode() != null) {
            findPostNode(node.getLeftNode());
        }
        return node;
    }
}
目录
相关文章
|
2月前
|
存储 Java Serverless
【数据结构】哈希表&二叉搜索树详解
本文详细介绍了二叉搜索树和哈希表这两种数据结构。二叉搜索树是一种特殊二叉树,具有左子树节点值小于根节点、右子树节点值大于根节点的特点,并且不允许键值重复。文章给出了插入、删除和搜索等方法的具体实现。哈希表则通过哈希函数将键名映射为数组下标,实现快速查找,其插入、删除和查找操作时间复杂度理想情况下为O(1)。文中还讨论了哈希函数的设计原则、哈希冲突的解决方法及哈希表的实现细节。
47 8
【数据结构】哈希表&二叉搜索树详解
|
1月前
【高阶数据结构】深度探索二叉树进阶:二叉搜索树概念及其高效实现(三)
【高阶数据结构】深度探索二叉树进阶:二叉搜索树概念及其高效实现
|
1月前
|
存储
【高阶数据结构】深度探索二叉树进阶:二叉搜索树概念及其高效实现(二)
【高阶数据结构】深度探索二叉树进阶:二叉搜索树概念及其高效实现
|
1月前
【高阶数据结构】深度探索二叉树进阶:二叉搜索树概念及其高效实现(一)
【高阶数据结构】深度探索二叉树进阶:二叉搜索树概念及其高效实现
|
1月前
【数据结构】二叉搜索树的功能实现详解
【数据结构】二叉搜索树的功能实现详解
24 0
|
2月前
|
存储 算法 C#
C#二叉搜索树算法
C#二叉搜索树算法
|
5月前
数据结构学习记录——判断是否为同一颗二叉搜索树(题意理解、求解思路、程序搭建框架、具体函数的实现)
数据结构学习记录——判断是否为同一颗二叉搜索树(题意理解、求解思路、程序搭建框架、具体函数的实现)
47 2
|
5月前
|
机器学习/深度学习
数据结构学习记录——堆的小习题(对由同样的n个整数构成的二叉搜索树(查找树)和最小堆,下面哪个说法是不正确的)
数据结构学习记录——堆的小习题(对由同样的n个整数构成的二叉搜索树(查找树)和最小堆,下面哪个说法是不正确的)
36 1
|
4月前
|
存储
【数据结构】AVL树——平衡二叉搜索树
【数据结构】AVL树——平衡二叉搜索树
|
4月前
|
存储 Linux 数据库
【数据结构】二叉搜索树——高阶数据结构的敲门砖
【数据结构】二叉搜索树——高阶数据结构的敲门砖

热门文章

最新文章