Created
October 11, 2013 21:50
-
-
Save munificent/6942575 to your computer and use it in GitHub Desktop.
My solution to http://cslibrary.stanford.edu/109/TreeListRecursion.html. I think mine is more efficient than Nick's.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is a Dart solution to: | |
// | |
// Nick Parlante's "Great Tree-List Recursion Problem" | |
// http://cslibrary.stanford.edu/109/TreeListRecursion.html | |
// | |
// Before you read the code here, try to solve it youself first! | |
main() { | |
var tree = makeTree(100); | |
printTree(tree); | |
var list = treeToList(tree); | |
printList(list); | |
} | |
// Here's the solution: | |
class Node { | |
final int data; | |
Node left; | |
Node right; | |
Node(this.data); | |
} | |
/// Convert [tree] to a linked list and return the head node. | |
Node treeToList(Node tree) { | |
var previous; | |
var last; | |
// Traverse the tree in order, and replace every left pointer to its previous | |
// one instead of its child. (We can't do the right pointers here because | |
// we haven't traversed those yet.) | |
inOrder(tree, (node) { | |
last = node; | |
node.left = previous; | |
previous = node; | |
}); | |
// Now walk the list along the previous chain and wire up the next pointers. | |
while (previous.left != null) { | |
previous.left.right = previous; | |
previous = previous.left; | |
} | |
// Make the list circular. | |
previous.left = last; | |
last.right = previous; | |
// Since we walked back to the beginning, this is now the head. | |
return previous; | |
} | |
/// Invoke [callback] on each node in [tree], in order. | |
void inOrder(Node tree, callback) { | |
if (tree.left != null) inOrder(tree.left, callback); | |
callback(tree); | |
if (tree.right != null) inOrder(tree.right, callback); | |
} | |
// Scaffolding: | |
Node makeTree(int numNodes) { | |
var nums = new Iterable.generate(numNodes, (i) => i).toList(); | |
nums.shuffle(); | |
var root = new Node(nums[0]); | |
for (var n in nums.skip(1)) { | |
insertInTree(root, n); | |
} | |
return root; | |
} | |
void insertInTree(Node tree, int n) { | |
if (n < tree.data) { | |
if (tree.left == null) { | |
tree.left = new Node(n); | |
} else { | |
insertInTree(tree.left, n); | |
} | |
} else { | |
if (tree.right == null) { | |
tree.right = new Node(n); | |
} else { | |
insertInTree(tree.right, n); | |
} | |
} | |
} | |
void printTree(Node tree, [String indent = ""]) { | |
if (tree.left != null) printTree(tree.left, indent + " "); | |
print("$indent${tree.data}"); | |
if (tree.right != null) printTree(tree.right, indent + " "); | |
} | |
void printList(Node head) { | |
var node = head; | |
do { | |
print("${node.left.data} <- ${node.data} -> ${node.right.data}"); | |
node = node.right; | |
} while (node != head); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment