forked from begeekmyfriend/leetcode
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Construct binary tree from order traversal
Signed-off-by: Leo Ma <[email protected]>
- Loading branch information
1 parent
466fade
commit 88cf82c
Showing
4 changed files
with
398 additions
and
0 deletions.
There are no files selected for viewing
2 changes: 2 additions & 0 deletions
2
105_construct_binary_tree_from_preorder_and_inorder_traversal/Makefile
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
all: | ||
gcc -O2 -o test binary_tree_build.c |
199 changes: 199 additions & 0 deletions
199
105_construct_binary_tree_from_preorder_and_inorder_traversal/binary_tree_build.c
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
|
||
struct hlist_node; | ||
|
||
struct hlist_head { | ||
struct hlist_node *first; | ||
}; | ||
|
||
struct hlist_node { | ||
struct hlist_node *next, **pprev; | ||
}; | ||
|
||
static inline void INIT_HLIST_HEAD(struct hlist_head *h) { | ||
h->first = NULL; | ||
} | ||
|
||
static inline void INIT_HLIST_NODE(struct hlist_node *n) { | ||
n->next = NULL; | ||
n->pprev = NULL; | ||
} | ||
|
||
static inline int hlist_empty(struct hlist_head *h) { | ||
return !h->first; | ||
} | ||
|
||
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) | ||
{ | ||
if (h->first != NULL) { | ||
h->first->pprev = &n->next; | ||
} | ||
n->next = h->first; | ||
n->pprev = &h->first; | ||
h->first = n; | ||
} | ||
|
||
static inline void hlist_del(struct hlist_node *n) | ||
{ | ||
struct hlist_node *next = n->next; | ||
struct hlist_node **pprev = n->pprev; | ||
*pprev = next; | ||
if (next != NULL) { | ||
next->pprev = pprev; | ||
} | ||
} | ||
|
||
#define container_of(ptr, type, member) \ | ||
((type *)((char *)(ptr) - (size_t)&(((type *)0)->member))) | ||
|
||
#define list_entry(ptr, type, member) \ | ||
container_of(ptr, type, member) | ||
|
||
#define hlist_for_each(pos, head) \ | ||
for (pos = (head)->first; pos; pos = pos->next) | ||
|
||
struct TreeNode { | ||
int val; | ||
struct TreeNode *left; | ||
struct TreeNode *right; | ||
}; | ||
|
||
struct order_node { | ||
struct hlist_node node; | ||
int val; | ||
int index; | ||
}; | ||
|
||
static int find(int num, int size, struct hlist_head *heads) | ||
{ | ||
struct hlist_node *p; | ||
int hash = (num < 0 ? -num : num) % size; | ||
hlist_for_each(p, &heads[hash]) { | ||
struct order_node *on = list_entry(p, struct order_node, node); | ||
if (num == on->val) { | ||
return on->index; | ||
} | ||
} | ||
return -1; | ||
} | ||
|
||
static struct TreeNode *node_new(int val) | ||
{ | ||
struct TreeNode *tn = malloc(sizeof(*tn)); | ||
tn->val = val; | ||
tn->left = NULL; | ||
tn->right = NULL; | ||
return tn; | ||
} | ||
|
||
static struct TreeNode *recursive(int *preorder, int pre_low, int pre_high, | ||
int *inorder, int in_low, int in_high, | ||
struct hlist_head *in_heads, int size) | ||
{ | ||
if (in_low > in_high || pre_low > pre_high) { | ||
return NULL; | ||
} | ||
struct TreeNode *tn = malloc(sizeof(*tn)); | ||
tn->val = preorder[pre_low]; | ||
int index = find(preorder[pre_low], size, in_heads); | ||
tn->left = recursive(preorder, pre_low + 1, pre_low + (index - in_low), inorder, in_low, index - 1, in_heads, size); | ||
tn->right = recursive(preorder, pre_high - (in_high - index - 1), pre_high, inorder, index + 1, in_high, in_heads, size); | ||
return tn; | ||
} | ||
|
||
static void node_add(int val, int index, int size, struct hlist_head *heads) | ||
{ | ||
struct order_node *on = malloc(sizeof(*on)); | ||
on->val = val; | ||
on->index = index; | ||
int hash = (val < 0 ? -val : val) % size; | ||
hlist_add_head(&on->node, &heads[hash]); | ||
} | ||
|
||
static struct TreeNode *buildTree(int *preorder, int preorderSize, int *inorder, int inorderSize) | ||
{ | ||
int i, j; | ||
struct hlist_head *in_heads = malloc(inorderSize * sizeof(*in_heads)); | ||
for (i = 0; i < inorderSize; i++) { | ||
INIT_HLIST_HEAD(&in_heads[i]); | ||
} | ||
for (i = 0; i < inorderSize; i++) { | ||
node_add(inorder[i], i, inorderSize, in_heads); | ||
} | ||
|
||
#if 0 | ||
struct hlist_head *pre_heads = malloc(preorderSize * sizeof(*pre_heads)); | ||
for (i = 0; i < preorderSize; i++) { | ||
INIT_HLIST_HEAD(&pre_heads[i]); | ||
} | ||
for (i = 0; i < inorderSize; i++) { | ||
node_add(preorder[i], i, preorderSize, pre_heads); | ||
} | ||
|
||
int last_index, level = 0; | ||
struct TreeNode **stack = malloc(preorderSize * sizeof(*stack)); | ||
struct TreeNode *tn, *root = NULL; | ||
for (i = 0; i < preorderSize; i++) { | ||
if (i == 0) { | ||
tn = root = node_new(preorder[0]); | ||
last_index = find(preorder[0], inorderSize, in_heads); | ||
stack[level++] = root; | ||
} else { | ||
int index = find(preorder[i], inorderSize, in_heads); | ||
if (index < last_index) { | ||
tn->left = node_new(preorder[i]); | ||
tn = tn->left; | ||
} else { | ||
for (j = index - 1; j >= 0; j--) { | ||
if (find(inorder[j], preorderSize, pre_heads) < i) { | ||
break; | ||
} | ||
} | ||
/* find the parent of the right child */ | ||
while (stack[--level]->val != inorder[j]) {} | ||
tn = stack[level++]; | ||
tn->right = node_new(preorder[i]); | ||
tn = tn->right; | ||
} | ||
stack[level++] = tn; | ||
last_index = index; | ||
} | ||
} | ||
|
||
return root; | ||
#else | ||
return recursive(preorder, 0, preorderSize - 1, inorder, 0, inorderSize - 1, in_heads, inorderSize); | ||
#endif | ||
} | ||
|
||
static void dump(struct TreeNode *node) | ||
{ | ||
if (node == NULL) { | ||
printf("# "); | ||
return; | ||
} | ||
printf("%d ", node->val); | ||
dump(node->left); | ||
dump(node->right); | ||
} | ||
|
||
int main(void) | ||
{ | ||
//int preorder[] = { 8,4,2,1,3,6,5,7,12,10,9,11,14,13,15 }; | ||
//int inorder[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }; | ||
int preorder[] = { 7,-10,-4,3,-1,2,-8,11 }; | ||
int inorder[] = { -4,-10,3,-1,7,11,-8,2 }; | ||
//int preorder[] = { 3,2,1 }; | ||
//int preorder[] = { 3,1,2 }; | ||
//int preorder[] = { 2,1,3 }; | ||
//int preorder[] = { 1,3,2 }; | ||
//int preorder[] = { 1,2,3 }; | ||
//int inorder[] = { 1,2,3 }; | ||
int pre_size = sizeof(preorder) / sizeof(*preorder); | ||
int in_size = sizeof(inorder) / sizeof(*inorder); | ||
struct TreeNode *root = buildTree(preorder, pre_size, inorder, in_size); | ||
dump(root); | ||
printf("\n"); | ||
return 0; | ||
} |
2 changes: 2 additions & 0 deletions
2
106_construct_binary_tree_from_inorder_and_postorder_traversal/Makefile
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
all: | ||
gcc -O2 -o test binary_tree_build.c |
Oops, something went wrong.