[英]Binary-Tree: Some Child Nodes Null, Others Not
我正在写一个程序,可以转换为莫尔斯电码,反之亦然。 我使用树来更有效地搜索代码或关联值。 Morse和关联的值将从文件读取到静态数组中。 索引0是所有其他子树的根,实际上是一个虚拟节点,链接到左子树(index [1])和右子树(index [16])。
读完节点后,我通过遍历静态数组并按需分配节点来链接子节点。 索引[2]-[16]保留左子树。 索引[17]-(alphaTree.length-1)保留右侧的子树。
这是我的问题:当尝试分配所有子节点时,当我将它们打印出来时,其中的一些为空。 节点本身不是null,而只是子节点。
我注意到了一种模式,但不知道如何解决。
下面是示例输出。 输出很大,因此我将其削减了,但留得足够多,您可以看到我的意思:
Element left 0: -, t
Element right 0: *, e
Element left 1: null
Element right 1: null
Element left 2: --, m
Element right 2: null
Element left 3: null
Element right 3: -*, n
Element left 4: ---, o
Element right 4: null
Element left 5: null
. . .
Element right 25: null
Element left 26: null
Element right 26: *-**, l
Element left 27: **--, ö
Element right 27: null
Element left 28: null
Element right 28: **-*, f
Element left 29: ***-, v
Element right 29: null
以下是我用来填充静态数组的文件。 因为树中有特殊字符,所以我使用ASCII并在读取文件时进行转换:
- 116
-- 109
-* 110
--- 111
--* 103
-*- 107
-** 100
---- 247
---* 246
--*- 113
--** 122
-*-- 121
-*-* 99
-**- 120
-*** 98
* 101
*- 97
** 105
*-- 119
*-* 114
**- 117
*** 115
*--- 106
*--* 112
*-*- 228
*-** 108
**-- 246
**-* 102
***- 118
**** 104
下面是我用来填充树并链接节点的代码。 linkLeftTree()和linkRightTree()是将父节点与其子节点链接的方法。 通过open()方法将节点读入数组。
package MorseTrees;
import MorseTrees.Nodes.*;
import java.util.*;
import java.io.*;
public class TreePopulater {
private static final int ALPHABET = 31;
private static final String alphaRaw = "alphatree2.txt";
private static final A_Node[] alphaTree = new AlphaNode[ALPHABET];
private A_Node aNode;
public TreePopulater() {
alphaTree[0] = new AlphaNode("000");
alphaTree[0].setAlpha('0');
populateRaw(alphaRaw);
}
private A_Node[] populateRaw(String treeType)
{
// open and fill static array
open(treeType);
}
private void open(String fileName) {
//try, catch, etc.
Scanner in = new Scanner(new File(fileName));
int counter = 1;
while (in.hasNextLine()) {
aNode = new AlphaNode(in.next());
aNode.setAlpha((char) in.nextInt());
alphaTree[counter] = aNode;
counter++;
}
linkNodes();
}
private void linkNodes() {
// force link root node
alphaTree[0].setLeft(alphaTree[1]);
alphaTree[0].setRight(alphaTree[16]);
linkLeftTree();
linkRightTree();
printChildren();
}
public void linkLeftTree()
{
// link the left, or first half, of the array
for (int i = 2; i < (alphaTree.length / 2); i++) // or 16
{
alphaTree[i].setLeft(alphaTree[(i++)]);
alphaTree[i].setRight(alphaTree[(i)]);
}
}
public void linkRightTree()
{
// link the right, or second half, of the array
for (int i = 17; i <= alphaTree.length - 1; i++)
{
alphaTree[i].setLeft(alphaTree[(i++)]);
alphaTree[i].setRight(alphaTree[(i)]);
}
}
public void printChildren()
{
for (int i = 0; i < alphaTree.length - 1; i++)
{
System.out.println("Element left " + i + ": " + alphaTree[i].leftChild());
System.out.println("Element right " + i + ": " + alphaTree[i].rightChild());
}
}
public static void main(String[] args)
{
TreePopulater tp = new TreePopulater();
}
}
节点类AlphaNode扩展了A_Node。 A_Node看起来就像您期望的那样:左右两个孩子的实例变量,莫尔斯电码和与其关联的字母以及所有所需的getter和setter方法。
奇怪的是,如果我在linkLeftTree()和linkRightTree()中的setter上使用System.out.println(),则在循环中看不到任何空值,但是当我实际尝试访问子节点时仍然有空值(例如例如,预订搜索)。
(应归功于信贷:该程序中实现的字母树是基于Charles Petzold在“代码”一书中优化的树。但是这里的所有代码都是您真正编写的。)
我对以下代码表示怀疑:
public void linkLeftTree()
{
// link the left, or first half, of the array
// NOTE: the code runs for i=2,4,8,10,12,14 so many nodes have the left
// and right neighbors unassigned
for (int i = 2; i < (alphaTree.length / 2); i++) // or 16
{ // NOTE:
// This should alphaTree[i].setLeft(alphaTree[i+1])
// Since you are changing the value of i twice
// A good idea is to print i and verify the values
alphaTree[i].setLeft(alphaTree[(i++)]);
alphaTree[i].setRight(alphaTree[(i)]);
}
}
public void linkRightTree()
{
// link the right, or second half, of the array
//NOTE: the code runs for i=17,19.. so many nodes have the left
// and right neighbors unassigned
for (int i = 17; i <= alphaTree.length - 1; i++)
{
// Same as above
alphaTree[i].setLeft(alphaTree[(i++)]);
alphaTree[i].setRight(alphaTree[(i)]);
}
}
我不完全确定哪种索引将特定于您的算法,但我想我回答了您的问题,涉及出现的空值。
祝您工作顺利! 自己解决这个问题真是太好了.. :-)
V
(代表OP张贴) 。
我更改了printChildren()方法以也打印出父节点,并意识到我正在将父节点本身分配为自己的子节点(例如:n成为n的子节点)。 在其他情况下,我完全跳过了节点。 发生这种情况是因为我在for循环中使用了i变量。
下面的代码已解决了该问题,并且正是我想要的。 这是一个骇人听闻的,微不足道的骇客,但是当我回去重构它时,我会想出如何使它更整洁的方法。 解决方案来自linkLeftTree()和linkRightTree()方法。 我意识到我不应该为叶子分配子节点,因此在两种情况下我都减少了循环遍历的节点数量,并使用计数器分配了子节点。
public void linkLeftTree() {
int counter = 2;
int counter2 = 3;
// link the left, or first half, of the array
for (int i = 1; i < 8; i++) {
alphaTree[i].setLeft(alphaTree[(counter++)]);
alphaTree[i].setRight(alphaTree[(counter2++)]);
if (counter <= 13) {
counter++;
counter2++;
}
}
}
public void linkRightTree() {
int counter = 16;
int counter2 = 17;
// link the right, or second half, of the array
for (int i = 16; i < (24); i++) {
alphaTree[i].setLeft(alphaTree[(counter++)]);
alphaTree[i].setRight(alphaTree[(counter2++)]);
if (counter < 29) {
counter++;
counter2++;
}
}
}
我的递归搜索和打印也按预期工作,并且编写程序几乎完成了。 现在开始清理它的过程。 感谢所有花时间研究此问题的人!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.