LeetCode刷题之树

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;
        }
    }
};
发布了19 篇原创文章 · 获赞 2 · 访问量 2529

猜你喜欢

转载自blog.csdn.net/SC_king/article/details/105253674