Author |
Topic: CS: BST TO LL (Read 1698 times) |
|
Jonathan_the_Red
Junior Member
Gender:
Posts: 102
|
|
CS: BST TO LL
« on: Aug 30th, 2002, 3:22pm » |
Quote Modify
|
What a cute little problem! It takes some thinking, but once you get it, the solution is nice and elegant. I think I'm gonna add this one to my interview repertoire. The problem isn't quite clear on how the "output parameters" first and last are supposed to work... the way I did it, the caller creates a couple of dummy nodes for head and tail pointers and passes them in. Like so: struct node First, Last; bst2ll(root, &First, &Last); // at this point, First.right points to the first node in the linked list, while Last.left points to the last. void bst2ll(struct node *root, struct node *first, struct node *last) { if (root->left) { bst2ll(root->left, first, root); } else { root->left = first; first->right = root; } if (root->right) { bst2ll(root->right, root, last); } else { root->right = last; last->left = root; } } Edit: hidden by color. Others might want to do this without a spoiler.
|
« Last Edit: Aug 30th, 2002, 3:24pm by Jonathan_the_Red » |
IP Logged |
My arcade cabinet
|
|
|
Jeremiah Smith
Full Member
Beep!
Posts: 172
|
|
Re: CS: BST TO LL
« Reply #1 on: Aug 30th, 2002, 9:10pm » |
Quote Modify
|
I had to do something like this once, in my CS class.
|
|
IP Logged |
|
|
|
TimMann
Senior Riddler
Gender:
Posts: 330
|
|
Re: CS: BST TO LL
« Reply #2 on: Sep 1st, 2002, 1:11am » |
Quote Modify
|
Extension: Can you do the same thing in constant space? (The given solution is recursive, which of course makes it take call stack space proportional to the depth of the tree.) If so, how; if not, why not?
|
|
IP Logged |
http://tim-mann.org/
|
|
|
TimMann
Senior Riddler
Gender:
Posts: 330
|
|
Re: CS: BST TO LL
« Reply #3 on: Sep 9th, 2002, 10:53pm » |
Quote Modify
|
Here's a nonrecursive, constant space solution. It's not nearly as pretty as the recursive solution. The code is untested, so let me know if you notice errors. Don't bother letting me know that "goto" is considered harmful. :-) Anyone know why I can't get YaBB to do the indentation right in "pre" format? It eats the first few spaces when a line starts with 7 or 8. struct node First, Last; bst2ll(root, &First, &Last); // at this point, First.right points to the first node in the linked list, // while Last.left points to the last. void bst2ll(struct node *root, struct node *first, struct node *last) { struct node *above, *cur, *below; first->left = NULL; first->right = last; last->left = first; last->right = NULL; above = NULL; cur = root; /* Try to go down to the left */ down_left: if (cur == NULL) return; below = cur->left; cur->left = above; // save how to get back up if (below) { above = cur; cur = below; goto down_left; } down_right: above = cur->left; // recall how to get back up below = cur->right; // save how to go down to the right /* Add cur to the list */ cur->left = last->left; last->left = cur; cur->left->right = cur; cur->right = last; /* Try to go down to the right */ /* We leave "above" alone because we don't want to return to cur anymore -- it's been removed from the tree and placed in the list. Instead, we want to return to the nearest ancestor of cur whose right child we haven't yet checked. This is "above". */ if (below) { cur = below; goto down_left; } /* Go back up */ cur = above; goto down_right; }
|
|
IP Logged |
http://tim-mann.org/
|
|
|
Grimbal
wu::riddles Moderator Uberpuzzler
Gender:
Posts: 7527
|
|
Re: CS: BST TO LL
« Reply #4 on: May 30th, 2004, 1:28pm » |
Quote Modify
|
on Sep 1st, 2002, 1:11am, TimMann wrote:Extension: Can you do the same thing in constant space? (The given solution is recursive, which of course makes it take call stack space proportional to the depth of the tree.) If so, how; if not, why not? |
| Here is a solution. I changed the type for first of last to the more logical pointer-to-pointer. void bst2ll(struct node *root, struct node **first, struct node **last) { // hidden code struct node *prev, *curr, *tmp; *first = *last = NULL; curr = root; prev = NULL; while( curr ){ while( (tmp = curr->left) ){ curr->left = tmp->right; tmp->right = curr; curr = tmp; } if( !prev ) *first = curr; curr->left = prev; prev = curr; curr = curr->right; } while( curr ); *last = curr; } It is O(n) because the code in the inner while increments the length of the right edge of the tree, i.e. the list of nodes reachable following the 'right' pointers.
|
« Last Edit: May 30th, 2004, 1:29pm by Grimbal » |
IP Logged |
|
|
|
|