簡體   English   中英

二叉樹:某些子節點為空,其他則不為

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM