Created
October 12, 2015 12:10
-
-
Save zapstar/266eb5b16134b3cdfef4 to your computer and use it in GitHub Desktop.
Convert a binary search tree into a doubly linked list (left acts as prev, right acts as next)
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
| #include <stdexcept> | |
| #include <iostream> | |
| using namespace std; | |
| struct node { | |
| int val; | |
| struct node *left; | |
| struct node *right; | |
| }; | |
| void inorder(struct node *root) { | |
| if (!root) { | |
| return; | |
| } | |
| inorder(root->left); | |
| cout << root->val << " "; | |
| inorder(root->right); | |
| } | |
| void traverse_dll(struct node *start, struct node *end) { | |
| if(!start || !end ||start->left || end->right) { | |
| throw invalid_argument("Invalid doubly linked list passed"); | |
| } | |
| struct node *t; | |
| for(t = start; t != end; t = t->right) { | |
| cout << t->val << " "; | |
| } | |
| cout << t->val << endl; | |
| for(t = end; t != start; t = t->left) { | |
| cout << t->val << " "; | |
| } | |
| cout << t->val <<endl; | |
| } | |
| void convert(struct node *root, struct node **start, struct node **end) { | |
| if (!root || !start || !end) { | |
| // raise an exception if no root is found | |
| // or if other ptrs are bad | |
| throw invalid_argument("Invalid pointers passed"); | |
| } | |
| // convert left sub-tree into doubly linked list | |
| // start of left dll = left_start, end of dll = left_end | |
| struct node *left_start, *left_end; | |
| struct node *left_child = root->left; | |
| // if there's a left child | |
| if (left_child) { | |
| // recursively convert left child | |
| convert(left_child, &left_start, &left_end); | |
| // join left_end and root | |
| left_end->right = root; | |
| root->left = left_end; | |
| } else { | |
| // no left child, make root as left_start | |
| // Notice that we have no need to populate the left_end | |
| left_start = root; | |
| } | |
| // similarly for right child... | |
| struct node *right_start, *right_end; | |
| struct node *right_child = root->right; | |
| //if there's a right child | |
| if (right_child) { | |
| // recurisvely convert right child | |
| convert(right_child, &right_start, &right_end); | |
| // join root and right_start | |
| root->right = right_start; | |
| right_start->left = root; | |
| } else { | |
| // no right child, make root as right_end | |
| // notice that we have no need to populate | |
| // right_start in this case | |
| right_end = root; | |
| } | |
| // populate the start and end double pointers with | |
| // start and end of doubly linked lists... | |
| *start = left_start; | |
| *end = right_end; | |
| } | |
| int main() { | |
| // construct a bst [3 to 17] | |
| struct node lll = {3, nullptr, nullptr}; | |
| struct node llr = {5, nullptr, nullptr}; | |
| struct node lrl = {7, nullptr, nullptr}; | |
| struct node lrr = {9, nullptr, nullptr}; | |
| struct node rll = {11, nullptr, nullptr}; | |
| struct node rlr = {13, nullptr, nullptr}; | |
| struct node rrl = {15, nullptr, nullptr}; | |
| struct node rrr = {17, nullptr, nullptr}; | |
| struct node ll = {4, &lll, &llr}; | |
| struct node lr = {8, &lrl, &lrr}; | |
| struct node rl = {12, &rll, &rlr}; | |
| struct node rr = {16, &rrl, &rrr}; | |
| struct node l = {6, &ll, &lr}; | |
| struct node r = {14, &rl, &rr}; | |
| struct node root = {10, &l, &r}; | |
| // print inorder | |
| inorder(&root); cout << endl; | |
| // convert bst to dll | |
| struct node *start, *end; | |
| convert(&root, &start, &end); | |
| // print doubly linked list | |
| traverse_dll(start, end); | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Output in Ideone: http://ideone.com/EAIJPH