94. 二叉树的中序遍历
思路:想到了常规递归算法,但是官方解使用提供了三种解法。第一中是最容易理解的,递归;第二中,栈和迭代完成遍历并返回数据;第三中,用了一种特殊的树来完成,这个方法我觉得就没必要学了。
递归解法:
C代码
typedef struct TreeNode {
int val;
struct TreeNode* left;
struct TreeNode* right;
}TreeNode;
//get树的节点数
int getSize(struct TreeNode* root)
{
if (!root)
return 0;
return getSize(root->left) + getSize(root->right) + 1;
}
//中序遍历树,并将数据读入堆上分配的内存中
void inorderTree(struct TreeNode* root, int* res)
{
//静态变量具有记忆功能
static int index = 0;
if (!root)
return;
inorderTree(root->left, res);
res[index++] = root->val;
inorderTree(root->right, res);
}
//主体函数,上面2个函数是辅助函数
int* inorderTraversal(struct TreeNode* root, int* returnSize) {
*returnSize = getSize(root);
int* res = (int*)malloc(sizeof(int) * *returnSize);
if (*returnSize == 0)
{
return res;
}
inorderTree(root, res);
return res;
}
c++代码
class Solution {
public:
vector<int> res;
vector<int> inorderTraversal(TreeNode* root) {
if (!root)
return res;
inorderTraversal(root->left);
res.push_back(root->val);
inorderTraversal(root->right);
return res;
}
};
144. 二叉树的前序遍历
思路:
1.递归算法,简洁明了,简单易懂,不做解释。
2.迭代算法,基于对递归算法的观察得出,代码中有详细注释为总结。
递归算法:
C代码
typedef struct TreeNode {
int val;
struct TreeNode* left;
struct TreeNode* right;
}TreeNode;
int getSize(struct TreeNode* root)
{
if (!root) return 0;
return getSize(root->left) + getSize(root->right) + 1;
}
void preorder(struct TreeNode* root, int* res)
{
static int index = 0;
if (!res || !root) return;
res[index++] = root->val;
preorder(root->left, res);
preorder(root->right, res);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
*returnSize = getSize(root);
int* res = (int*)malloc(sizeof(int) * (*returnSize));
if (*returnSize == 0) return res;
//递归的先序遍历tree,并依次访问节点。
preorder(root, res);
return res;
}
c++代码
class Solution {
public:
vector<int> res;
vector<int> preorderTraversal(TreeNode* root) {
if(!root)
return res;
res.push_back(root->val);
//以下为递归调用,任何一次递归调用执行具有实质效果的代码都是上面的代码,这就如同迭代
//任何一次迭代都将执行相同形式的代码,尾递归形式是最好转为迭代的。
preorderTraversal(root->left);
preorderTraversal(root->right);
return res;
}
};
迭代算法1:
遗憾的是,该迭代形式尽管十分容易理解但却并不通用与中序,后序。
C代码(什么接口都要自己写。。。好不方便,不用C写了。)
C++代码
class Solution {
public:
vector<int> res;
vector<int> preorderTraversal(TreeNode* root) {
stack<const TreeNode*> S; //维护一个临时的辅助栈,元素为指向节点的指针,由于我们不修改节点数据设定底层const
if (root) S.push(root); //根节点存在,入栈
while (!S.empty()) //栈非空,往返循环
{
//以代码作用为,访问局部root节点,在依次访问左孩子,右孩子节点,此为先序遍历
//若孩子节点不存在,即为空,没有任何实质操作,我们用if限制这种特殊情况
auto t = S.top();
vist(t, res);
S.pop();
if (t->right) S.push(t->right);
if (t->left) S.push(t->left);
}
return res;
}
//对节点进行访问,依据题目不同要求可做修改,该题目要求为读取数据
inline void vist(const TreeNode* node, vector<int>& res)
{
res.push_back(node->val);
}
};
迭代算法2:
该迭代算法的思想可推广至中序和后序,是通用的迭代算法。但该算法比较复杂难懂,注释就不写了,因为写了也没用。
class Solution {
public:
vector<int> res;
vector<int> preorderTraversal(TreeNode* root) {
stack<TreeNode*> s;
while (true)
{
vistAlongLeft(s, root);
if (s.empty()) return res;
root = s.top();
s.pop();
}
}
void vistAlongLeft(stack<TreeNode*>& s, TreeNode* t)
{
while (t)
{
res.push_back(t->val);
s.push(t->right);
t = t->left;
}
}
};