二叉树中和为某一值的路径
题目:输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的全部路径。
路径定义为从树的根结点開始往下一直到叶结点所经过的结点形成一条路径。
比方:
上面这棵二叉树,假设寻找和为22的路径,那应该有两条。首先是10,5,7,另外一条是10,12.
思路:
能够依照先序遍历的方式訪问二叉树,这样能够确保根先于子树被訪问到,另外需准备一个栈(可用数组取代,由于须要打印路径),每訪问一个结点,就统计当前路径和以及当前结点是否是叶子结点,假设满足则打印,否则递归其左右子树,须要注意的是在返回到父节点时。须要将栈顶元素删除。
代码:
/* 二叉树中和为某一值的路径 by Rowandjj 2014/8/4 */ #include<stdio.h> #include<stdlib.h> #define MAX 1000 typedef struct _NODE_ { int data; struct _NODE_ *lChild; struct _NODE_ *rChild; }Node,*pNode,*pTree; void FindPath(pTree pT,int stack[],int exceptedNum,int curNum,int p) { curNum += pT->data;//路径和加上当前结点值 stack[p++] = pT->data;//把当前结点纳入stack中 bool isLeaf = (pT->lChild == NULL) && (pT->rChild == NULL);//是否为叶子结点 if((curNum == exceptedNum) && isLeaf)//当前为叶子节点并且路径和恰为期待值 { printf("found a path:"); for(int i = 0; i < p; i++)//打印路径 { printf("%d ",stack[i]); } printf("\n"); } if(pT->lChild)//假设有左孩子,那么递归遍历左子树 { FindPath(pT->lChild,stack,exceptedNum,curNum,p); } if(pT->rChild)//假设有右孩子 { FindPath(pT->rChild,stack,exceptedNum,curNum,p); } p--;//返回父节点前要将栈回退,pop出当前栈顶元素 } void FindPath(pTree pT,int exceptedNum) { int stack[1000];//使用数组模拟一个栈 if(pT == NULL) { return; } int curNum = 0;//当前路径和 int p = 0;//栈顶指针 FindPath(pT,stack,exceptedNum,curNum,p); } void create(pTree *ppTree) { int data; scanf("%d",&data); if(data == -1) { return; } *ppTree = (pNode)malloc(sizeof(Node)); if(*ppTree == NULL) { exit(-1); } (*ppTree)->data = data; (*ppTree)->lChild = NULL; (*ppTree)->rChild = NULL; create(&(*ppTree)->lChild); create(&(*ppTree)->rChild); } int main() { pTree pT = NULL; create(&pT); FindPath(pT,9); return 0; }
看OJ上这道题:
- 题目描写叙述:
-
输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的全部路径。路径定义为从树的根结点開始往下一直到叶结点所经过的结点形成一条路径。
- 输入:
-
每一个測试案例包含n+1行:
第一行为2个整数n,k(1<=n<=10000),n表示结点的个数。k表示要求的路径和。结点编号从1到n。
接下来有n行。
这n行中每行为3个整数vi,leftnode,rightnode,vi表示第i个结点的值。leftnode表示第i个结点的左孩子结点编号,rightnode表示第i个结点的右孩子结点编号,若无结点值为-1。
编号为1的结点为根结点。
- 输出:
-
相应每一个測试案例,先输出“result:”占一行。接下来按字典顺序输出满足条件的全部路径。这些路径由结点编号组成,输出格式參照输出例子。
- 例子输入:
-
5 2210 2 35 4 512 -1 -14 -1 -17 -1 -11 51 -1 -1
- 例子输出:
-
result:A path is found: 1 2 5A path is found: 1 3result:
注意两点: - 1.输出的是结点的序号。而不是结点值;
- 2.以字典顺序输出。
- 非常显然。我们应该使用数组来存储二叉树:
- 代码:
#include<stdio.h> #include<stdlib.h> #define MAX 100000 typedef struct _NODE_ { int data; int lChild; int rChild; int index; }Node,*pNode; void FindPath(pNode pTree,int exceptedNum,int curNum,int stack[],int p,int index) {//exceptedNum为期待路径和,curNum为当前路径和。stack为栈数组,p为栈顶指针。index为当前 树根的位置 if(pTree == NULL || index == -1) { return; } curNum += pTree[index].data; stack[p++] = pTree[index].index; bool isLeaf = (pTree[index].lChild == -1) && (pTree[index].rChild == -1); if(isLeaf && (curNum == exceptedNum)) { printf("A path is found:"); for(int i = 0; i < p; i++) { printf(" %d",stack[i]); } printf("\n"); } if(pTree[index].lChild < pTree[index].rChild) { FindPath(pTree,exceptedNum,curNum,stack,p,pTree[index].lChild); FindPath(pTree,exceptedNum,curNum,stack,p,pTree[index].rChild); }else { FindPath(pTree,exceptedNum,curNum,stack,p,pTree[index].rChild); FindPath(pTree,exceptedNum,curNum,stack,p,pTree[index].lChild); } p--; } void FindPath(pNode pTree,int exceptedNum) { if(pTree == NULL) { return; } int cutNum = 0; int p = 0; int stack[MAX]; int index = 0; FindPath(pTree,exceptedNum,cutNum,stack,p,index); } int main() { int n,k; while(scanf("%d %d",&n,&k) != EOF) { if(n <= 0) { continue; } pNode pTree = (pNode)malloc(sizeof(Node)*n); if(!pTree) { exit(-1); } for(int i = 0; i < n; i++) { int data,left,right; scanf("%d %d %d",&data,&left,&right); pTree[i].data = data; if(left != -1) { pTree[i].lChild = left-1; }else { pTree[i].lChild = -1; } if(right != -1) { pTree[i].rChild = right-1; }else { pTree[i].rChild = -1; } pTree[i].index = i+1; } printf("result:\n"); FindPath(pTree,k); free(pTree); } return 0; }