首页 > 编程语言 >数据结构之二叉搜索树(java语言版)

数据结构之二叉搜索树(java语言版)

时间:2024-04-11 11:56:16浏览次数:18  
标签:Node node 数据结构 java parent int null 节点 语言版

之前介绍了树,主要实现了二叉树的代码。在二叉树的基础上有许多衍生的树,如二叉搜索树、哈夫曼树等,今天学习一下二叉搜索树。

二叉搜索树

二叉搜索树是二叉树的一种,是应用非常广泛的一种二叉树,英文简称为 BST

又被称为:二叉查找树、二叉排序树

特点

任意一个节点的值都大于其左子树所有节点的值

任意一个节点的值都小于其右子树所有节点的值

它的左右子树也是一棵二叉搜索树

◼ 二叉搜索树可以大大提高搜索数据的效率

◼ 二叉搜索树存储的元素必须具备可比较性

在这里插入图片描述

java语言实现

有了之前的二叉树的实现,此时实现二叉搜索树就比较简单。

节点类

1、节点类中的data要求必须具有可比较性,我在此使用int型,如果使用的数据是其他对象,需要经过处理使其具有可比较性。

2、二叉搜索树需要有三条引用链,左节点、右节点、父节点。父节点在删除数据时需要使用。

public class Node {
    int data;
    Node left;
    Node right;
    Node parent;

    public Node(int data, Node left, Node right, Node parent) {
        this.data = data;
        this.left = left;
        this.right = right;
        this.parent = parent;
    }

    @Override
    public String toString() {
        return "Node [data=" + data + "]";
    }

}


方法

二叉搜索树的方法:

作为接口BinaryTree

public interface BinaryTree {

    void add(int e);

    void remove(int e);

    void replace(int e1, int e2);

    Node search(int e);

    boolean isEmpty();

    int compare(int e1, int e2);

    void display(Node root);

}

二叉搜索树实现

构造方法

public class BST implements BinaryTree {

    int size;
    Node root;

    public BST() {
        System.out.println("BST init....");
    }

    
    @Override
    public boolean isEmpty() {

        return size == 0;
    }


}

compare()方法

通过compare方法比较大小,决定节点的位置。

 /**
     *
     *     将两个节点传入,进行比较,
     *     如果e1>e2,return 1
     *     e1<e2,return -1
     *     相等 return 0
     */
@Override
public int compare(int e1, int e2) {
        if (e1 == e2) {
            return 0;
        }
        return e1 > e2 ? 1 : -1;
    }

    

add方法

add方法用于加入数据.

调用了compare()方法用于比较大小。

@Override
    public void add(int e) {
        if (root == null) {
            root = new Node(e, null, null, null);
            System.out.println("add root succcessful!!!");
            return;
        }

        Node head = root;
        Node parent = root;
        int cap = 0;
        while (head != null) {
            parent = head;

            cap = compare(head.data, e);

            if (cap > 0) {
                head = head.left;
            } else if (cap < 0) {
                head = head.right;
            } else {
                System.out.println("=====已有相关节点");
                return;
            }
        }

        Node newNode = new Node(e, null, null, parent);
        if (cap > 0) {
            parent.left = newNode;
        } else {
            parent.right = newNode;
        }
        System.out.println("add successfu!!!");

        size++;
    }

先序遍历

@Override
public void display(Node root) {
        if (root == null) {
            return;
        }

        System.out.print("  " + root);
        display(root.left);
        display(root.right);
    }

测试

用一个数组作为数据测试一下:

public static void main(String[] args) {
		int[] arr = new int[] { 8, 6, 10, 4, 7, 9, 13 };

        BST bst = new BST();
        for (int i : arr) {
            bst.add(i);
        }

        bst.display(bst.root);

    }

按测试数据的输入,得到的树应该是右边的树。

在这里插入图片描述

得到如下结果:

BST init....
add root succcessful!!!
add successfu!!!
add successfu!!!
add successfu!!!
add successfu!!!
add successfu!!!
add successfu!!!
  Node [data=8]  Node [data=4]  Node [data=6]  Node [data=7]  Node [data=9]  Node [data=10]  Node [data=13]

如果需要得到左边的树、那么需要以下顺序输入:

8,6,10,4,7,9,13

此时的树与节点输入顺序有关系,右边的树虽然是二叉搜索树,但已经不平衡了。不平衡的树有许多缺点,所以有了平衡二叉树。

search方法

通过search方法得到元素所在的节点。

 @Override
public Node search(int e) {
        if (isEmpty()) {
            System.out.println("null tree");
            return null;
        }

        Node head = root;
        Node parent = root;
        int cap = 0;
        while (head != null) {
            parent = head;

            cap = compare(head.data, e);

            if (cap > 0) {
                head = head.left;
            } else if (cap < 0) {
                head = head.right;
            } else {
                return head;
            }
        }

        return null;
    }

replace方法

replace这个方法在使用是注意约束条件,要控制替换的数据满足二叉搜索树的定义。

 @Override
public void replace(int e1, int e2) {
        Node node = search(e1);
        if (node == null) {
            System.out.println("not node could be replace");
            return;
        }

        // 代替的位置主要要满足约束条件
        int cap;
        if (node.parent != null) {
            cap = compare(node.parent.data, e2);
            if (cap >= 0) {
                System.out.println("not node could be replace");
                return;
            }
        }

        if (node.left != null) {
            cap = compare(node.left.data, e2);
            if (cap >= 0) {
                System.out.println("not node could be replace");
                return;
            }
        }

        if (node.right != null) {
            cap = compare(node.right.data, e2);
            if (cap <= 0) {
                System.out.println("not node could be replace");
                return;
            }
        }

        node.data = e2;

    }

remove方法

删除节点需要用到parent节点,节点被删除后,其子节点和父节点的相关引用都会改变。

并且根据删除的节点的位置,需要有一些细微的操作。

删除叶子节点
 @Override
    public void remove(int e) {
        Node node = search(e);
        if (node == null) {
            System.out.println("not node could be remove");
            return;
        }
        size--;

        Node parent = node.parent;// 得到父节点

        if (node.left == null && node.right == null) {// 叶子节点
            if (parent.right == node) {
                parent.right = null;
            } else {
                parent.left = null;
            }
            System.out.println("叶子节点删除。。。");
            return;
        }

        if (node.left != null && node.right != null) {// 度为2的节点
            if (parent == null) {// 为root节点时,默认选择前驱节点为new root
                Node newRoot = maxChildNode(node);
                System.out.println(" new root: " + newRoot);
                if (newRoot != null) {
                    node.data = newRoot.data;

                } else {
                    newRoot = minChildNode(node);
                    node.data = newRoot.data;
                }

                // 消灭newRoot
                if (newRoot.parent.right == newRoot) {
                    newRoot.parent.right = null;
                } else {
                    newRoot.parent.left = null;
                }
            }

            if (parent != null) {
						//.........
            }

            System.out.println("度为2的节点删除");
            return;
        } else {// 度为1

            if (parent == null) {// root节点
                if (node.right != null) {

                    node = node.right;
                    node.right.parent = null;

                } else {
                    node = node.left;
                    node.left.parent = null;
                }
            }
            
            //.................

            System.out.println("度为1的节点删除");
        }

    }

标签:Node,node,数据结构,java,parent,int,null,节点,语言版
From: https://www.cnblogs.com/cgl-dong/p/18128735

相关文章

  • 数据结构之链表(c语言版)
    链表是线性表,链表的特点就是可以动态增减元素。种类有单向链表、双向链表,循环链表。一、单链表单链表的储存思想使用指针表示节点之间的逻辑关系,它的储存单元可以连续也可以不连续,每个储存单元需要储存信息和储存与后继节点的地址信息,储存单元又称之为节点。单链表由头指针唯......
  • 数据结构之栈(c语言版)
    栈(stack):在逻辑上是一种线性存储结构,它有以下几个特点:1、栈中数据是按照"后进先出(LIFO,LastInFirstOut)"方式进出栈的。2、向栈中添加/删除数据时,只能从栈顶进行操作。栈通常包括的三种操作:push、peek、pop。push--向栈中添加元素。peek--返回栈顶元素。pop--返......
  • 数据结构之队列(c语言版)
    队列(Queue):在逻辑上是一种线性存储结构。它有以下几个特点:1、队列中数据是按照"先进先出(FIFO,First-In-First-Out)"方式进出队列的。2、队列只允许在"队首"进行删除操作,而在"队尾"进行插入操作。队列通常包括的两种操作:入队列和出队列。队列的种类也很多,单向队列,双向队列,循......
  • 数据结构之二叉树(c语言版)
    之前的都是线性结构,而树结构在计算机应用中的应用更加广泛。linux中的目录结构,某些数据库的底层存储等,都是采用树结构进行构架的。树的概念线性表是一对一的关系,而树是一对多的关系。树的结点:包含一个数据元素及若干指向子树的分支;孩子结点:结点的子树的根称为该结点的孩子;双......
  • 数据结构之图(c语言版)
    图是比树更复杂的结构,树是一对多的关系,图是多对多的关系。一、基本概念1、定义:图(graph)是由一些点(vertex)和这些点之间的连线(edge)所组成的;其中,点通常被成为"顶点(vertex)",而点与点之间的连线则被成为"边或弧"(edege)。通常记为,G=(V,E)。2、根据边是否有方向,将图可以划分......
  • 链表(java语言版)
    链表(Linkedlist)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。使用链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域......
  • 排序算法(c语言版)
    排序算法(c语言版)1、插入排序#include<stdio.h>//插入排序,升序voidinsertion_sort(intarr[],intlen){inti,j,key;for(i=1;i<len;i++){key=arr[i];//arr[i]为待插入的元素,保存在key中j=i-1;wh......
  • 深入浅出 妙用Javascript中apply、call、bind
    这篇文章实在是很难下笔,因为网上相关文章不胜枚举。巧合的是前些天看到阮老师的一篇文章的一句话:“对我来说,博客首先是一种知识管理工具,其次才是传播工具。我的技术文章,主要用来整理我还不懂的知识。我只写那些我还没有完全掌握的东西,那些我精通的东西,往往没有动力写。炫耀从来......
  • 数据结构与算法引言
    数据结构与算法引言数据结构和算法是计算机专业重要的基础课程。数据结构是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合。算法简单来说就是解决问题的步骤。有了一个个数据结构和算法,我们可以编写出高质量的代码,高性能的产品。数据结构数......
  • java代码将16进制字符串转换为图片,jdbc入库blob字段,解决ORA-01704,PLS-00172,ORA-06550,
    从Oracle导出SQL文件中的insert语句包含blob字段,语句HEXTORAW函数将16进制的字符串入库,由于字符串太长,insert失败下面的代码读取完整的insert语句,将HEXTORAW函数连同16进制的字符串替换为NULL,先将字段置空插入记录,然后使用PreparedStatement对图片文件读流更新入库importorg.......