描述
给定一个二叉树,返回它的中序 遍历。
示例:
1 2 3 4 5 6 7 8
| 输入: [1,null,2,3] 1 \ 2 / 3
输出: [1,3,2]
|
进阶: 递归算法很简单,你可以通过迭代算法完成吗?
来源:力扣(LeetCode)
链接:94. Binary Tree Inorder Traversal
解题思路
先来一波中规中矩的递归的中序遍历,所谓中序遍历,其遍历的顺序是左子节点->根节点->右子节点,中的意思是将根节点放在中间的位置进行遍历。用递归实现的代码在大部分的基础数据结构书籍当中都会有介绍,换到本题,在具体求解时,有几个注意点:
- 返回的指针空间初始需要分配得稍微大一点
* returnSize指针变量要放在辅助的遍历函数当中实时修改
具体实现代码见解法一。
除了递归,也可以借助栈用迭代来实现二叉树的中序遍历。利用栈的先进后出的特性,从根节点开始,先将根节点入栈,然后用一个循环将它的所有左子节点入栈,然后取出栈顶元素并保存到需要返回的指针变量当中,再将当前指针移动其右子节点上,若存在右子节点,则在下次循环时又可以将其所有的左子节点入栈。
这样可以保证了访问顺序是是左子节点->根节点->右子节点,具体实现代码见解法二和解法三,分别为C版本和采用STL的C版本。其中C不需要处理*returnSize变量,代码会简洁不少。
下面再介绍一种即不使用栈也不递归的二叉树遍历方法,有个专门的名字叫Morris Traversal,需要借助一种新型的数据结构,叫做Threaded binary tree,其主要步骤如下:
- 将当前节点
current初始化为根节点
- 当当前节点不为空时,进入循环
- 若
current没有左子节点
- 将
current添加到返回结果指针
- 将指针移动到其右子节点,即
current = current->right
- 否则,
current有左子节点
- 将
pre 指针指向 current 的左子树中的最右子节点
- 如果
pre不存在右子节点
- 将其右子节点指回
current
current指向其左子节点
- 反之
- 将
pre的右子节点置空
- 将
current添加到返回结果指针
- 将指针移动到其右子节点,即
current = current->right
具体代码实现见解法四,另外,同样的Morris Traversal,在current有左子节点时的具体处理不同,还有另外一种解法,具体步骤如下:
初始二叉树状态:
1 2 3 4 5 6 7
| X / \ / \ Y Z / \ / \ A B C D
|
首先,X 是根节点,所以将 current 初始化为 X。X 有左子节点,然后将 X 放到 X 左子树的最右节点,这时 X 成为 B 的右孩子,然后将 current 设到 Y。 新的树看起来是这样的:
1 2 3 4 5 6 7 8 9
| Y / \ A B \ X / \ (Y) Z / \ C D
|
上图的(Y)代表原来的Y及其所有的孩子节点。现在树有一个链接链回原来的 X,然后遍历继续:
1 2 3 4 5 6 7 8 9 10 11
| A \ Y / \ (A) B \ X / \ (Y) Z / \ C D
|
此时A已经没有左孩子节点了,然后current回到了Y,在上一步迭代当中被设置为A的右子节点。current回到了Y,这也意味着它的左子树已经遍历完毕了,然后开始输出current,从A、Y、B、X、一直到Z,这时current是Z,剩下的树,即X为根节点时的右子树,如下所示,可以以相同的模式重复以上过程。
具体代码见解法五,实现上面更为简洁。
代码
解法一
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
|
int inorder(struct TreeNode* root, int *result, int* returnSize) { if(root) { inorder(root->left, result, returnSize);
result[(*returnSize)++] = root->val;
inorder(root->right, result, returnSize);
} return 0; }
int* inorderTraversal(struct TreeNode* root, int* returnSize){ int *result = (int *)malloc(100 * sizeof(int)); *returnSize = 0;
inorder(root, result, returnSize);
return result; }
|
解法二
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
|
#define MAXSIZE 100
int* inorderTraversal(struct TreeNode* root, int* returnSize) { int *result = (int*)malloc(sizeof(int) * MAXSIZE); int *stack[MAXSIZE]; int top = -1; struct TreeNode *p = root; *returnSize = 0; while (p != NULL || top != -1) { while (p != NULL) { stack[++top] = p; p = p->left; } p = stack[top--]; result[(*returnSize)++] = p->val; p = p->right; } return result; }
|
解法三
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
|
class Solution { public: vector<int> inorderTraversal(TreeNode *root) { vector<int> result; stack<TreeNode*> s; TreeNode *p = root; while (p || !s.empty()) { while (p) { s.push(p); p = p->left; } p = s.top(); s.pop(); result.push_back(p->val); p = p->right; } return result; } };
|
解法四
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 53 54 55 56 57 58 59
|
#define MAXSIZE 100
int* inorderTraversal(struct TreeNode* root, int* returnSize) { int *result = (int*)malloc(sizeof(int) * MAXSIZE); *returnSize = 0;
if(!root) return result; struct TreeNode *current, *pre; current = root; while(current) { if(!current->left) { result[(*returnSize)++] = current->val; current = current->right; } else { pre = current->left; while(pre->right && pre->right != current) pre = pre->right; if(!pre->right) { pre->right = current; current = current->left; } else { pre->right = NULL; result[(*returnSize)++] = current->val; current = current->right; } } } return result; }
|
解法五
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
|
#define MAXSIZE 100
int* inorderTraversal(struct TreeNode* root, int* returnSize) { int *result = (int*)malloc(sizeof(int) * MAXSIZE); *returnSize = 0;
if(!root) return result; struct TreeNode *current, *pre, *tmp; current = root; while(current) { if(!current->left) { result[(*returnSize)++] = current->val; current = current->right; } else { pre = current->left; while(pre->right) pre = pre->right; pre->right = current; tmp = current; current = current->left; tmp->left = NULL; } } return result; }
|
参考