问题
My goal is to create a Binary Search Tree (BST) from a given string, using a preorder traversal. Eventually, I will use the BST to decode a binary message using Huffman encoding/decoding. My question/issue pertains to setting up the tree itself. (I already figured out how to decode the message after the set up.)
Here is an example of what I'm trying to accomplish. (NOTE: This was provided in the assignment we were given.
String: ^a^^!^dc^rb
Here is what the tree should look like:
My issue comes with setting up the tree and using it in the other methods I have. I want to be able to use the root of the tree in the other methods, but every time I would use it, it would give me a null value.
Here is my code:
public class MsgTree {
public char payloadChar;
public MsgTree left;
public MsgTree right;
public MsgTree root;
public String encodingString;
private static int staticCharIdx = 0; //Need static char idx in the tree string for recursive solution
public MsgTree(String encodingString) { //Constructor building the tree from a string
this.encodingString = encodingString;
for(staticCharIdx = 0; staticCharIdx < encodingString.length(); staticCharIdx++) { //The for loop loops through every character in the string one char at a time
char charToTest = encodingString.charAt(staticCharIdx); //The program creates a charToTest variable to use for creating the new MsgTree node.
MsgTree newNode = new MsgTree(charToTest); //A new MsgTree node is created for every new char in the encodingString. It does this by calling the second MsgTree constructor
if(staticCharIdx == 0) {
root = newNode;
}
preOrderTraversal(newNode); //The program then calls a private function to perform a preOrder traversal of the tree
}
}
public MsgTree(char payloadChar) { //Constructor for a single node with null children
left = null; //This method assigns two children (left and right) to the char node and sets them both to null
right = null;
this.payloadChar = payloadChar; //A payloadChar value is utilized to avoid naming conflicts and for use in other methods
}
private void preOrderTraversal(MsgTree newNode) { //This method performs a preOrder traversal of the string and creates it into a BST
if(newNode == null) { //If the newNode taken from the constructor is null, then nothing happens. This happens when it is past the last char of the string.
return;
}
System.out.printf("%s", newNode.payloadChar); //Prints the char value of the NewNode
preOrderTraversal(newNode.left); //Calls the same method, but focuses instead on the left child of the newNode
preOrderTraversal(newNode.right); //Calls the same method, but focuses instead on the right child of the newNode
}
public static void printCodes(MsgTree root, String code) { //method to print characters and their binary codes
//DOES THE PRINTING HERE
}
public void decode(MsgTree codes, String msg) { //Prints the decoded message to the console
//DOES THE DECODING HERE
}
public static void main(String args[]) throws FileNotFoundException { //Main method putting the tree and message into two separate strings and implementing the above methods
String treeString = "^a^^!^dc^rb";
String messageString = "10100101010110110111100";
MsgTree newTree = new MsgTree(treeString); //A new tree is created using the new tree string derived from the arch file
String code = "";
System.out.println();
System.out.println("character code");
System.out.println("-------------------------");
newTree.printCodes(root, code); //WHY CANT I CALL IT HERE? IT GIVES ME A NULL VALUE
newTree.decode(root, messageString); //I ALSO CAN'T USE IT HERE
}
Attempting to use the root value or the BST in any method besides where it was created will give me a null value. I've tried using "newTree.root" or "MsgTree.root" but that doesn't work.
I would appreciate any help with this. Thank you.
回答1:
You never assign anything other than null
to left
and right
, so you aren't actually building a tree.
It looks like the input string has a recursive definition:
- If the character is
'^'
then the node payload is empty (or'^'
),left
is the node that we get from parsing the string starting at the next character, andright
is the node we get by parsing the string starting at the next character after whatever we read forleft
. - Otherwise, the node payload is the character, and
left
andright
arenull
.
You have the right idea with staticCharIdx
. This is how you keep track of the "next character." But you don't want to loop through the whole string in the MsgTree
constructor. And if staticCharIdx
is going to be static, might as well make encodingString
static too, and make a static tree-building method something like this:
public static MsgTree build(String encodingString) {
MsgTree.encodingString = encodingString;
staticCharIdx = 0;
return buildNextMsgTree();
}
The function buildNextMsgTree
implements the two cases above, in the first case recursively calling itself to create the left and right nodes.
private static MsgTree buildNextMessageTree() {
char c = encodingString.charAt(staticCharIdx++);
MsgTree tree = new MsgTree(c);
if (c == '^') {
tree.left = buildNextMessageTree();
tree.right = buildNextMessageTree();
}
return tree;
}
You'll have to adjust the MsgTree
constructor to accept the payload.
来源:https://stackoverflow.com/questions/62744092/did-i-set-up-this-bst-correctly-if-so-how-can-i-use-it-in-other-methods