7 Chapter 7 Solutions¶
Solution to Challenge 1¶
A straightforward way to print the nodes in level-order is to leverage the level-order traversal using a Queue
data structure. The tricky bit is determining when a newline should occur. For that it would be useful to know the number of elements in the queue. The queues you made in the last chapter don’t have a length
property, but you can add one now.
Open your QueueStack
implementation and add the following line:
int get length => _leftStack.length + _rightStack.length;
You implemented the double-stack queue using two lists, so finding the length is still an O(1) operation. This would not be true if you used the linked-list implementation.
Now you’re ready to deal with the challenge:
void printEachLevel<T>(TreeNode<T> tree) {
final result = StringBuffer();
// 1
var queue = QueueStack<TreeNode<T>>();
var nodesLeftInCurrentLevel = 0;
queue.enqueue(tree);
// 2
while (!queue.isEmpty) {
// 3
nodesLeftInCurrentLevel = queue.length;
// 4
while (nodesLeftInCurrentLevel > 0) {
final node = queue.dequeue();
if (node == null) break;
result.write('${node.value} ');
for (var element in node.children) {
queue.enqueue(element);
}
nodesLeftInCurrentLevel -= 1;
}
// 5
result.write('\n');
}
print(result);
}
- You begin by initializing a
Queue
data structure to facilitate the level-order traversal. You also createnodesLeftInCurrentLevel
to keep track of the number of nodes you’ll need to work on before you print a new line. - Your level-order traversal continues until your queue is empty.
- Inside the first
while
loop, you begin by settingnodesLeftInCurrentLevel
to the number of current elements in the queue. - Using another
while
loop, you dequeue the firstnodesLeftInCurrentLevel
number of elements from the queue. Every element you dequeue is added toresult
without establishing a new line. You also enqueue all the children of the node. - At this point, you append a newline to
result
. In the next iteration,nodesLeftInCurrentLevel
will be updated with the count of the queue, representing the number of children from the previous iteration.
This algorithm has a time complexity of O(n). Since you initialize the Queue
data structure as an intermediary container, this algorithm also uses O(n) space.
Solution to Challenge 2¶
When building a UI widget tree it’s easier if you can pass the children in as parameters in the constructor. Here is one version of what the nodes could look like:
class Widget {}
class Column extends Widget {
Column({this.children});
List<Widget>? children;
}
class Padding extends Widget {
Padding({this.value = 0.0, this.child});
double value;
Widget? child;
}
class Text extends Widget {
Text([this.value = '']);
String value;
}
Now you can easily build a Flutter-like widget tree:
final tree = Column(
children: [
Padding(
value: 8.0,
child: Text('This'),
),
Padding(
value: 8.0,
child: Text('is'),
),
Column(
children: [
Text('my'),
Text('widget'),
Text('tree!'),
],
),
],
);