在二元树中找出和为某一值的所有路径
晚上看到C、C++经典面试题由此题,一开始没有思路,开了其他人的分析(http://blog.csdn.net/dazhong159/article/details/7906916)有了思路,然后照着书上的代码一边看一边写,理解了思路后,在VS上几乎是背写出来的。有此也有所感触,有时候问题本事可能并不复杂,只是我们自己把它看的太难,太复杂,如果能真正静下心来试着理解并推理之的话,之中的乐趣便妙不可言,此时的自己仿佛也达到了一种“心流”状态,学习充实的感觉真的很好!(想起了网上郝斌老师说过的一句话,大意是有些(数据结构)算法真的很难,自己能理解了就已经不错了,自己实在想不出来,就参考下前人的思路,借鉴甚至背会别人的代码,以后你会慢慢理解的。。。)
好,闲话改天再叙。
题目要求:
输入一个整数和一棵二元树。从树的根结点开始往下访问一直到叶结点所经过的所有结点形成一条路径。打印出和与输入整数相等的所有路径。
例如输入整数 22 ,如下图二元树:
10
/ \
5 12
/ \
4 7
则打印出两条路径:10, 12和10, 5, 7。思路分析就见首行给出的链接,讲的很清楚,接下来贴下自己的代码,错误之处欢迎指正。
1 #include<malloc.h> 2 #include<stdio.h> 3 4 typedef struct node // 定义树节点 5 { 6 int data; 7 struct node *leftch; 8 struct node *rightch; 9 }BiNode, * PBiNode; 10 11 typedef struct path // 定义路径节点 12 { 13 PBiNode tree; 14 struct path *next; 15 }PATH, *pPath; 16 17 static int record = 0; 18 19 void init_path(pPath &L) // 初始化 20 { 21 pPath p = (pPath)malloc(sizeof(path)); 22 if(NULL == p) 23 { 24 printf("init_path malloc failure.\n"); 25 return ; 26 } 27 L = p; 28 p->next = NULL; 29 } 30 31 void find_path(PBiNode T, int sum, pPath L) //查找所有路径 32 { 33 push_path(L, T); //将该树节点入栈 34 record += T->data; 35 36 if((sum == record) && (IsLeftNode(T))) //递归+回溯 查找到合适路劲 37 { 38 print_path(L); // 打印相应的路径 39 printf("\n"); 40 } 41 42 if(NULL != T->leftch) //继续查找左子树 43 find_path(T->leftch, sum, L); 44 45 if(NULL != T->rightch) // 继续查找右子树 46 find_path(T->rightch, sum, L); 47 48 record -= T->data; //回溯 49 pop_path(L); 50 51 } 52 53 void push_path(pPath L, PBiNode T) //树节点 入栈 54 { 55 pPath p = L->next; 56 pPath q = L; 57 58 while(NULL != p) 59 { 60 q = p; 61 p = p->next; 62 } 63 p = (pPath)malloc(sizeof(PATH)); 64 if(NULL == p) 65 { 66 printf("push_path malloc failure.\n"); 67 } 68 p->tree = T; 69 p->next = NULL; 70 71 q->next = p; //树节点入栈 72 } 73 74 bool IsLeftNode(PBiNode T)//判断是否为叶子节点 75 { 76 if((NULL == T->leftch) && (NULL == T->rightch)) 77 return true; 78 else 79 return false; 80 } 81 82 void print_path(pPath L)//打印树节点 83 { 84 pPath p = L->next; 85 while(NULL != p) 86 { 87 printf("%d ", p->tree->data); 88 p = p->next; 89 } 90 } 91 92 93 void pop_path(pPath L) //树节点 出栈 94 { 95 pPath p = L->next; 96 pPath q = L; 97 98 if(NULL == p) 99 { 100 printf("pop_path stack is NULL!\n"); 101 return ; 102 } 103 p = p->next; 104 while(NULL != p) 105 { 106 p = p->next; 107 q = q->next; 108 } 109 free(q->next); // 树节点出栈 110 q->next = NULL; 111 } 112 113 114 int main(void) 115 { 116 117 PBiNode root; 118 CreateBiTree(root); 119 printf("PreOrderTraverse:"); 120 PreTraverse(root); 121 printf("\n"); 122 pPath L; 123 init_path(L); 124 find_path(root, 22, L); 125 126 return 0; 127 }
需要说明的一点是,主函数中采用的(前序遍历)递归创建二叉树,输入的时候,先为二叉树补充完整,然后按前序遍历顺序输入,如:
10
/ \
5 12
/ \ / \
4 7 0 0
/ \ / \
0 0 0 0
则输入是顺序为10 5 4 0 0 7 0 0 12 0 0 (中间空格隔开,然后enter键结束)。
以下是运行结果