二叉树中和为某一值的路

题意描述:输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。如:
        10
        /    \
      5    12
    /   \

  4    7

解题思路:借助栈,进行深度优先遍历,如果当前结点为叶子结点并且从根结点到当前结点的值的和等于给定值,则找到一条路径并打印,否则继续向叶结点遍历或者返回上一级,返回上一级时需要在当前计算的和的基础上减去当前结点的值

(C++版本)

struct BinaryTreeNode {
	int m_nValue;
	BinaryTreeNode* m_pLeft;
	BinaryTreeNode* m_pRight;
};

//创建二叉树结点
BinaryTreeNode* CreateBinaryTreeNode(int value) {
	BinaryTreeNode* pNode = new BinaryTreeNode();
	pNode->m_nValue = value;
	pNode->m_pLeft = NULL;
	pNode->m_pRight = NULL;
	return pNode;
}

//连接二叉树结点
void ConnectionTreeNodes(BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight) {
	if (pParent != NULL) {
		pParent->m_pLeft = pLeft;
		pParent->m_pRight = pRight;
	}
}


void findPath(BinaryTreeNode* pRoot, int expectedSum, vector<int>& path, int currentSum) {
	currentSum += pRoot->m_nValue;
	path.push_back(pRoot->m_nValue);

	//如果是叶结点,并且路径上结点的和等于输入的值打印出这条路径
	bool isLeaf = (pRoot->m_pLeft == NULL) && (pRoot->m_pRight == NULL);
	
	if (isLeaf && (currentSum == expectedSum)) {
		cout << "A path is found: ";
		//vector<int>::iterator it = path.begin();
		//for (; it != path.end(); ++it)
		//	cout << *it << " ";
		for (vector<int>::size_type i = 0; i < path.size(); i++)
			cout << path[i] << " ";
		cout << endl;
	}

	//如果不是叶结点
	if (pRoot->m_pLeft != NULL)
		findPath(pRoot->m_pLeft, expectedSum, path, currentSum);
	if (pRoot->m_pRight != NULL)
		findPath(pRoot->m_pRight, expectedSum, path, currentSum);

	//在返回父结点之前,在路径上删除当前结点
	path.pop_back();
}

void findPath(BinaryTreeNode* pRoot, int expectedSum) {
	if (pRoot == NULL)
		return;

	vector<int> path;
	int currentSum = 0;
	findPath(pRoot, expectedSum, path, currentSum);
}


//先序遍历
void InOrder(BinaryTreeNode* pTreeRoot) {	
	if (pTreeRoot->m_pLeft != NULL)
		InOrder(pTreeRoot->m_pLeft);
	cout << pTreeRoot->m_nValue << " ";
	if (pTreeRoot->m_pRight != NULL)
		InOrder(pTreeRoot->m_pRight);
}

int main()
{
	BinaryTreeNode* node1 = CreateBinaryTreeNode(10);
	BinaryTreeNode* node2 = CreateBinaryTreeNode(5);
	BinaryTreeNode* node3 = CreateBinaryTreeNode(12);
	BinaryTreeNode* node4 = CreateBinaryTreeNode(4);
	BinaryTreeNode* node5 = CreateBinaryTreeNode(7);

	ConnectionTreeNodes(node1, node2, node3);
	ConnectionTreeNodes(node2, node4, node5);

	InOrder(node1);
	cout << endl;

	findPath(node1, 22);

    return 0;
}

(Java版本)

class BinaryTreeNode{
	int value;
	BinaryTreeNode leftNode;
	BinaryTreeNode rightNode;
}

public class FindPath {		
	
	//解题思路:借助栈,进行深度优先遍历,如果当前结点为叶子结点并且从根结点到当前结点的值的和等于给定值,则找到一条路径并打印
	//否则继续向叶结点遍历或者返回上一级,返回上一级时需要在当前计算的和的基础上减去当前结点的值
	public static void findPath(BinaryTreeNode root, int expectedSum){
		if(root == null)
			return;
		Stack<Integer> stack = new Stack<Integer>();
		int currentSum = 0;
		findPath(root, currentSum, stack, expectedSum);
	}
	public static void findPath(BinaryTreeNode root,int currentSum, Stack<Integer> path, int expectedSum){
		currentSum += root.value;
		path.add(root.value);
		
		//如果是叶结点,并且路径上结点的和等于输入的值则打印
		boolean isLeaf = (root.leftNode==null)&&(root.rightNode==null);
		if(isLeaf && (currentSum == expectedSum)){
			System.out.print("A path find: ");
			for(int n : path)
				System.out.print(n + " ");
			System.out.println();
		}
		
		//如果不是叶结点
		if(root.leftNode != null)
			findPath(root.leftNode, currentSum, path, expectedSum);
		if(root.rightNode != null)
			findPath(root.rightNode, currentSum, path, expectedSum);
			
		//在返回父结点之前把路径上的当前结点删除
		path.pop();
	}
	
	public static void main(String[] args) {
		BinaryTreeNode root = new BinaryTreeNode();
		BinaryTreeNode node1 = new BinaryTreeNode();
		BinaryTreeNode node2 = new BinaryTreeNode();
		BinaryTreeNode node3 = new BinaryTreeNode();
		BinaryTreeNode node4 = new BinaryTreeNode();
		
		root.leftNode = node1;
		root.rightNode = node2;
		node1.leftNode = node3;
		node1.rightNode = node4;
		
		root.value = 10;
		node1.value = 5;
		node2.value = 12;
		node3.value = 4;
		node4.value = 7;
		
		findPath(root, 22);
	}

}

(Golang版本)

package main

import (
	list2 "container/list"
	"fmt"
)

// 二叉树结构
type BTree struct {
	Val   int
	Left  *BTree
	Right *BTree
}

// 构建一棵二叉树
//      8
//    /   \
//   6     10
//  / \    / \
// 5   7  9   11
func newBTree() *BTree {
	node2_1 := &BTree{Val: 5}
	node2_2 := &BTree{Val: 7}
	node2_3 := &BTree{Val: 9}
	node2_4 := &BTree{Val: 11}
	node1_1 := &BTree{Val: 6, Left: node2_1, Right: node2_2}
	node1_2 := &BTree{Val: 10, Left: node2_3, Right: node2_4}
	root := &BTree{Val: 8, Left: node1_1, Right: node1_2}
	return root
}

/*
 * 求二叉树和为某值的所有路径
 */
func findPath(root *BTree, expSum int) {
	if root == nil {
		return
	}

	path := newStack()
	curSum := 0
	solution(root, curSum, expSum, path)
}
func solution(root *BTree, curSum, expSum int, path *myStack) {
	curSum += root.Val
	path.push(root)

	if root.Left == nil && root.Right == nil && curSum == expSum {
		for ele := path.List.Front(); ele != nil ; ele = ele.Next()  {
			node := ele.Value.(*BTree)
			fmt.Printf("%d\t", node.Val)
		}
		fmt.Println()
	}

	if root.Left != nil {
		solution(root.Left, curSum, expSum, path)
	}
	if root.Right != nil {
		solution(root.Right, curSum, expSum, path)
	}

	path.pop()
}

func main() {
	root := newBTree()
	findPath(root, 21)
}

/
// 自定义栈
type myStack struct {
	List *list2.List
}

func newStack() *myStack {
	stack := myStack{List: list2.New()}
	return &stack
}

func (stack *myStack) push(ele interface{}) {
	stack.List.PushBack(ele)
}

func (stack *myStack) pop() interface{} {
	if ele := stack.List.Back(); ele != nil {
		stack.List.Remove(ele)
		return ele.Value
	}
	return nil
}

func (stack *myStack) len() int {
	return stack.List.Len()
}


// 自定义队列
type myQueue struct {
	List *list2.List
}

func newQueue() *myQueue {
	queue := myQueue{List: list2.New()}
	return &queue
}

func (queue *myQueue) push(ele interface{}) {
	queue.List.PushBack(ele)
}

func (queue *myQueue) pop() interface{} {
	if ele := queue.List.Front(); ele != nil {
		queue.List.Remove(ele)
		return ele.Value
	}
	return nil
}

func (queue *myQueue) len() int {
	return queue.List.Len()
}

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值