BST(二叉搜索树) Java 实现解析

1.二叉搜索树的定义:一颗树的所有左子树都比根小,所有右子树都比根大,成为二叉搜索树。

2.该BST树实现了9个重要方法,分别是关键字查找,插入,删除,删除节点后续节点查找,前序遍历,中序遍历,后序遍历,获取最大节点,获取最小节点。

3.以下是Java的代码实现:

//定义Node类,拥有元素值,节点名称,左孩子节点,右孩子节点,4个成员变量。class Node {    int element;    String name;    Node leftChild;    Node rightChild;

    public Node(int element, String name) {        this.element = element;        this.name = name;    }}
public class BinSearchTreeDemo {    public Node root;    //查找节点   //方法思路:从根开始找起,如果比根小,就查找左孩子,如果比根大,就查找右孩子,如果相等,则返回该节点。    public Node find(int key){        if(root==null){            System.out.println("The tree is empty...");            return null;        }        Node current=root;        while (current.element!=key){            if(current.element>key){                current=current.leftChild;            }else{                current=current.rightChild;            }            if(current==null){                return null;            }        }        return current;    }    //插入节点    //方法思路:从根节点开始遍历,如果比根小,则继续查找左孩子,如果比根大,则继续查找右孩子,一直查到某节点左孩子或者右孩子为null,则在该节点后继插入节点。    //注意:被插入的元素在树中一定是叶子节点    public boolean insert(Node node){        if(root==null){            root=node;            return true;        }        Node current=root;        if(find(node.element)!=null){            System.out.println("不允许出现重复节点...");            return false;        }        while (current!=null){            if(current.element>node.element){                if(current.leftChild==null){                    current.leftChild=node;                    return true;                }                current=current.leftChild;            }else{                if(current.rightChild==null){                    current.rightChild=node;                    return true;                }                current=current.rightChild;            }        }        return false;    }    //前序遍历(根左右的)    public void preOrder_iterator(Node node){        System.out.println(node.element+" ");        if(node.leftChild!=null){            preOrder_iterator(node.leftChild);        }        if(node.rightChild!=null){            preOrder_iterator(node.rightChild);        }    }    //中序遍历(左根右)    public void inOrder_iterator(Node node){        if(node.leftChild!=null){            inOrder_iterator(node.leftChild);        }        System.out.println(node.element+" ");        if(node.rightChild!=null){            inOrder_iterator(node.rightChild);        }    }    //后序遍历(左右根)    public void postOrder_iterator(Node node){        if(node.leftChild!=null){            postOrder_iterator(node.leftChild);        }        if(node.rightChild!=null){            postOrder_iterator(node.rightChild);        }        System.out.println(node.element+" ");    }    //获取树中最小节点    public Node getMinNode(Node node){        if(find(node.element)==null){            System.out.println("This node does not exist...");            return null;        }        Node current=node.leftChild;        while (current!=null){            current=current.leftChild;        }        return current;    }    //获取树中最大节点    public Node getMaxNode(Node node){        if(find(node.element)==null){            System.out.println("This node does not exist...");            return null;        }        Node current=node.rightChild;        while (current!=null){            current=current.rightChild;        }        return current;    }    //删除节点    //方法思路:    //1.首先找到删除节点和该节点对应的父亲节点,分别用target变量和targetParent变量保存,并且利用一个布尔变量保存删除的节点是父亲的左孩子还是右孩子,左孩子则为true,右孩子则为    //  false    //2.接下来进行节点删除,删除需要分为三种情况,第一种是删除的是叶子节点,该情况是如果删除的是父亲的左孩子,则直接将父亲的leftChild设为target的左孩子,,如果删除的是右孩子,则    //  直接将父亲的rightChild设为target的左孩子,即为null;第二种情况是删除的节点带有一个孩子节点,该节点可以是左孩子,也可以是右孩子,需要分开处理,如果删除的节点本身是左子树    //  ,并且带有左孩子,则将targetParent的左孩子指向target的左孩子,如果带有右孩子,则将targetParent的左孩子指向target的右孩子;如果删除的节点本身是右子树,并且带有左孩子     //  ,则将targetParent的右孩子指向target的左孩子,否则指向右孩子。第三种情况是删除的是带有两个孩子的节点,这种情况稍微复杂,我们单独说明    //3.带有两个孩子的节点删除情况分析:该方法伴有一个getFollwingNode的方法,目的是为了捕获删除节点的后续节点,思路如下,    //  ①.先找到删除节点的右子树节点,调用getFollowingNode方法可以找到删除节点的右子树中的最左边的节点,也就是最小节点,并返回该最小节点,此时调整该右子树的结构,将返回节点的     //     父节点指向返回节点的右子树(如果存在的话,左子树一定是不存在的);    //  ②.此时将删除节点的父节点指向该返回的节点(注意左右情况),然后将返回节点的左指针指向删除节点的左孩子,右指针指向删除节点的右孩子,结束。    public boolean delete(int key){        if(root==null){            System.out.println("The tree is empty...");            return false;        }        Node targetParent=root;        Node target=root;        boolean isLeftChild=false;        //找到对应的删除节点target和其父节点targetParent        while (target.element!=key){            if(key<target.element){                targetParent=target;                target=target.leftChild;                isLeftChild=true;            }else{                targetParent=target;                target=target.rightChild;                isLeftChild=false;            }            if(target==null){                System.out.println("The target node does not exist...");                return false;            }        }        //如果删除的节点是叶子节点        if(target.leftChild==null&&target.rightChild==null){            if(root.element==target.element){                root=null;                return true;            }            if(isLeftChild){                targetParent.leftChild=target.leftChild;            }else{                targetParent.rightChild=target.leftChild;            }        }        //如果删除的节点只有一个子节点        //如果该节点是左子树        else if(target.leftChild!=null&&target.rightChild==null){            if(root.element==target.element){                root=target.leftChild;                return true;            }            if(isLeftChild){                targetParent.leftChild=target.leftChild;            }else{                targetParent.leftChild=target.rightChild;            }        }        //如果该节点是右子树        else if(target.leftChild==null&&target.rightChild!=null){            if(root.element==target.element){                root=target.rightChild;                return true;            }            if(isLeftChild){                targetParent.rightChild=target.leftChild;            }else{                targetParent.rightChild=target.rightChild;            }        }        else{            Node followingNode = this.getFollowingNode(target);            if(target.element == root.element)                root = followingNode;            else if(isLeftChild)                targetParent.leftChild = followingNode;            else                targetParent.rightChild = followingNode;            followingNode.leftChild = target.leftChild;            followingNode.rightChild = target.rightChild;        }

        return true;    }    //获取删除节点后续节点    public Node getFollowingNode(Node node2Del){        Node nodeParent = node2Del;        //只有被删除节点有左右子节点时,才会调用该方法        //这里直接调用rightChild是没有问题的        Node node = node2Del.rightChild;        while(node.leftChild != null){            nodeParent = node;            node = node.leftChild;        }        if(node.element != node2Del.rightChild.element)            nodeParent.leftChild = node.rightChild;        else            nodeParent.rightChild = node.rightChild;        return node;    }}
时间: 2024-10-09 02:05:01

BST(二叉搜索树) Java 实现解析的相关文章

二叉搜索树(Java实现)

二叉搜索树基本操作 求树中的结点个数 判断节点是否为空 向树中插入新结点key-value 树中是否存在key 返回树中key对应的value值 先序遍历 中序遍历 后续遍历 层序遍历 求树中key最小的结点 求树中key最大的结点 删除树中key最小的结点 删除树中key最大的结点 树中删除一个结点 代码: /** * @param <Key> 键的泛型 * @param <Value> 值的泛型 */ public class BinarySearchTree<Key e

BST二叉搜索树

1.二叉搜索树 (1).逼近折半查找的查找算法: (2).一般不允许出现重复数字,不然没法存储: (3).满足:左孩子数据 < 根结点数据 < 右孩子数据:根(父)结点比左孩子的大,比右孩子的小: (4)左子树和右子树也是二叉搜索树: 2.为什么叫二叉搜索树? 如果对一颗二叉搜索树进行中序遍历,可以按从小到大的顺序输出,此时又叫做二叉排序树. 如图: 3.搜索二叉树上的操作 全部用C++实现的. (1).之前学习二叉树,并没有说什么插入,删除操作,那是因为,没有规律而言,怎么进行操作呢?搜索二

[LeetCode] Serialize and Deserialize BST 二叉搜索树的序列化和去序列化

Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another comput

数据结构中常见的树(BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树)

树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: BST树的搜索,从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中: 如果BST树的所有非叶子结点的左右子树的结点数目均保持差不多(平衡),那么B树 的搜索性能逼近二分查找:但它比连续内存空间的二分查找的优点是,改变BST树结构 插入与删除结点)不需要移动大段的内存数据,甚至通常是常数开销: 如:

[LeetCode] 938. Range Sum of BST 二叉搜索树的区间和

Given the?`root`?node of a binary search tree, return the sum of values of all nodes with value between?`L`?and?`R`?(inclusive). The binary search tree is guaranteed to have unique values. Example 1: Input: root = [10,5,15,3,7,null,18], L = 7, R = 15

二叉搜索树JAVA实现

引入: 二叉搜索树是这样的一种二叉树: (1)每个元素都有一个关键值,并且没有任意两个元素有相同的关键值 (2)根节点的左子树中任意元素的关键值小于根节点的关键值. (3)根节点的右子树中任意元素的关键值大于根节点的关键值. (4)根节点的左右子树也是二叉搜索树. 我们这里就用程序来实现这样一颗二叉搜索树. 分析: 从定义看出,二叉搜索树是一种特殊的二叉树,它给每个元素加上了序的概念,但又不同于最大最小堆,它总是 左<根<右的.我们分别看常用的几个操作. 查找: 关键值查找很简单,就是从根元素

【转载】Morris遍历二叉树 &amp; BST(二叉搜索树) Traverse &amp; 空间O(1) 时间O(n)

因为做一道Leetcode的题目(前面博客有:link),需要用Space O(1)空间复杂度来中序遍历树, 看了Discuss,也上网搜了一下,发现空间O(1)可以用 Morris遍历的方法.方法介绍如下: http://www.cnblogs.com/AnnieKim/archive/2013/06/15/MorrisTraversal.html其中,中序遍历和前序遍历比较方便解决: 通常,实现二叉树的前序(preorder).中序(inorder).后序(postorder)遍历有两个常用

标准BST二叉搜索树写法

本人最近被各种数据结构的实验折磨的不要不要的,特别是代码部分,对数据结构有严格的要求,比如写个BST要分成两个类,一个节点类,要给树类,关键是所以操作都要用函数完成,也就是在树类中不能直接操作节点,需要使用节点类中的函数来实现各种操作. 简直太麻烦,但是花时间写了也是有好处的,认真写完绝对几年忘不了.同时用函数操作数据也更安全,将数据设为私有成员更符合规范.下面给出代码. 1 #include<iostream> 2 using namespace std; 3 4 class BinNode

POJ 2309 BST(二叉搜索树)

BST Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8657   Accepted: 5277 Description Consider an infinite full binary search tree (see the figure below), the numbers in the nodes are 1, 2, 3, .... In a subtree whose root node is X, we c

数据结构第三部分:树与树的表示、二叉树及其遍历、二叉搜索树、平衡二叉树、堆、哈夫曼树、集合及其运算

参考:浙大数据结构(陈越.何钦铭)课件 1.树与树的表示 什么是树? 客观世界中许多事物存在层次关系 人类社会家谱 社会组织结构 图书信息管理 分层次组织在管理上具有更高的效率! 数据管理的基本操作之一:查找(根据某个给定关键字K,从集合R 中找出关键字与K 相同的记录).一个自然的问题就是,如何实现有效率的查找? 静态查找:集合中记录是固定的,没有插入和删除操作,只有查找 动态查找:集合中记录是动态变化的,除查找,还可能发生插入和删除 静态查找——方法一:顺序查找(时间复杂度O(n)) int