[英]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.