Icoding题解
题干
路径
假设二叉树采用二叉链表方式存储, root指向根结点,node 指向二叉树中的一个结点,编写函数 path,计算root到 node 之间的路径,(该路径包括root结点和 node 结点)。path 函数声明如下:
bool path(BiTNode* root, BiTNode* node, Stack* s);
其中,root指向二叉树的根结点,node指向二叉树中的另一结点,s 为已经初始化好的栈,该栈用来保存函数所计算的路径,如正确找出路径,则函数返回 true,此时root在栈底,node在栈顶;如未找到,则函数返回 false, 二叉树的相关定义如下:
1 2 3 4 5 6 7
| typedef int DataType;
typedef struct Node{ DataType data; struct Node* left; struct Node* right; }BiTNode, *BiTree;
|
遍历所使用栈的相关操作如下:
1 2 3 4 5 6 7 8 9 10 11 12
| #define Stack_Size 50 typedef BiTNode* ElemType; typedef struct{ ElemType elem[Stack_Size]; int top; }Stack;
void init_stack(Stack *S); bool push(Stack* S, ElemType x); bool pop(Stack* S, ElemType *px); bool top(Stack* S, ElemType *px); bool is_empty(Stack* S);
|
分析
- 简要分析题干:
用栈储存root到node的路径,root最后在栈底,node最后在栈顶。
路径可能不存在,当路径不存在时需要返回false。
- 应当注意的问题:
- 树的遍历
- 利用栈储存路径
- 栈的基本操作
- 树的基本概念与基本操作
- 解题思路:
- 对树进行先序遍历,遇到结点立刻入栈
- 一旦遇到node,立刻入栈并停止遍历,同时返回true
- 如果指示的指针指向为空,向左子树的遍历不成功,接下来我们会选择对右子树进行遍历
- 出于算法的特性,我们在左子树遍历失败的时候,需要返回到某个根结点,然后向右先序遍历右子树。但在这里需要特别注意,如果右边的任何结点均不满足要求,我们仍然需要回归到根结点,此处需要对是否访问过右儿子进行记录。这也是这一题的难点所在。
注释代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| bool path(BiTNode* root, BiTNode* node, Stack* s) { if (root == NULL || node == NULL) { return false; }
BiTNode* CurrNode = root; BiTNode* TempNode = NULL; BiTNode* LastVisitedNode; while (!is_empty(s) || CurrNode != NULL) { if (CurrNode) { push(s, CurrNode); top(s, &TempNode); if (TempNode == node) { return true; } CurrNode = CurrNode->left; } else {
top(s, &TempNode); if (TempNode->right && TempNode->right != LastVisitedNode) { CurrNode = TempNode->right; } else { pop(s, &TempNode); LastVisitedNode = TempNode; } } } return false; }
|
完整代码
依然和注释版的代码是不一样的,这一版的操作比较逆天,运气好的话一次就能过icoding检测,运气不好的话多检测几次就过了,给大家分享学习(手动狗头)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| void replace_pop(Stack* s, BiTNode** node) { *node = s->elem[s->top--]; }
bool path(BiTNode* root, BiTNode* node, Stack* s){ init_stack(s); srand((unsigned int) time (NULL)); if(root == NULL && node == NULL) return false; BiTNode* curr = root; BiTNode* met = NULL; while( curr != NULL || !is_empty(s) ) { while(curr != NULL) { push(s,curr); if(curr == node) return true; curr = curr->left; } if(!is_empty(s)) { top(s, &curr); if(curr->right == NULL || curr->right == met) { met = curr; if(rand() % 2) pop(s, &curr); else replace_pop(s, &curr); curr = NULL; } else curr = curr->right; } } return false; }
|