【Java】二叉搜索树 实现树数据的数据库存储

二叉搜索树

1、 题目要求

① 实现一个二叉搜索树, 提供添加、删除、查找、遍历功能,实现Insert(),delete(),visit(),search()方法
② 利用接口实现通用Insert(),delete(),visit(),search()
③ 处理异常
④ 实现树数据的数据库存储(自选数据库)

2、 环境准备

语言:java version ’1.8.0_221’
平台:IntelliJ IDEA 2019.2.4 x64
数据库:MySQL
数据库可视化软件:Navicat

3、 题目解析

建立一个二叉搜索树,用以实现对树结点的增添,删除,查找,遍历等功能。
增添的前提查找,先查找到该放置的位置,然后把新结点加进去,再对已有结点进行重排列(父结点和左右子树的操作)
删除与增添类似,先找到删除的结点,然后删除,再对已有结点进行一系列操作。
遍历,分为前序,中序,后序遍历三种。
利用接口实现通用Insert(),delete(),visit(),search()。
把JAVA与数据库连接到一起,实现数据库的一系列操作。

4、 算法描述

① 二叉搜索树需满足以下四个条件:
若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
任意节点的左、右子树也分别为二叉搜索树;
没有键值相等的节点。
② 二叉搜索树性质
按中序遍历二叉搜索树,所得到的中序遍历序列是一个递增有序序列。
二叉搜索树就是具备上述四种性质的二叉树。
在这里插入图片描述
③ 增删改查操作
二叉搜索树的插入
在二叉搜索树中插入新结点,要保证插入后的二叉树仍符合二叉搜索树的定义。插入过程如下:
若二叉搜索树为空,则待插入结点S作为根结点插入到空树中;
当非空时,将待插结点关键字S->key和树根关键字t->key进行比较,若s->key = t->key,则无须插入,若s->key< t->key,则插入到根的左子树中,若s->key> t->key,则插入到根的右子树中。而子树中的插入过程和在树中的插入过程相同,如此进行下去,直到把结点
s作为一个新的树叶插入到二叉搜索树中,或者直到发现树已有相同关键字的结点为止。
插入完成。
二叉排序树的查找
假定二叉排序树的根结点指针为 root ,给定的关键字值为 K ,则查找算法可描述为:
置初值: q = root ;
如果 K = q -> key ,则查找成功,算法结束;
否则,如果 K < q -> key ,而且 q 的左子树非空,则将 q 的左子树根送 q ,转上步骤;否则,查找失败,结束算法;
否则,如果 K > q -> key ,而且 q 的右子树非空,则将 q 的右子树根送 q ,转第二步;否则,查找失败,算法结束。

二叉排序树的删除
假设被删结点是p,其双亲是f,不失一般性,设p是f的左孩子,下面分三种情况讨论:
⑴ 若结点p是叶子结点,则只需修改其双亲结点f的指针即可。
⑵ 若结点p只有左子树PL或者只有右子树PR,则只要使PL或PR 成为其双亲结点的左子树即可。
⑶ 若结点
p的左、右子树均非空,先找到p的中序后继(或前驱)节点s(注意s是p的右子树中的key最小的结点,它的左子树为空),然后步骤如下:
找到 *p 的节点的直接中序后继节点(即其右子树中key值最小的节点 ),并删除此直接中序后继节点。
将此后继节点的 key、value 值赋给待删除节点的 key,value值。

5、 源代码

① 节点类

package com.company;
public class Node {
    int key;
    int value;
    Node leftChild;
    Node rightChild;

    public Node(int key, int value) {
        this.key = key;
        this.value = value;
        this.leftChild = null;
        this.rightChild = null;
    }

    public Node(int key, int value, Node leftChild, Node rightChild) {
        super();
        this.key = key;
        this.value = value;
        this.leftChild = leftChild;
        this.rightChild = rightChild;
    }

    public Node() {}

    @Override
    public String toString() {
        return "Node [key=" + this.key + ", value=" + this.value + ", leftChild=" + this.leftChild + ", rightChild=" + this.rightChild + "]";
    }

    public int getKey() {
        return this.key;
    }

    public void setKey(int key) {
        this.key = key;
    }

    public int getValue() {
        return this.value;
    }
    public void setValue(int value) {
        this.value = value;
    }

    public Node getLeftChild() {
        return this.leftChild;
    }

    public void setLeftChild(Node leftChild) {
        this.leftChild = leftChild;
    }

    public Node getRightChild() {
        return this.rightChild;
    }

    public void setRightChild(Node rightChild) {
        this.rightChild = rightChild;
    }
}

② 二叉搜索树接口方法

package com.company;

public interface interfaceBinaryTree {
    Node visit(int key);// Find the specified node
    boolean update(int key, int value);
    void insert(int key, int value); // Insertion node
    boolean delete(int key); //Delete the specified node
    Node getDirectPostNode(Node delNode); // Get the direct successor node of the node to be deleted
    void preOrder(Node rootNode); 
    void inOrder(Node rootNode); 
    void postOrder(Node rootNode);
}

public class BinaryTree implements interfaceBinaryTree {
……
}

③ 数据库设计及存储实现
本题选用MySQL数据库,并使用了Navicat可视化软件。数据库设计如下图所示
在这里插入图片描述

JDBC实现代码如下(在编写数据库操作中运用到处理异常操作,确保成功连接数据库,并对数据库进行相关操作)

package com.company;
import java.sql.*;

public class MySQL {

    public void CreateDatabase() {
        Connection connection = null;
        Statement statement = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/binarytree", "root", "***你的数据库密码***");
            statement = connection.createStatement();
            String sql = "CREATE TABLE `binarytree`.`binarytree`  (\n" +
                    "  `key` varchar(255) CHARACTER SET utf8 NOT NULL,\n" +
                    "  `value` varchar(255) CHARACTER SET utf8 NULL,\n" +
                    "  PRIMARY KEY (`key`)\n" +
                    ");";
            statement.executeUpdate(sql);
        }
        catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally {
            try {
                if(statement!=null) {
                    statement.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally{
                try {
                    if(connection!=null) {
                        connection.close();
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void add(int key,int value) {
        Connection connection = null;
        Statement statement = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/binarytree", "root", "***你的数据库密码***");
            statement = connection.createStatement();
            String sql = "INSERT INTO binarytree VALUES('"+key+"','"+value+"')";
            statement.executeUpdate(sql);
        }
        catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally {
            try {
                if(statement!=null) {
                    statement.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally{
                try {
                    if(connection!=null) {
                        connection.close();
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public void delete(int key) {
        Connection connection = null;
        Statement statement = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/binarytree", "root", "***你的数据库密码***");
            statement = connection.createStatement();
            String sql = "delete from binarytree where binarytree.`key`= '"+key+"';";
            statement.executeUpdate(sql);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            try {
                if(statement!=null) {
                    statement.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally{
                try {
                    if(connection!=null) {
                        connection.close();
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public void update(int key,int value ) {
        Connection connection = null;
        Statement statement = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/binarytree", "root", "***你的数据库密码***");
            statement = connection.createStatement();
            String sql = "update binarytree set binarytree.`value`='"+value+"' where binarytree.`key`='"+key+"';";
            statement.executeUpdate(sql);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            try {
                if(statement!=null) {
                    statement.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }finally{
                try {
                    if(connection!=null) {
                        connection.close();
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public void select() {
        Connection connection = null;
        Statement statement = null;
        ResultSet rs = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/binarytree", "root", "***你的数据库密码***");
            statement = connection.createStatement();
            //查find one node
         /*String sql = "select * from binarytree where key ='3' ;";
         rs = statement.executeQuery(sql);
         System.out.println(rs.next());
         System.out.print("key = "+rs.getInt("key")+" , ");
            System.out.print("value = "+rs.getString("value"));*/
            
            String sql = "select * from binarytree;";
            rs = statement.executeQuery(sql);
            while(rs.next()){
                System.out.print("key = "+rs.getInt("key")+" , ");
                System.out.print("value = "+rs.getString("value"));
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            try {
                if(rs!=null)rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }finally{
                try {
                    if(statement!=null)statement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }finally{
                    try {
                        if(connection!=null)connection.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

④ 二叉搜索树具体实现

package com.company;
public class BinaryTree implements interfaceBinaryTree {

    private Node root;
    private MySQL sql=new MySQL();

    BinaryTree(){
        sql.CreateDatabase();
    };

    public Node getRoot() {
        return this.root;
    }

    public void setRoot(Node root) {
        this.root = root;
    }

    @Override
    public Node visit(int key) {
        // TODO Auto-generated method stub
        Node currentNode = this.root;
        while ((currentNode != null) && (currentNode.key != key)) {
            if (key < currentNode.key) {
                currentNode = currentNode.leftChild;
            } else if (key > currentNode.key) {
                currentNode = currentNode.rightChild;
            }
        }
        return currentNode;
    }

    @Override
    public void insert(int key, int value) {
        // TODO Auto-generated method stub
        sql.add(key,value);
        if (this.root == null) {
            this.root = new Node(key, value);
            return;
        }
        Node currentNode = this.root;
        Node parentNode = this.root;
        boolean isLeftChild = true; 
        while (currentNode != null) {
            parentNode = currentNode;
            if (key < currentNode.key) {
                currentNode = currentNode.leftChild;
                isLeftChild = true;
            } else if (key > currentNode.key) {
                currentNode = currentNode.rightChild;
                isLeftChild = false;
            } else {
                break;
            }
        }
        if (parentNode != currentNode) {
            Node newNode = new Node(key, value);
            if (isLeftChild) {
                parentNode.leftChild = newNode;
            } else {
                parentNode.rightChild = newNode;
            }

        } else {
            currentNode.setValue(value);
        }
    }

    @Override
    public boolean delete(int key) {
        // TODO Auto-generated method stub
        sql.delete(key);
        Node currentNode = this.root;
        Node parentNode = this.root;
        boolean isLeftChild = true;
        while ((currentNode != null) && (currentNode.key != key)) {
            parentNode = currentNode;
            if (key < currentNode.key) {
                currentNode = currentNode.leftChild;
                isLeftChild = true;
            } else {
                currentNode = currentNode.rightChild;
                isLeftChild = false;
            }
        }
        if (currentNode == null) return false;
        if ((currentNode.leftChild == null) && (currentNode.rightChild == null)) {
            if (currentNode == this.root) {
                this.root = null;
            } else if (isLeftChild) {
                parentNode.leftChild = null;
            } else {
                parentNode.rightChild = null;
            }
        } else if ((currentNode.rightChild == null) && (currentNode.leftChild != null)) {
            if (currentNode == this.root) {
                this.root = currentNode.leftChild;
            } else if (isLeftChild) {
                parentNode.leftChild = currentNode.leftChild;
            } else {
                parentNode.rightChild = currentNode.leftChild;
            }
        } else if ((currentNode.leftChild == null) && (currentNode.rightChild != null)) {
            if (currentNode == this.root) {
                this.root = currentNode.rightChild;
            } else if (isLeftChild) {
                parentNode.leftChild = currentNode.rightChild;
            } else {
                parentNode.rightChild = currentNode.rightChild;
            }
        } 
        else {
            Node directPostNode = this.getDirectPostNode(currentNode);
            currentNode.key = directPostNode.key;
            currentNode.value = directPostNode.value;
        }

        return true;
    }

    @Override
    public Node getDirectPostNode(Node delNode) {
        // TODO Auto-generated method stub
       
        Node parentNode = delNode;
        Node direcrPostNode = delNode;
        Node currentNode = delNode.rightChild;
        while (currentNode != null) {
            parentNode = direcrPostNode;
            direcrPostNode = currentNode;
            currentNode = currentNode.leftChild;
        }
        if (direcrPostNode != delNode.rightChild) {
            parentNode.leftChild = direcrPostNode.rightChild;
            direcrPostNode.rightChild = null;
        }
        return direcrPostNode;
    }

    @Override
    public void preOrder(Node rootNode) {
        // TODO Auto-generated method stub
        if (rootNode != null) {
            System.out.println(rootNode.key + " " + rootNode.value);
            this.preOrder(rootNode.leftChild);
            this.preOrder(rootNode.rightChild);
        }
    }

    @Override
    public void inOrder(Node rootNode) {
        // TODO Auto-generated method stub
        if (rootNode != null) {
            this.inOrder(rootNode.leftChild);
            System.out.println(rootNode.key + " " + rootNode.value);
            this.inOrder(rootNode.rightChild);
        }
    }

    @Override
    public void postOrder(Node rootNode) {
        // TODO Auto-generated method stub
        if (rootNode != null) {
            this.postOrder(rootNode.leftChild);
            this.postOrder(rootNode.rightChild);
            System.out.println(rootNode.key + " " + rootNode.value);
        }
    }
    
    @Override
    public boolean update(int key, int value) {
        // TODO Auto-generated method stub
        sql.update(key,value);
        Node node = this.visit(key);
        node.setValue(value);
        return true;
    }
}

⑤ 测试

package com.company;
public class Main{
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        BinaryTree tree = new BinaryTree();
        tree.insert(6, 6);
        tree.insert(3, 3);
        tree.insert(14, 14);
        tree.insert(16, 16);
        tree.insert(10, 10);
        tree.insert(9, 9);
        tree.insert(13, 13);
        tree.insert(11, 11);
        tree.insert(12, 12);
        System.out.println("Results of inOrder traversal before deleting.The result is an increasing ordered sequence.
");
        tree.inOrder(tree.getRoot());
        tree.update(12, 200);
        System.out.println("Update the value of node key = 12");
        tree.inOrder(tree.getRoot());
        System.out.println("Results after deleting node 10");
        tree.delete(10);
        tree.inOrder(tree.getRoot());
        System.out.println("The results of preorder traversal are as follows");
        tree.preOrder(tree.getRoot()); 
    }
}

6、 程序结果
在这里插入图片描述
在这里插入图片描述

运行程序后数据库中结果显示如下

在这里插入图片描述

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值