0

I have a binary tree node like this:

class BinaryTreeNode<T> {
  BinaryTreeNode(this.value, {this.leftChild, this.rightChild});
  T value;
  BinaryTreeNode? leftChild;
  BinaryTreeNode? rightChild;
}

I'd like to add a toString method so that I can have a visual representation of the contents of the binary tree.

This is a Dart version of this Java question. I was able to port one of the answers there so I am adding it below.

Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393

1 Answers1

4

Here is a modified version of this answer:

class BinaryTreeNode<T> {
  BinaryTreeNode(this.value, {this.leftChild, this.rightChild});
  T value;
  BinaryTreeNode<T>? leftChild;
  BinaryTreeNode<T>? rightChild;

  @override
  String toString() {
    final out = StringBuffer();

    rightChild?._buildTree(out, true, '');
    out.writeln(value);
    leftChild?._buildTree(out, false, '');

    return out.toString();
  }

  void _buildTree(StringBuffer out, bool isRight, String indent) {
    rightChild?._buildTree(out, true, indent + (isRight ? '     ' : '│    '));

    out
      ..write(indent)
      ..write(isRight ? '┌─── ' : '└─── ')
      ..writeln(value);

    leftChild?._buildTree(out, false, indent + (isRight ? '│    ' : '     '));
  }
}

If you build a tree like so:

void main() {
  final tree = BinaryTreeNode('D',
      leftChild: BinaryTreeNode('A'),
      rightChild: BinaryTreeNode(
        'R',
        leftChild: BinaryTreeNode('T'),
        rightChild: BinaryTreeNode('Fun'),
      ));
  print(tree);
}

The output looks like this:

     ┌─── Fun
┌─── R
│    └─── T
D
└─── A

Feel free to modify my answer to simply the code. I feel like the toString method could be simplified to not repeat so much code.

Suggested solution from lrn

The following solution is more efficient since we are avoiding creating intermediate string objects as we go though the tree structure. Thanks to lrn for suggesting this approach:

class BinaryTreeNode<T> {
  BinaryTreeNode(this.value, {this.leftChild, this.rightChild});

  T value;
  BinaryTreeNode<T>? leftChild;
  BinaryTreeNode<T>? rightChild;

  @override
  String toString() {
    final out = StringBuffer();

    final indents = <String>[];
    rightChild?._buildTree(out, true, indents);
    out.writeln(value);
    leftChild?._buildTree(out, false, indents);

    return out.toString();
  }

  void _buildTree(StringBuffer out, bool isRight, List<String> indents) {
    if (rightChild != null) {
      indents.add(isRight ? '     ' : '│    ');
      rightChild!._buildTree(out, true, indents);
      indents.removeLast();
    }

    out
      ..writeAll(indents)
      ..write(isRight ? '┌─── ' : '└─── ')
      ..writeln(value);

    if (leftChild != null) {
      indents.add(isRight ? '│    ' : '     ');
      leftChild!._buildTree(out, false, indents);
      indents.removeLast();
    }
  }
}
lrn
  • 64,680
  • 7
  • 105
  • 121
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
  • Updated the solution with use of `writeln` (instead of `write('\n')` and `?.` operator instead of `if (value != null)`. Also added use of cascade operator (..). And at last, I thought it would make more sense to have `leftChild` and `rightChild` to follow the same generic as the parent (so `BinaryTreeNode` instead of `BinaryTreeNode`). See the last change as a personal artistic choice not really needed. :) – julemand101 Oct 25 '21 at 05:02
  • Made some minor adjustments to the layout so the first lines is not shifted by one to make it more consistent with the rest. I hope that is okay. :) – julemand101 Oct 25 '21 at 08:58
  • @julemand101, That's amazing! Learning from people like you is why I like posting public answers online. – Suragch Oct 25 '21 at 09:33
  • If you want to optimize for performance (who doesn't?!?), you could make `indent` a `List`, where you `add` the next layer before calling recursively, and remove it again with `removeLast` when coming back, and then adds all of the indents to the string buffer. That avoids creating intermediate string objects, but does add more individual strings to the `StringBuffer`. – lrn Oct 25 '21 at 13:50
  • 1
    @lrn Added your suggested solution. Please change it I have misunderstood your intention. :) – julemand101 Oct 25 '21 at 17:48
  • 1
    Perfect. Only changed it to use `StringBuffer.writeAll` to write all the indents in one call. – lrn Oct 26 '21 at 09:22