求 二叉树中和为某一个值的所有路径(非递归版本c语言实现)

题目


/* 二叉树中和为某一个值的路径:
输入一颗二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。
从树的根节点开始往下一直到叶节点的所有经过的节点形成一条路径。 */

思想:

借助栈,将从根开始往下的前序节点遍历,如果当前节点的值加上之前的节点的值得和是小于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);

}

 

运行结果:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值