繁体   English   中英

二叉树中的节点交叉

[英]Nodes crossing in Binary Tree

我正在研究代码以构建二叉树并显示它以进行家庭作业。(因此,自然地,我必须从头开始构建树。)代码功能,但是我似乎想不出一种方法来保持节点从树上越过大约4个级别。 我希望有人可以帮助我动动脑筋...但是有没有办法检查树倒下多少层并调整上面各层节点之间的水平距离? 在我的研究中,我看到了一些不同的方法,但是根据分配参数,必须使用displayTree()方法来递归地进行操作。 任何帮助表示赞赏。

PS:当前的horizo​​ntalGap变量是我一直在修改的,因此,如果它与代码混淆,我深表歉意。 这是displayTree()方法。

//displayTree() with crossing issue
//**************************************************************************
public void displayTree(Graphics g, Node localTree, int x, int y, int level)

{
      // Display the root
      int verticalGap = 50;
      int horizontalGap = 250 / level;

      g.drawOval(x, y, radius, radius);
      g.drawString(localTree.getKey() + "", x + (radius / 4) , y + 20);

      if (localTree.getLeft() != null) {
         // Draw a line to the left node
         lineToLeftChild(g, x - horizontalGap, y + verticalGap, x, y);
        // Draw the left subtree recursively
         displayTree(g, localTree.leftChild, x - horizontalGap, y + verticalGap, level + 1);
      }

     if (localTree.rightChild != null) {
         // Draw a line to the right node
        lineToRightChild(g, x + horizontalGap, y + verticalGap, x, y);
        // Draw the right subtree recursively
        displayTree(g, localTree.rightChild, x + horizontalGap, y + verticalGap, level + 1);  
      }
    }//end displayTree()
    //**************************************************************************

    //Line to child
    //**************************************************************************
    private void lineToLeftChild(Graphics g,  int x1, int y1, int x2, int y2) { 
        g.drawLine(x1 + (radius/2), y1, x2, y2 + (radius/2));  
    }//end LinetoLeft
    //**************************************************************************

    //Line to child
    //**************************************************************************
    private void lineToRightChild(Graphics g, int x1, int y1, int x2, int y2) {
        g.drawLine(x1 + (radius /2), y1, (x2 + radius) , y2 + (radius/2));
    }//end line to Right()
    //**************************************************************************
}  

这是您遇到交叉节点问题的一个示例吗?

带有交叉节点的屏幕截图

我认为您的节​​点开始在某个级别交叉的事实是您如何显示树的结果。 较低级别的节点数量可以比较高级别的节点数量高得多,因此需要在具有最高节点数量的级别上确定最小的空间量。 这会在较高级别上导致大量空白。

您要支持多少个级别? 您可以计算某个级别上最大数量的节点的最小空间(例如,根节点下6个级别的2 ^ 6 = 10个像素= 64个节点),每个更高级别的空间则加倍。

您还可以使用其他方式显示树,例如The Java Tutorials-How to Use Trees中的“文件管理器”之类的方法,在该方法中,子节点占用所需的空间就足够了:

像树一样的文件管理器

编辑:代码示例

如果您想从Stack Overflow上获得好的和快速的答案,最好在问题中添加一个简短,可运行的问题示例(所谓的Minimal,Complete和Verifiable示例:请参见https://stackoverflow.com / help / mcve了解更多信息)。 这样,您可以帮助他人来帮助您。

这是我添加到您的代码中的一些代码,以创建具有可能解决方案的示例:

// Main class TreeFromScratch:

import java.awt.BorderLayout;
import javax.swing.*;

public class TreeFromScratch {
    public static void main(final String[] arguments) {
        SwingUtilities.invokeLater(() -> new TreeFromScratch().createAndShowGui());
    }

    private void createAndShowGui() {
        final JFrame frame = new JFrame("Stack Overflow");
        frame.setBounds(100, 100, 1200, 600);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        final JPanel panel = new JPanel(new BorderLayout());
        final Node tree = createTree();
        panel.add(new CustomTree(tree), BorderLayout.CENTER);
        frame.getContentPane().add(panel);

        frame.setVisible(true);
    }

    private Node createTree() {
        final Node tree = new Node('a');
        tree.leftChild = new Node('b');

        tree.leftChild.leftChild = new Node('c');
        tree.leftChild.leftChild.leftChild = new Node('d');
        tree.leftChild.leftChild.leftChild.leftChild = new Node('e');
        tree.leftChild.leftChild.leftChild.leftChild.leftChild = new Node('f');

        tree.leftChild.rightChild = new Node('g');
        tree.leftChild.rightChild.rightChild = new Node('h');
        tree.leftChild.rightChild.rightChild.rightChild = new Node('i');
        tree.leftChild.rightChild.rightChild.rightChild.rightChild = new Node('j');

        tree.rightChild = new Node('k');
        tree.rightChild.leftChild = new Node('l');
        tree.rightChild.leftChild.leftChild = new Node('m');
        tree.rightChild.leftChild.leftChild.leftChild = new Node('n');
        tree.rightChild.leftChild.leftChild.leftChild.leftChild = new Node('o');

        return tree;
    }
}


// Class CustomTree:

import java.awt.Graphics;
import javax.swing.JPanel;

public class CustomTree extends JPanel {
    private Node tree;
    private int radius = 40;

    public CustomTree(Node tree) {
        this.tree = tree;
    }

    @Override
    protected void paintComponent(Graphics g) {
        displayTree(g, tree, 660, 100, 1);
    }

    //displayTree() with crossing issue
    //**************************************************************************
    public void displayTree(Graphics g, Node localTree, int x, int y, int level) {
        // Display the root
        int verticalGap = 50;
        //int horizontalGap = 250 / level;
        int horizontalGap = (int) (660 / Math.pow(2, level));

        g.drawOval(x, y, radius, radius);
        g.drawString(localTree.getKey() + "", x + (radius / 4), y + 20);

        if (localTree.getLeft() != null) {
            // Draw a line to the left node
            lineToLeftChild(g, x - horizontalGap, y + verticalGap, x, y);
            // Draw the left subtree recursively
            displayTree(g, localTree.leftChild, x - horizontalGap, y + verticalGap,
                        level + 1);
        }

        if (localTree.rightChild != null) {
            // Draw a line to the right node
            lineToRightChild(g, x + horizontalGap, y + verticalGap, x, y);
            // Draw the right subtree recursively
            displayTree(g, localTree.rightChild, x + horizontalGap, y + verticalGap,
                        level + 1);
        }
    }//end displayTree()
    //**************************************************************************

    //Line to child
    //**************************************************************************
    private void lineToLeftChild(Graphics g, int x1, int y1, int x2, int y2) {
        g.drawLine(x1 + (radius / 2), y1, x2, y2 + (radius / 2));
    }//end LinetoLeft
    //**************************************************************************

    //Line to child
    //**************************************************************************
    private void lineToRightChild(Graphics g, int x1, int y1, int x2, int y2) {
        g.drawLine(x1 + (radius / 2), y1, (x2 + radius), y2 + (radius / 2));
    }//end line to Right()
    //**************************************************************************
}


// Class Node:

public class Node {
    private char key;
    protected Node leftChild;
    protected Node rightChild;

    public Node(char key) {
        this.key = key;
    }

    public char getKey() {
        return key;
    }

    public Node getLeft() {
        return leftChild;
    }
}

用不同的方法来计算horizontalGap ,树现在看起来像这样:

屏幕截图,没有交叉节点

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM