Java实战(三):二叉排序树的可视化

目录

前言

1.树节点类

2.二叉树类

2.1插入

2.2删除

2.3查询

3.二叉树可视化

2.1界面设计

4.总代码


前言

插入

删除

查询

1.树节点类

class TreeNode {
    private String value;
    private TreeNode left;
    private TreeNode right;

    public TreeNode(String value) {
        this.value = value;
        this.left = null;
        this.right = null;
    }

    public String getValue() {
        return value;
    }

    public TreeNode getLeft() {
        return left;
    }

    public TreeNode getRight() {
        return right;
    }

    public void setLeft(TreeNode left) {
        this.left = left;
    }

    public void setRight(TreeNode right) {
        this.right = right;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

定义了一个树节点类(TreeNode),包含节点的值(value)、左子节点(left)和右子节点(right)。设置和得到其节点的值

2.二叉树类

2.1插入

 public void insert(String value) {
        // 如果根节点为空,则创建一个新的树节点
        if (root == null) {
            root = new TreeNode(value);
        } else {
            // 否则,插入新节点
            insertNode(root, value);
        }
    }

    // 递归插入节点
    private void insertNode(TreeNode node, String value) {
        //比较当前节点的值和插入的值的大小
        if (value.compareTo(node.getValue()) < 0) {
            //如果当前节点的左子节点为空,则插入新节点
            if (node.getLeft() == null) {
                node.setLeft(new TreeNode(value));
            } else {
                //如果当前节点的左子节点不为空,则递归插入新节点
                insertNode(node.getLeft(), value);
            }
        } else {
            //如果当前节点的右子节点为空,则插入新节点
            if (node.getRight() == null) {
                node.setRight(new TreeNode(value));
            } else {
                //如果当前节点的右子节点不为空,则递归插入新节点
                insertNode(node.getRight(), value);
            }
        }
    }

 递归插入,先比较和其根节点的大小,若小于,插入其左子树;若大于插入其右子树;记得判断是不是空的,若是空的插入下一个左子树或右子树。

2.2删除

  public void delete(String value) {
        // 删除值为value的节点,并将删除后的节点赋值给root
        root = deleteNode(root, value);
    }
    // 递归删除节点
    private TreeNode deleteNode(TreeNode node, String value) {
        // 如果节点为空,则返回空
        if (node == null) {
            return null;
        }

        // 如果要删除的值小于当前节点的值,则递归删除左子树
        if (value.compareTo(node.getValue()) < 0) {
            node.setLeft(deleteNode(node.getLeft(), value));
        // 如果要删除的值大于当前节点的值,则递归删除右子树
        } else if (value.compareTo(node.getValue()) > 0) {
            node.setRight(deleteNode(node.getRight(), value));
        // 如果要删除的值等于当前节点的值,则分情况处理
        } else {
            // 如果当前节点没有左右子树,则返回空
            if (node.getLeft() == null && node.getRight() == null) {
                return null;
            // 如果当前节点只有左子树,则返回左子树
            } else if (node.getLeft() == null) {
                return node.getRight();
            // 如果当前节点只有右子树,则返回右子树
            } else if (node.getRight() == null) {
                return node.getLeft();
            // 如果当前节点左右子树都存在,则找到右子树的最小节点,将当前节点的值替换为该最小节点的值,然后递归删除该最小节点
            } else {
                TreeNode minNode = findMinNode(node.getRight());
                node.setValue(minNode.getValue());
                node.setRight(deleteNode(node.getRight(), minNode.getValue()));
            }
        }

        return node;
    }

    // 查找最小节点
   private TreeNode findMinNode(TreeNode node) {
        // 循环查找左子树的最小节点
        while (node.getLeft() != null) {
            node = node.getLeft();
        }
        return node;
    }

比较删除的值和当前节点的大小,若小于则递归删除左子树,大于则递归删除右子树,等于分为四种情况,当前节点没有左子树和右子树,就删他,只有左子树,则删左子树,只有右子树,则删右子树,两个树都有, 则找到右子树的最小节点,将当前节点值替换成最小节点值,然后递归删除该最小节点。

2.3查询

   // 查找节点
   public boolean search(String value) {
        // 调用searchNode函数,传入根节点和要搜索的值,返回搜索结果
        return searchNode(root, value);
    }
    // 递归查找节点
   private boolean searchNode(TreeNode node, String value) {
        // 如果节点为空,返回false
        if (node == null) {
            return false;
        }

        // 如果节点值等于value,返回true
        if (value.equals(node.getValue())) {
            return true;
        // 如果节点值小于value,在左子树中查找
        } else if (value.compareTo(node.getValue()) < 0) {
            return searchNode(node.getLeft(), value);
        // 如果节点值大于value,在右子树中查找
        } else {
            return searchNode(node.getRight(), value);
        }
    }

比较节点值和根节点的大小,等于返回TURE,小于在左子树查找,大于在右子树查找,递归出口为节点为空,返回FLASE

3.二叉树可视化

public class BinaryTreeVisualization extends JFrame {
    private BinaryTree binaryTree;
    private DefaultTreeModel treeModel;
    private JTextField valueField;
    private JTextArea resultArea;

    public BinaryTreeVisualization() {
// 创建一个BinaryTree对象
        binaryTree = new BinaryTree();
// 创建一个DefaultTreeModel对象,并传入null
        treeModel = new DefaultTreeModel(null);

        // 初始化二叉树
        binaryTree.insert("5");
        binaryTree.insert("3");
        binaryTree.insert("7");
        binaryTree.insert("2");
        binaryTree.insert("4");
        binaryTree.insert("6");
        binaryTree.insert("8");

// 创建一个JTree,将treeModel作为参数传入
        JTree tree = new JTree(treeModel);
// 创建一个JScrollPane,将tree作为参数传入
        JScrollPane treeScrollPane = new JScrollPane(tree);
// 设置treeScrollPane的尺寸为(400,400)
        treeScrollPane.setPreferredSize(new Dimension(400, 400));

// 创建一个JTextField,宽度为10
        valueField = new JTextField(10);

        JButton insertButton = new JButton("插入");
        insertButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //获取输入框中的值
                String value = valueField.getText();
                //将值插入到二叉树中
                binaryTree.insert(value);
                //更新二叉树
                updateTree();
                //清空输入框
                valueField.setText("");
                //输出插入成功
                resultArea.setText("插入成功");
            }
        });

        JButton deleteButton = new JButton("删除");
        deleteButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //获取输入框中的值
                String value = valueField.getText();
                //将值从二叉树中删除
                binaryTree.delete(value);
                //更新二叉树
                updateTree();
                //清空输入框
                valueField.setText("");
                //输出删除成功
                resultArea.setText("删除成功");
            }
        });

        JButton searchButton = new JButton("查询");
        searchButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //获取输入框中的值
                String value = valueField.getText();
                //查询二叉树中是否有这个值
                boolean found = binaryTree.search(value);
                if (found) {
                    //输出查询成功,有这个节点
                    resultArea.setText("查询成功,有这个节点");
                } else {
                    //输出查询失败,没有这个节点
                    resultArea.setText("查询失败,没有这个节点");
                }
                //清空输入框
                valueField.setText("");
            }
        });
        resultArea = new JTextArea(5, 20);
        resultArea.setEditable(false);

        JPanel controlPanel = new JPanel();
        controlPanel.add(new JLabel("节点值:"));
        controlPanel.add(valueField);
        controlPanel.add(insertButton);
        controlPanel.add(deleteButton);
        controlPanel.add(searchButton);

        Container contentPane = getContentPane();
        contentPane.setLayout(new BorderLayout());
        contentPane.add(treeScrollPane, BorderLayout.CENTER);
        contentPane.add(controlPanel, BorderLayout.NORTH);
        contentPane.add(resultArea, BorderLayout.SOUTH);

//设置窗口的关闭操作
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//设置窗口的标题
        setTitle("二叉树可视化");
//设置窗口的尺寸
        pack();
//设置窗口的位置
        setLocationRelativeTo(null);
//设置窗口的可见性
        setVisible(true);

//更新二叉树
        updateTree();
    }

    // 更新树的显示
   private void updateTree() {
        //创建根节点
        DefaultMutableTreeNode root = createTreeNode(binaryTree.getRoot());
        //设置根节点
        treeModel.setRoot(root);
        //重新加载树模型
        treeModel.reload();
    }

    // 创建树节点
   private DefaultMutableTreeNode createTreeNode(TreeNode node) {
        // 创建一个DefaultMutableTreeNode对象,并传入node的值
        DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode(node.getValue());
        // 如果node的左子树不为空,则添加到treeNode中
        if (node.getLeft() != null) {
            treeNode.add(createTreeNode(node.getLeft()));
        }
        // 如果node的右子树不为空,则添加到treeNode中
        if (node.getRight() != null) {
            treeNode.add(createTreeNode(node.getRight()));
        }
        // 返回treeNode
        return treeNode;
    }

    public static void main(String[] args) {
        // 使用SwingUtilities的invokeLater方法,在UI线程中运行BinaryTreeVisualization类
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new BinaryTreeVisualization();
            }
        });
    }
}

2.1界面设计

有插入,查询和删除按钮,然后展示二叉树的结构。

DefaultMutableTreeNodejavax.swing.tree包中的一个类,它表示一棵默认的树形结构。这个类提供了基本的树节点操作,例如添加子节点、删除子节点、设置和获取节点的值等。可以加载树的结构

4.总代码

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

// 树节点类
class TreeNode {
    private String value;
    private TreeNode left;
    private TreeNode right;

    public TreeNode(String value) {
        this.value = value;
        this.left = null;
        this.right = null;
    }

    public String getValue() {
        return value;
    }

    public TreeNode getLeft() {
        return left;
    }

    public TreeNode getRight() {
        return right;
    }

    public void setLeft(TreeNode left) {
        this.left = left;
    }

    public void setRight(TreeNode right) {
        this.right = right;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

// 二叉树类
class BinaryTree {
    private TreeNode root;

    public BinaryTree() {
        root = null;
    }

    public TreeNode getRoot() {
        return root;
    }

    // 插入节点
   public void insert(String value) {
        // 如果根节点为空,则创建一个新的树节点
        if (root == null) {
            root = new TreeNode(value);
        } else {
            // 否则,插入新节点
            insertNode(root, value);
        }
    }

    // 递归插入节点
    private void insertNode(TreeNode node, String value) {
        //比较当前节点的值和插入的值的大小
        if (value.compareTo(node.getValue()) < 0) {
            //如果当前节点的左子节点为空,则插入新节点
            if (node.getLeft() == null) {
                node.setLeft(new TreeNode(value));
            } else {
                //如果当前节点的左子节点不为空,则递归插入新节点
                insertNode(node.getLeft(), value);
            }
        } else {
            //如果当前节点的右子节点为空,则插入新节点
            if (node.getRight() == null) {
                node.setRight(new TreeNode(value));
            } else {
                //如果当前节点的右子节点不为空,则递归插入新节点
                insertNode(node.getRight(), value);
            }
        }
    }

    // 删除节点
   public void delete(String value) {
        // 删除值为value的节点,并将删除后的节点赋值给root
        root = deleteNode(root, value);
    }
    // 递归删除节点
    private TreeNode deleteNode(TreeNode node, String value) {
        // 如果节点为空,则返回空
        if (node == null) {
            return null;
        }

        // 如果要删除的值小于当前节点的值,则递归删除左子树
        if (value.compareTo(node.getValue()) < 0) {
            node.setLeft(deleteNode(node.getLeft(), value));
        // 如果要删除的值大于当前节点的值,则递归删除右子树
        } else if (value.compareTo(node.getValue()) > 0) {
            node.setRight(deleteNode(node.getRight(), value));
        // 如果要删除的值等于当前节点的值,则分情况处理
        } else {
            // 如果当前节点没有左右子树,则返回空
            if (node.getLeft() == null && node.getRight() == null) {
                return null;
            // 如果当前节点只有左子树,则返回左子树
            } else if (node.getLeft() == null) {
                return node.getRight();
            // 如果当前节点只有右子树,则返回右子树
            } else if (node.getRight() == null) {
                return node.getLeft();
            // 如果当前节点左右子树都存在,则找到右子树的最小节点,将当前节点的值替换为该最小节点的值,然后递归删除该最小节点
            } else {
                TreeNode minNode = findMinNode(node.getRight());
                node.setValue(minNode.getValue());
                node.setRight(deleteNode(node.getRight(), minNode.getValue()));
            }
        }

        return node;
    }

    // 查找最小节点
   private TreeNode findMinNode(TreeNode node) {
        // 循环查找左子树的最小节点
        while (node.getLeft() != null) {
            node = node.getLeft();
        }
        return node;
    }

    // 查找节点
   public boolean search(String value) {
        // 调用searchNode函数,传入根节点和要搜索的值,返回搜索结果
        return searchNode(root, value);
    }
    // 递归查找节点
   private boolean searchNode(TreeNode node, String value) {
        // 如果节点为空,返回false
        if (node == null) {
            return false;
        }

        // 如果节点值等于value,返回true
        if (value.equals(node.getValue())) {
            return true;
        // 如果节点值小于value,在左子树中查找
        } else if (value.compareTo(node.getValue()) < 0) {
            return searchNode(node.getLeft(), value);
        // 如果节点值大于value,在右子树中查找
        } else {
            return searchNode(node.getRight(), value);
        }
    }
}
// 二叉树可视化界面类
public class BinaryTreeVisualization extends JFrame {
    private BinaryTree binaryTree;
    private DefaultTreeModel treeModel;
    private JTextField valueField;
    private JTextArea resultArea;

    public BinaryTreeVisualization() {
// 创建一个BinaryTree对象
        binaryTree = new BinaryTree();
// 创建一个DefaultTreeModel对象,并传入null
        treeModel = new DefaultTreeModel(null);

        // 初始化二叉树
        binaryTree.insert("5");
        binaryTree.insert("3");
        binaryTree.insert("7");
        binaryTree.insert("2");
        binaryTree.insert("4");
        binaryTree.insert("6");
        binaryTree.insert("8");

// 创建一个JTree,将treeModel作为参数传入
        JTree tree = new JTree(treeModel);
// 创建一个JScrollPane,将tree作为参数传入
        JScrollPane treeScrollPane = new JScrollPane(tree);
// 设置treeScrollPane的尺寸为(400,400)
        treeScrollPane.setPreferredSize(new Dimension(400, 400));

// 创建一个JTextField,宽度为10
        valueField = new JTextField(10);

        JButton insertButton = new JButton("插入");
        insertButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //获取输入框中的值
                String value = valueField.getText();
                //将值插入到二叉树中
                binaryTree.insert(value);
                //更新二叉树
                updateTree();
                //清空输入框
                valueField.setText("");
                //输出插入成功
                resultArea.setText("插入成功");
            }
        });

        JButton deleteButton = new JButton("删除");
        deleteButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //获取输入框中的值
                String value = valueField.getText();
                //将值从二叉树中删除
                binaryTree.delete(value);
                //更新二叉树
                updateTree();
                //清空输入框
                valueField.setText("");
                //输出删除成功
                resultArea.setText("删除成功");
            }
        });

        JButton searchButton = new JButton("查询");
        searchButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //获取输入框中的值
                String value = valueField.getText();
                //查询二叉树中是否有这个值
                boolean found = binaryTree.search(value);
                if (found) {
                    //输出查询成功,有这个节点
                    resultArea.setText("查询成功,有这个节点");
                } else {
                    //输出查询失败,没有这个节点
                    resultArea.setText("查询失败,没有这个节点");
                }
                //清空输入框
                valueField.setText("");
            }
        });
        resultArea = new JTextArea(5, 20);
        resultArea.setEditable(false);

        JPanel controlPanel = new JPanel();
        controlPanel.add(new JLabel("节点值:"));
        controlPanel.add(valueField);
        controlPanel.add(insertButton);
        controlPanel.add(deleteButton);
        controlPanel.add(searchButton);

        Container contentPane = getContentPane();
        contentPane.setLayout(new BorderLayout());
        contentPane.add(treeScrollPane, BorderLayout.CENTER);
        contentPane.add(controlPanel, BorderLayout.NORTH);
        contentPane.add(resultArea, BorderLayout.SOUTH);

//设置窗口的关闭操作
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//设置窗口的标题
        setTitle("二叉树可视化");
//设置窗口的尺寸
        pack();
//设置窗口的位置
        setLocationRelativeTo(null);
//设置窗口的可见性
        setVisible(true);

//更新二叉树
        updateTree();
    }

    // 更新树的显示
   private void updateTree() {
        //创建根节点
        DefaultMutableTreeNode root = createTreeNode(binaryTree.getRoot());
        //设置根节点
        treeModel.setRoot(root);
        //重新加载树模型
        treeModel.reload();
    }

    // 创建树节点
   private DefaultMutableTreeNode createTreeNode(TreeNode node) {
        // 创建一个DefaultMutableTreeNode对象,并传入node的值
        DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode(node.getValue());
        // 如果node的左子树不为空,则添加到treeNode中
        if (node.getLeft() != null) {
            treeNode.add(createTreeNode(node.getLeft()));
        }
        // 如果node的右子树不为空,则添加到treeNode中
        if (node.getRight() != null) {
            treeNode.add(createTreeNode(node.getRight()));
        }
        // 返回treeNode
        return treeNode;
    }

    public static void main(String[] args) {
        // 使用SwingUtilities的invokeLater方法,在UI线程中运行BinaryTreeVisualization类
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new BinaryTreeVisualization();
            }
        });
    }
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

从零开始的奋豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值