I'm trying to write a Huffman-tree decode function to decode a given Boolean array.I'm using the recursion method in the decode_helper() but I keep getting caught in an infinite loop, and I'm not sure as to why because I thought I implemented a proper base case to stop the recursive calls.
I've tried playing around with different base cases but nothing that I try seems to stop the recursive calls.
public class HuffmanTree {
public class HuffmanTree {
// ******************** Start of Stub Code ******************** //
// ************************************************************ //
/** Node<E> is an inner class and it is abstract.
* There will be two kinds
* of Node, one for leaves and one for internal nodes. */
abstract static class Node implements Comparable<Node>{
/** The frequency of all the items below this node */
protected int frequency;
public Node(int freq) {
this.frequency = freq;
}
/** Needed for the Minimum Heap used later in this stub. */
public int compareTo(Node other) {
return this.frequency - other.frequency;
}
}
/** Leaves of a Huffman tree contain the data items */
protected static class LeafNode extends Node {
// Data Fields
/** The data in the node */
protected char data;
/** Constructor to create a leaf node (i.e. no children) */
public LeafNode(char data, int freq) {
super(freq);
this.data = data;
}
/** toString method */
public String toString() {
return "[value= "+this.data + ",freq= "+frequency+"]";
}
}
/** Internal nodes contain no data,
* just references to left and right subtrees */
protected static class InternalNode extends Node {
/** A reference to the left child */
protected Node left;
/** A reference to the right child */
protected Node right;
/** Constructor to create an internal node */
public InternalNode(Node leftC, Node rightC) {
super(leftC.frequency + rightC.frequency);
left = leftC; right = rightC;
}
public String toString() {
return "(freq= "+frequency+")";
}
}
// Enough space to encode all "extended ascii" values
// This size is probably overkill (since many of the values are not
//"printable" in the usual sense)
private static final int codex_size = 256;
/* Data Fields for Huffman Tree */
private Node root;
public HuffmanTree(String s) {
root = buildHuffmanTree(s);
}
/**
* Returns the frequencies of all characters in s.
* #param s
* #return
*/
//How many times a character shows up in a string
public static int[] frequency(String s) {
int[] freq = new int[codex_size];
for (char c: s.toCharArray()) {
freq[c]++;
}
return freq;
}
public String decode(boolean[] coding) {
// TODO Complete decode method
//Function to decode the binary input
String code = "";
Node temp = root;
int i = 0;
if (coding.length == 0) {
throw new IllegalArgumentException("The given code cannot be empty");
}
for(int j = 0; j < coding.length; j++) {
if(coding[j] != true && coding[j] != false) {
throw new IllegalArgumentException("The given code has an invalid
input");
}
}
decode_helper(temp, code, coding);
return code;
}
public void decode_helper(Node root, String code, boolean[] coding) {
int i = 0;
if(root == null) {
throw new IllegalArgumentException("Given tree is empty");
}
//Base case for the recursion
if(i != coding.length) {
if (root instanceof InternalNode) {
InternalNode n = (InternalNode)root;
if(coding[i] == false) {
n.left = (InternalNode)root;
i++;
decode_helper(n.left, code, coding);
}
if(coding[i] == true) {
n.right = (InternalNode)root;
i++;
decode_helper(n.right, code, coding);
}
}
else if (root instanceof LeafNode) {
LeafNode l = (LeafNode)root;
code += l.data;
i++;
decode_helper(root, code, coding);
}
}
}
The issue is because you are initializing int i = 0 within the decode_helper method. And that method is called recursively. Since i is always initialized to zero, it would never become equal to coding.length and hence the infinite loop.
You might need to initialize i outside the decode_helper method and pass it inside it.
Related
I am trying to create a binary tree that takes strings but it uses "-" and "+" to go left or right if the sign is + insert left and if it's - then insert right. Here is a visual representation of what I am trying to do.
insert method should take the word and just a single sign for now and based of that insert right or left
Here is my code but I am getting nullpointer error. Apparently, I am not inserting into the right order
public class BinaryTree {
private static Node root = null;
private static Node sign = null;
public static void main(String[] args) {
// TODO Auto-generated method stub
BinaryTree bt = new BinaryTree();
bt.insert("to", "-");
bt.insert("the", "+");
bt.preorder();
}
private class Node {
String data;
String sign;
Node left;
Node right;
public Node(String w) {
data = w;
left = right = null;
}
// public Node(String w, String s) {
// data = w;
// sign = s;
// left = right = null;
//
// }
} // -----------------end of Node
private void insert(String val, String sign) {
root = insert(root, val, sign);
}
Node insert(Node r, String data, String passSign) {
if (r == null) {
return new Node(data);
}
if(r.sign.equals(passSign)) {
r.right = insert(r.right, data, passSign);
}
else if (r.sign.equals(passSign)){
r.left = insert(r.left, data, passSign);
}
return r;
}
public void preorder() {
preorder(root);
}
public void preorder(Node p) {
if (p != null) {
System.out.println(p.data);
preorder(p.left);
preorder(p.right);
}
}
}
The main problems are:
The BinaryTree nor the Node instances should have a sign member. The sign only plays a role during the insertion process, but has no meaning any more once a node is inserted
r.sign.equals(passSign) is therefore also not the correct condition to check. According to your description you should just check whether the sign is a "-" and go right, or else go left ("+"). There is no state of the node that influences this decision. So do passSign.charAt(0) == '-' instead.
When making the recursive call you should not pass the same sign again: it has already been processed. Instead, pass any signs that follow after the consumed one. You can use substring for that purpose.
The image shows a root node that has no value. Yet you are right in creating a tree instance with no node at all. So your insert method should deal with the case where the root is null, but the sign argument is not the empty string. In that case a root node should be created, but it should not hold the target data, as for that we should still go deeper in the tree. This principle could apply to any node, not only the root. So foresee the creation of such "place-holder" nodes and give them some default value (like "(null)").
Not a problem, but I find it more useful to print in inorder order, and indent the deeper nodes. This way you get an idea how the tree is structured.
Here is the corrected code:
public class BinaryTree {
private static Node root = null;
// No sign member needed;
public static void main(String[] args) {
BinaryTree bt = new BinaryTree();
bt.insert("to", "-");
bt.insert("the", "+");
bt.insert("buy", "-+");
bt.insert("imperial", "+-");
bt.insert("afflication", "++");
bt.inorder();
}
private class Node {
String data;
// No sign member needed;
Node left;
Node right;
public Node(String w) {
data = w;
left = right = null;
}
}
private void insert(String val, String sign) {
root = insert(root, val, sign);
}
Node insert(Node r, String data, String passSign) {
// Check whether there is a sign
if (passSign.length() == 0) {
return new Node(data);
}
// If needed, create a placeholder node so to be able to descend further
if (r == null) {
r = new Node("(null)");
}
if (passSign.charAt(0) == '-') {
// Extract the rest of the signs
r.right = insert(r.right, data, passSign.substring(1, passSign.length()));
}
else {
r.left = insert(r.left, data, passSign.substring(1, passSign.length()));
}
return r;
}
public void inorder() {
inorder(root, "");
}
// This method gives a bit more visual output
public void inorder(Node p, String indent) {
if (p != null) {
inorder(p.left, indent + " ");
System.out.println(indent + p.data);
inorder(p.right, indent + " ");
}
}
}
This question already has answers here:
What causes "Can't find Symbol" and how to fix it?
(5 answers)
Closed 5 years ago.
I can't seem to make my program that implements a Binary Search Tree (using User input) and search for a value, to print out the number of iterations that were necessary to actually find this value.
I've created a method called 'getLastIterationCount()' that returns the number of iterations but when I want to print it out in my main method, I get an error on the line 'System.out.println(getLastIterationCount());'. I think that my method is not in the right place but I'm not sure whats missing. Any ideas how I could make this program work?
/* Class Node */
class Node
{
Node left, right;
int data;
/* Constructor */
public Node(int n)
{
left = null;
right = null;
data = n;
}
/* Function to get data from node */
public int getData()
{
return data;
}
/* Function to get left node */
public Node getLeft()
{
return left;
}
/* Function to get right node */
public Node getRight()
{
return right;
}
}
/* Class BST */
class BST
{
private Node root;
private int iterations;
/* Constructor */
public BST()
{
root = null;
}
/* Functions to insert data */
public void insert(int data)
{
root = insert(root, data);
}
/* Function to insert data recursively */
private Node insert(Node node, int data)
{
if (node == null)
node = new Node(data);
else
{
if (data <= node.data)
node.left = insert(node.left, data);
else
node.right = insert(node.right, data);
}
return node;
}
/* Functions to search for an element */
public boolean search(int val)
{
iterations=0;
iterations++;
return search(root, val);
}
/* Function to search for an element recursively */
private boolean search(Node r, int val)
{
iterations=0;
boolean found = false;
while ((r != null) && !found)
{
int rval = r.getData();
if (val < rval){
r = r.getLeft();
}
else if (val > rval){
r = r.getRight();
}
else
{
found = true;
break;
}
found = search(r, val);
}
return found;
}
public int getLastIterationCount(){
return iterations;
}
}
/* Class LinkedListBST */
public class LinkedListBST
{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
/* Creating object of BST */
BST bst = new BST();
System.out.println("Linked List Binary Search Tree Test\n");
char ch;
/* Accept input */
do
{
System.out.println("Enter integer element to insert");
bst.insert( scan.nextInt() );
System.out.println("\nDo you want to continue (Type y or n) \n");
ch = scan.next().charAt(0);
} while (ch == 'Y'|| ch == 'y');
System.out.println("\nEnter an element to be searched: ");
Scanner sc = new Scanner(System.in);
System.out.println("Search result : " + bst.search(sc.nextInt()));
System.out.println(getLastIterationCount()); //ISSUE IS HERE
sc.close();
}
}
You are accessing the method getLastIterationCount()without the object. Please call it using bst.getLastIterationCount()
You should call the method using the object bst that you have instantiated as below :
bst.getLastIterationCount();
I think your search code is already close to being correct. First, initialize the counter at the external entry point to search:
public boolean search(int val) {
iterations = 1;
return search(root, val);
}
Then, at each call to the private internal search method, increment the counter by one:
private boolean search(Node r, int val) {
++iterations; // increment counter by one for current iteration
boolean found = false;
while ((r != null) && !found) {
int rval = r.getData();
if (val < rval){
r = r.getLeft();
}
else if (val > rval) {
r = r.getRight();
}
else {
found = true;
break;
}
found = search(r, val);
}
return found;
}
I have assumed here that you want the number of recursive calls necessary to find the value. If instead you wanted the height at which an item was found, it is a different question.
Edit:
I noticed that you have a getter method for returning the count. It is an instance method and you should therefore call it as such:
bst.getLastIterationCount()
I'm attempting to write a pre-order traversal algorithm on a binary tree using the recursive method. Here's what I have:
void traverse(BT t) {
if (t == null){
return;
}
System.out.print(t);
traverse(t.left);
traverse(t.right);
}
That doesn't compile for some reason. I think the problem is with the rest of my code. Here's the entire code:
class ZOrep extends TreeAndRepresentation {
private int k;
ZOrep left;
ZOrep right;
ZOrep( int m, int[] b ) { // given sequence build tree
super( m, b );
N = (M-1)/2;
k = -1;
t = build();
}
ZOrep( int n, BT t ) { // given tree build sequence
super(n, t);
t = build();
traverse( t );
}
BT build() {
return(a[++k] == 0 ? null : new BT( build(), build() ));
}
void traverse(BT t) {
if (t == null){
return;
}
System.out.print(t);
traverse(t.left);
traverse(t.right);
}
}
I feel like I'm missing something when I'm building the tree (with my ZOrep method). Also here's the BT class:
class BT {
BT L; BT R;
BT( BT l, BT r ) { L = l; R = r; }
}
Currently my compiler says it can't find the symbol for t.left and t.right.
When the compiler says it can't find the symbol, it means the field you're trying to reference doesn't exist.
Looking at your class BT, this is correct; BT doesn't have left or right, it has L and R. Thus, replacing
traverse(t.left);
traverse(t.right);
with
traverse(t.L);
traverse(t.R);
Will fix this issue.
Currently my compiler says it can't find the symbol for t.left and t.right.
This is because t is a BT and it doesn't have a left and a right.
I suggest you decide what you want to call your tree node class. Is it ZOrep or BT and only use one of these or you will create confusion.
System.out.print(t);
If you want to print out a BT, you will need to add a toString() method to it as the default won't tell you anything useful.
What are you passing into your transverse function? If it's a BT object, then you can't use left and right, you must use L and R. Left and right are parts of your object that extends from BT, but it looks like you're passing in a BT.
// Java
static String tree = "";
private static void preOrder(HuffTree currentObject) {
if (currentObject == null) {
return;
}
if (currentObject.filling == null) tree += 1;
else tree += 0;
preOrder(currentObject.child0);
preOrder(currentObject.child1);
}
}
// class code here
import java.util.Objects;
/**
Huffman tree as class
*/
class HuffTree implements Comparable {
// element filling
Byte filling;
// element repeats
int repeats;
// zero child
HuffTree child0;
// child 1
HuffTree child1;
/**
* constructor for tree fathers and leaves
*/
public HuffTree(Byte filling, int repeats, HuffTree child0, HuffTree child1) {
// father filling
this.filling = filling;
// father repeats
this.repeats = repeats;
// zero child
this.child0 = child0;
// child 1
this.child1 = child1;
}
/**
* finding difference between our tree's items
*/
#Override
public int compareTo(HuffTree currentByte) {
return currentByte.repeats - repeats;
}
/**
* take byte code as a string by recursive three search in depth
*/
public String getCodeForByte(Byte currentByte, String wayToFather) {
// there is 4 cases:
if (!Objects.equals(filling, currentByte)) {
// case 1 - zero child found
if (child0 != null) {
// recursive code add for zero child
String currentWay = child0.getCodeForByte(currentByte, wayToFather + "0");
// return temporary string
if (currentWay != null) return currentWay;
}
// case 2 - child 1 found. recursive code add for child 1. return temporary string
if (child1 != null) return child1.getCodeForByte(currentByte, wayToFather + "1");
}
// case 3 - correct leaf found. return correct code
if (Objects.equals(filling, currentByte)) return wayToFather;
// case 4 - wrong leaf found. return null
return null;
}
}
I have spent entire weekend playing around with this. I am trying to store the nodes in PriorityQueue data structure. My astar function doesnt seem to be doing what it should. Anyone mind having a look?
public void aStar(Node from, Node to) {
PriorityQueue<Node> exploreList = new PriorityQueue<Node>();
ArrayList<Node> visited = new ArrayList<Node>();
ArrayList<Node> successors = new ArrayList<Node>();
Node current = from;
System.out.println(current.getName());
while (current != to) {
successors = current.getConnected();
Collections.sort(successors);
for (Node n : successors) {
if (!visited.contains(n)) {
exploreList.add(n);
}
for (Node n1 : successors) {
if (n.fSum() > n1.fSum()) {
exploreList.remove(n);
exploreList.add(n1);
}
}
}
visited.add(current);
current = exploreList.remove();
System.out.println(current.getName());
}
Node Class here
public class Node implements Comparable {
private String name;
private int travDist;
private int straightDist;
private ArrayList<Arc> arcs;
/**
* Constructor for a new node
*
* #param n
*/
public Node(String n, int aTravDist, int aStraightDist) {
name = n;
travDist = aTravDist;
straightDist = aStraightDist;
arcs = new ArrayList<Arc>();
}
/**
* Adds a new arc
*
* #param to
* #param c
*/
public void addArc(Node to, int c) {
arcs.add(new Arc(to, c));
}
/**
* Gets the list of connected nodes to this node
*
* #return
*/
public ArrayList<Node> getConnected() {
ArrayList<Node> returnData = new ArrayList<Node>();
for (Arc a : arcs) {
returnData.add(a.getNode());
}
return returnData;
}
#Override
public int compareTo(Object o) {
//return name.compareTo(((Node) o).getName());
Integer sum = ((Node)o).fSum();
return sum.compareTo(fSum());
}
public int fSum () {
return travDist + straightDist;
}
/**
* Gets the name of the Node
*
* #return
*/
public String getName() {
return name;
}
}
What you are doing is not a proper A star algorithm.
Collections.sort(successors);
You shouldn't do that. In A star you always consider all the successors. You needn't worry about the order- the priority queue will take care of that. However, adding this line increases the complexity of the algorithm.
for (Node n1 : successors) {
if (n.fSum() > n1.fSum()) {
exploreList.remove(n);
exploreList.add(n1);
}
}
This is entirely wrong. What you are doing here is: you only add the closest of all the successors. This will be a beam search with a beam of size 1, not A star - just keep them all in.
I've been trying to write a recursive string method for a binary search tree that returns a multiple line representation of a tree with preorder path info.
Each node should be prefaced by a series of < and > characters showing the path that leads from the root to that node. I'm not sure how to use a string prefix parameter that is extended by one character with each successive call.
The method should be able reproduce this example:
Tree:
15
/ \
12 18
/ / \
10 16 20
\ \
11 17
Expected Print Output:
15
<12
<<10
<<>11
>18
><16
><>17
>>20
I'm new to recursion and so far my actual print output isn't close enough after hours of messing with the code:
18
<17
<10
>15
<11
>12
16
20
Here's my tree node class that works properly:
/**
* A single binary tree node.
* <p>
* Each node has both a left or right child, which can be null.
*/
public class TreeNode<E> {
private E data;
private TreeNode<E> left;
private TreeNode<E> right;
/**
* Constructs a new node with the given data and references to the
* given left and right nodes.
*/
public TreeNode(E data, TreeNode<E> left, TreeNode<E> right) {
this.data = data;
this.left = left;
this.right = right;
}
/**
* Constructs a new node containing the given data.
* Its left and right references will be set to null.
*/
public TreeNode(E data) {
this(data, null, null);
}
/** Returns the item currently stored in this node. */
public E getData() {
return data;
}
/** Overwrites the item stored in this Node with the given data item. */
public void setData(E data) {
this.data = data;
}
/**
* Returns this Node's left child.
* If there is no left left, returns null.
*/
public TreeNode<E> getLeft() {
return left;
}
/** Causes this Node to point to the given left child Node. */
public void setLeft(TreeNode<E> left) {
this.left = left;
}
/**
* Returns this nodes right child.
* If there is no right child, returns null.
*/
public TreeNode<E> getRight() {
return right;
}
/** Causes this Node to point to the given right child Node. */
public void setRight(TreeNode<E> right) {
this.right = right;
}
}
Here's my binary search tree class with the toFullString() method near the bottom:
import java.util.*;
/**
* A binary search tree (BST) is a sorted ADT that uses a binary
* tree to keep all elements in sorted order. If the tree is
* balanced, performance is very good: O(n lg n) for most operations.
* If unbalanced, it performs more like a linked list: O(n).
*/
public class BinarySearchTree<E extends Comparable<E>> {
private TreeNode<E> root = null;
private int size = 0;
/** Creates an empty tree. */
public BinarySearchTree() {
}
public BinarySearchTree(Collection<E> col) {
List<E> list = new ArrayList<E>(col);
Collections.shuffle(list);
for (int i = 0; i < list.size() ; i++) {
add(list.get(i));
}
}
/** Adds the given item to this BST. */
public void add(E item) {
this.size++;
if (this.root == null) {
//tree is empty, so just add item
this.root = new TreeNode<E>(item);
}else {
//find where to insert, with pointer to parent node
TreeNode<E> parent = null;
TreeNode<E> curr = this.root;
boolean wentLeft = true;
while (curr != null) { //will execute at least once
parent = curr;
if (item.compareTo(curr.getData()) <= 0) {
curr = curr.getLeft();
wentLeft = true;
}else {
curr = curr.getRight();
wentLeft = false;
}
}
//now add new node on appropriate side of parent
curr = new TreeNode<E>(item);
if (wentLeft) {
parent.setLeft(curr);
}else {
parent.setRight(curr);
}
}
}
/** Returns the greatest (earliest right-most node) of the given tree. */
private E findMax(TreeNode<E> n) {
if (n == null) {
return null;
}else if (n.getRight() == null) {
//can't go right any more, so this is max value
return n.getData();
}else {
return findMax(n.getRight());
}
}
/**
* Returns item from tree that is equivalent (according to compareTo)
* to the given item. If item is not in tree, returns null.
*/
public E get(E item) {
return get(item, this.root);
}
/** Finds it in the subtree rooted at the given node. */
private E get(E item, TreeNode<E> node) {
if (node == null) {
return null;
}else if (item.compareTo(node.getData()) < 0) {
return get(item, node.getLeft());
}else if (item.compareTo(node.getData()) > 0) {
return get(item, node.getRight());
}else {
//found it!
return node.getData();
}
}
/**
* Removes the first equivalent item found in the tree.
* If item does not exist to be removed, throws IllegalArgumentException().
*/
public void remove(E item) {
this.root = remove(item, this.root);
}
private TreeNode<E> remove(E item, TreeNode<E> node) {
if (node == null) {
//didn't find item
throw new IllegalArgumentException(item + " not found in tree.");
}else if (item.compareTo(node.getData()) < 0) {
//go to left, saving resulting changes made to left tree
node.setLeft(remove(item, node.getLeft()));
return node;
}else if (item.compareTo(node.getData()) > 0) {
//go to right, saving any resulting changes
node.setRight(remove(item, node.getRight()));
return node;
}else {
//found node to be removed!
if (node.getLeft() == null && node.getRight() == null) {
//leaf node
return null;
}else if (node.getRight() == null) {
//has only a left child
return node.getLeft();
}else if (node.getLeft() == null) {
//has only a right child
return node.getRight();
}else {
//two children, so replace the contents of this node with max of left tree
E max = findMax(node.getLeft()); //get max value
node.setLeft(remove(max, node.getLeft())); //and remove its node from tree
node.setData(max);
return node;
}
}
}
/** Returns the number of elements currently in this BST. */
public int size() {
return this.size;
}
/**
* Returns a single-line representation of this BST's contents.
* Specifically, this is a comma-separated list of all elements in their
* natural Comparable ordering. The list is surrounded by [] characters.
*/
#Override
public String toString() {
return "[" + toString(this.root) + "]";
}
private String toString(TreeNode<E> n) {
//would have been simpler to use Iterator... but not implemented yet.
if (n == null) {
return "";
}else {
String str = "";
str += toString(n.getLeft());
if (!str.isEmpty()) {
str += ", ";
}
str += n.getData();
if (n.getRight() != null) {
str += ", ";
str += toString(n.getRight());
}
return str;
}
}
public String toFullString() {
StringBuilder sb = new StringBuilder();
toFullString(root, sb);
return sb.toString();
}
/**
* Preorder traversal of the tree that builds a string representation
* in the given StringBuilder.
* #param n root of subtree to be traversed
* #param sb StringBuilder in which to create a string representation
*/
private void toFullString(TreeNode<E> n, StringBuilder sb)
{
if (n == null)
{
return;
}
sb.append(n.getData().toString());
sb.append("\n");
if (n.getLeft() != null) {
sb.append("<");
} else if (n.getRight() != null) {
sb.append(">");
}
if (n.getLeft() != null || n.getRight() != null)
{
toFullString(n.getLeft(), sb);
toFullString(n.getRight(), sb);
}
}
/**
* Tests the BST.
*/
public static void main(String[] args) {
Collection collection = new ArrayList();
collection.add(15);
collection.add(12);
collection.add(18);
collection.add(10);
collection.add(16);
collection.add(20);
collection.add(11);
collection.add(17);
BinarySearchTree bst = new BinarySearchTree(collection);
//System.out.println(bst);
String temp = bst.toFullString();
System.out.println(temp);
}
}
Any help with the recursive toFullString method will be greatly appreciated.
There are two levels you need to think about when designing a recursive solution.
How do I deal with the current item in the recursion?
How do I go from this item to the next one, and what information gets passed on?
Since we are printing out each item in the tree, there is going to be a single print statement inside of each recursive call. However, the string printed in each row includes information about previous steps that were traversed to reach the current node. How do we deal with this information? It needs to be passed down from previous recursive calls to the next one.
Here is a set of possible rules:
If the current item is a leaf, print out the current result.
If the current item has a left node, add <, and recursively act on the left node.
If the current item has a right node, add >, and recursively act on the right node.
What do we add < and > to? We need a parameter to carry along the current previous steps that have occurred in the recursion from recursive call to call. You don't want to simply print out < and > as you traverse the tree, because you need to remember the current set of steps to print out the prefix to every single node. There could be a second helper method that takes the same parameters as the original toFullString(), but a custom third parameter to carry the current set of previous steps.
So the logic might look something like this:
If there is no current prefix, initialize prefix to "", since the root initially has no steps to reach it.
If the current node is a leaf, add a line of output with the current prefix + leaf value.
If the current node has a left node, recursively call toFullString() on the left node, and add < to the current prefix string, which is handed down.
If the current node has a right node, recursively call toFullString() on the right node, and add > to the current prefix string, which is handed down.