题目
/* 二叉树中和为某一个值的路径:
输入一颗二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。
从树的根节点开始往下一直到叶节点的所有经过的节点形成一条路径。 */
思想:
借助栈,将从根开始往下的前序节点遍历,如果当前节点的值加上之前的节点的值得和是小于n时,将该值入栈,继续遍历;如果等于,则入栈,打印栈中所有元素,然后出栈该元素,继续往后面元素遍历;如果大于,往后继续遍历。
代码:
/* 二叉树中和为某一个值的路径:
输入一颗二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。
从树的根节点开始往下一直到叶节点的所有经过的节点形成一条路径。 */
/*这个实现好像还是有点问题..*/
void print_all_path_in_BST_sum_is_n(bstNode* root, int val)
{
stack* st1 = createStack();
bstNode* p = root;
int cur_sum = 0;
int right_tag = 0;
if(NULL == root)
{
return;
}
if(root->data > val)
{
return;
}
if(root->data == val)
{
printf("%d\n\n", root->data );
return;
}
push(st1, root);
cur_sum = root->data;
while( !StackIsEmpty(st1) )
{
p = GetTop(st1);
if( p->left != NULL && right_tag == 0)
{
if(p->left->data + cur_sum == val)
{
/*入栈,打印路径、出栈当前节点 */
push(st1, p->left);
cur_sum = cur_sum + p->left->data;
showData_from_base_to_top_bstnode(st1, val);
p = GetTop(st1);
cur_sum -= p->data;
pop(st1);
/* 找寻新的路径入口:*/
/*若栈顶元素是父的左孩子:从栈顶开始,当前路径上仅有左孩子的节点出栈,因为肯定不满足条件。到第一个有右孩子的节点,即是新路径的入口*/
p = GetTop(st1);
while( !StackIsEmpty(st1) && NULL != p->parent && p->parent->left == p && p->right == NULL )
{
cur_sum = cur_sum - p->data;
pop(st1);
p = GetTop(st1);
}
right_tag = 1;
/*若栈顶元素是父的右孩子:从栈顶开始,当前路径上连续是父的右孩子的节点出栈,因为肯定不满足条件。到第一个是父的左孩子的节点,该元素也要出栈,下一个元素,即是新路径的入口*/
if( !StackIsEmpty(st1) && NULL != p->parent && p->parent->right == p )
{
while(!StackIsEmpty(st1) && NULL != p->parent && p->parent->right == p)
{
cur_sum -= p->data;
pop(st1);
p = GetTop(st1);
}
if(!StackIsEmpty(st1))
{
cur_sum -= p->data;
pop(st1);
}
}
}
else if( p->left->data + cur_sum < val )
{
cur_sum += p->left->data;
push(st1, p->left);
right_tag = 0;
/*若当前入栈元素是叶子节点,则不满足条件,寻找新入口,同上面调整过程*/
p = GetTop(st1);
if( p->right == NULL && NULL == p->left )
{
p = GetTop(st1);
while( !StackIsEmpty(st1) && NULL != p->parent && p->parent->left == p && p->right == NULL)
{
cur_sum -= p->data;
pop(st1);
p = GetTop(st1);
}
right_tag = 1;
if( !StackIsEmpty(st1) && NULL != p->parent && p->parent->right == p )
{
while(!StackIsEmpty(st1) && NULL != p->parent && p->parent->right == p)
{
cur_sum -= p->data;
pop(st1);
p = GetTop(st1);
}
if(!StackIsEmpty(st1))
{
cur_sum -= p->data;
pop(st1);
}
}
}
}
else
{
/*出栈 栈顶元素,因为栈顶元素的左孩子不满足条件,则右孩子必然不满足条件,故出栈*/
p = GetTop(st1);
cur_sum = cur_sum - p->data;
pop(st1);
/* 寻找新入口 */
p = GetTop(st1);
while( !StackIsEmpty(st1) && NULL != p->parent && p->parent->left == p && p->right == NULL)
{
cur_sum -= p->data;
pop(st1);
p = GetTop(st1);
}
if(!StackIsEmpty(st1))
{
cur_sum -= p->data;
pop(st1);
}
right_tag = 1;
}
}
else
{
if(cur_sum + p->right->data == val)
{
push(st1, p->right );
cur_sum += p->right->data;
showData_from_base_to_top_bstnode(st1, val);
p = GetTop(st1);
while( !StackIsEmpty(st1) && NULL != p->parent && p->parent->right == p)
{
cur_sum -= p->data;
pop(st1);
p = GetTop(st1);
}
if(!StackIsEmpty(st1))
{
cur_sum -= p->data;
pop(st1);
}
right_tag = 1;
}
else if(cur_sum + p->right->data < val )
{
cur_sum += p->right->data;
push(st1, p->right);
right_tag = 0;
p = GetTop(st1);
if( p->right == NULL && NULL == p->left )
{
while( !StackIsEmpty(st1) && NULL != p->parent && p->parent->right == p)
{
cur_sum -= p->data;
pop(st1);
p = GetTop(st1);
}
if(p->parent == NULL)
{
pop(st1);
return;
}
cur_sum -= p->data;
if(!StackIsEmpty(st1) )
{
pop(st1);
}
right_tag = 1;
}
}
else
{
p = GetTop(st1);
cur_sum -= p->data;
pop(st1);
p = GetTop(st1);
while( !StackIsEmpty(st1) && NULL != p->parent && p->parent->right == p)
{
cur_sum -= p->data;
pop(st1);
p = GetTop(st1);
}
p = GetTop(st1);
if(root == p)
{
pop(st1);
return;
}
while(!StackIsEmpty(st1) && p->parent != NULL && p == p->parent->left)
{
cur_sum -= p->data;
pop(st1);
p = GetTop(st1);
}
right_tag = 1;
}
}
}
}
其实大致的解题思路比较简单,实现起来真的一点不简单>__< ,我写了一个下午。 主要是某一个路径往下走到一个位置不能再往下走,不满足小于n以后,需要弹出当前栈中的此条路径上的部分节点,然后进入新的路径,这是最复杂的地方,这种稍不留神就死循环了>>__<<(如果面试现场手写代码考这道题目,那简直是直接GG)
测试:
int main()
{
bstNode* root = Bst_BuyNode(10);
single_list_node* head = NULL, *head_pre = NULL, *head_post = NULL;
single_list_node* head_level = NULL;
root = Tree_Insert(root, 5);
root = Tree_Insert(root, 4);
root = Tree_Insert(root, 3);
root = Tree_Insert(root, 2);
root = Tree_Insert(root, 1);
root = Tree_Insert(root, 7);
root = Tree_Insert(root, 6);
root = Tree_Insert(root, 8);
root = Tree_Insert(root, 15);
printf("Inorder:\n");
Inorder_Tree_Walk(root);
#if 1
head = Inorder_Tree_Walk_stack(root);
SingleList_showdata_bst(head);
print_all_path_in_BST_sum_is_n(root,0);
print_all_path_in_BST_sum_is_n(root,10);
print_all_path_in_BST_sum_is_n(root,15);
print_all_path_in_BST_sum_is_n(root,19);
print_all_path_in_BST_sum_is_n(root,22);
print_all_path_in_BST_sum_is_n(root,24);
print_all_path_in_BST_sum_is_n(root,28);
print_all_path_in_BST_sum_is_n(root,25);
print_all_path_in_BST_sum_is_n(root,30);
print_all_path_in_BST_sum_is_n(root,100);
#endif
print_all_path_in_BST_sum_is_n(root,23);
print_all_path_in_BST_sum_is_n(root,18);
print_all_path_in_BST_sum_is_n(root,11);
print_all_path_in_BST_sum_is_n(root,29);
}
运行结果: