我正在编写一个转换为摩尔斯电码的程序,反之亦然。我使用树来更有效地搜索代码或相关值。Morse 和相关值从文件读入静态数组。索引 0 是所有其他子树的根,实际上是一个连接到左子树 (index[1]) 和右子树 (index[16]) 的虚拟节点。
读入节点后,我通过遍历静态数组并在执行过程中分配节点来链接子节点。索引 [2] - [16] 保存左子树。索引 [17] - (alphaTree.length - 1) 持有右子树。
这是我的问题:在尝试分配所有子节点时,其中一些在我打印出来时为空。节点本身不是空的,只是子节点。
我注意到一个模式,但不知道如何修复它。
下面是示例输出。输出很大,所以我把它剪掉了,但留得足够多,这样你就可以明白我的意思了:
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() 中的设置器上使用 System.out.println(),我在循环中看不到空值,但当我实际尝试访问子节点时仍然有空值(如例如预订搜索)。
(功劳归于功劳:本程序中实现的字母树是基于 Charles Petzold 在《代码》一书中优化的树。但这里所有的代码都是你写的。)