图描述了 Java 中的二叉树遍历

graph describe binary tree traversal in Java

在我的程序中,我使用一个名为 "curNode" 的变量来表示树根。每次我在文本字段中输入 0 或 1 时,curNode 将变为 curNode.left 或 curNode.right,然后新的当前节点变为红色而不是黑色。但它只有在我输入一些东西后才有效,在 init 中,树根没有红色。 这是我的 TriesView.java:

package tree;

import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Stack;

import javax.swing.*;

public class TriesView extends JPanel {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private Huffman tree; // A binary tree to be displayed
    private PaintTree paintTree;
    private JTextField pathTxt;
    public HuffmanNode curNode;
    private Stack<String> txtStack = new Stack<String>();

    /** Construct a view for a binary tree */
    public TriesView(Huffman tree) {   
        this.tree = tree; // Set a binary tree to be displayed
        curNode = tree.root;
        paintTree = new PaintTree();
        setUI();
    }

    /** Initialize UI for binary tree */
    private void setUI() {
        this.setLayout(new BorderLayout()); 
        JScrollPane scrollPane = new JScrollPane(paintTree, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        add(scrollPane, BorderLayout.CENTER);

        if(!tree.isEmpty()){
            paintTree.setPreferredSize(new Dimension((int)Math.pow(2, (tree.getDepth() + 1)) * paintTree.radius, (tree.getDepth() + 1) * paintTree.vGap + paintTree.radius));
            scrollPane.setPreferredSize(new Dimension((int)Math.pow(2, (tree.getDepth() + 1)) * paintTree.radius, (tree.getDepth() + 1) * paintTree.vGap + paintTree.radius));
        }
        JPanel panel = new JPanel();
        pathTxt = new JTextField(10);
        panel.add(new JLabel("Enter key path: "));
        panel.add(pathTxt);
        add(panel, BorderLayout.SOUTH);

        pathTxt.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent evt) {
                String txt = pathTxt.getText();
                txtStack.push(txt);
            }
            public void keyReleased(KeyEvent evt) {
                String txt = pathTxt.getText();
                String oldTxt = pathTxt.getText();
                if(!txtStack.isEmpty())
                    oldTxt = txtStack.pop();
                if (txt.matches("^[01]*$") != true) {
                    pathTxt.setText(oldTxt);
                    JOptionPane.showMessageDialog(null, "Ký tự không hợp lệ");
                    return;
                }
                HuffmanNode temp = tree.root;
                for(int i = 0; i < txt.length() && temp != null; i++){
                    if(txt.charAt(i) == '0'){
                        temp = temp.left;
                    }else if(txt.charAt(i) == '1'){
                        temp = temp.right;
                    }
                }
                if(temp == null){
                    JOptionPane.showMessageDialog(null, "Dãy không hợp lệ");
                    pathTxt.setText(oldTxt);
                    return;
                }
                curNode = temp;
                scrollPane.repaint();
            }
        });
    }

    // Inner class PaintTree for displaying a tree on a panel
    class PaintTree extends JPanel {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        private int radius = 20; // Tree node radius
        private int vGap = 50; // Gap between two levels in a tree

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            if (tree != null) {
                // Display tree recursively    
                //              displayTree(g, tree.root, (int)Math.pow(2, tree.root.height - 1)*radius, 30, (int)Math.pow(2, tree.root.height-2)*radius); 
                displayTree(g, tree.root, getWidth()/2, 30, getWidth()/4); 
            }
        }

        /** Display a subtree rooted at position (x, y) */
        private void displayTree(Graphics g, HuffmanNode root, 
                int x, int y, int hGap) {
            // Display the root
            if(root == null) return;
            Graphics2D ga = (Graphics2D)g;
            if(curNode == root){
                ga.setPaint(Color.RED);
            }else{
                ga.setPaint(Color.BLACK);
            }
            ga.fillOval(x - radius, y - radius, 2 * radius, 2 * radius);
            ga.setPaint(Color.BLACK);
            ga.setColor(Color.WHITE);
            ga.drawString(String.valueOf(root.frequency), x - 6, y + 4);
            ga.setColor(Color.RED);
            ga.drawString(String.valueOf(root.value), x - 6, y + 36);
            ga.setColor(Color.BLACK);

            if (root.left != null) {
                // Draw a line to the left node
                connectLeftChild(g, x - hGap, y + vGap, x, y);
                ga.drawString("0", x - hGap/2 - 12, y + vGap/2);
                displayTree(g, root.left, x - hGap, y + vGap, Math.max(hGap / 2, radius));
            }

            if (root.right != null) {
                // Draw a line to the right node
                connectRightChild(g, x + hGap, y + vGap, x, y);
                ga.drawString("1", x + hGap/2 + 5, y + vGap/2);
                // Draw the right subtree recursively
                displayTree(g, root.right, x + hGap, y + vGap, Math.max(hGap / 2, radius));  
            }
        }

        public int getRadius(){
            return this.radius;
        }

        public int getVGap(){
            return this.vGap;
        }

        /** Connect a parent at (x2, y2) with 
         * its left child at (x1, y1) */
        private void connectLeftChild(Graphics g, 
                int x1, int y1, int x2, int y2) { 
            double d = Math.sqrt(vGap * vGap + (x2 - x1) * (x2 - x1));
            int x11 = (int)(x1 + radius * (x2 - x1) / d);
            int y11 = (int)(y1 - radius * vGap / d);
            int x21 = (int)(x2 - radius * (x2 - x1) / d);
            int y21 = (int)(y2 + radius * vGap / d);
            g.drawLine(x11, y11, x21, y21);
        }

        /** Connect a parent at (x2, y2) with 
         * its right child at (x1, y1) */
        private void connectRightChild(Graphics g, 
                int x1, int y1, int x2, int y2) {
            double d = Math.sqrt(vGap * vGap + (x2 - x1) * (x2 - x1));
            int x11 = (int)(x1 - radius * (x1 - x2) / d);
            int y11 = (int)(y1 - radius * vGap / d);
            int x21 = (int)(x2 + radius * (x1 - x2) / d);
            int y21 = (int)(y2 + radius * vGap / d);
            g.drawLine(x11, y11, x21, y21);
        }
    }
}

我找到了解决方案: 每次在树中插入或删除节点后重新绘制组件