二叉树2:二叉树的递归遍历

本文详细介绍递归算法的核心要素,包括确定递归函数的参数与返回值、终止条件及单层递归逻辑,并通过二叉树的前序、中序、后序遍历实例进行讲解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

主要是我自己刷题的一些记录过程。如果有错可以指出哦,大家一起进步。
转载代码随想录
原文链接:
代码随想录
这次我们要好好谈一谈递归,为什么很多同学看递归算法都是“一看就会,一写就废”。

基础

主要是对递归不成体系,没有方法论,每次写递归算法 ,都是靠玄学来写代码,代码能不能编过都靠运气。

本篇将介绍前后中序的递归写法,一些同学可能会感觉很简单,其实不然,我们要通过简单题目把方法论确定下来,有了方法论,后面才能应付复杂的递归。

这里帮助大家确定下来递归算法的三个要素。每次写递归,都按照这三要素来写,可以保证大家写出正确的递归算法!

  1. 确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。

  2. 确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。

  3. 确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。

好了,我们确认了递归的三要素,接下来就来练练手:

以下以前序遍历为例

  1. 确定递归函数的参数和返回值:因为要打印出前序遍历节点的数值,所以参数里需要传入vector在放节点的数值,除了这一点就不需要在处理什么数据了也不需要有返回值,所以递归函数返回类型就是void,代码如下:
void traversal(TreeNode* cur, vector<int>& vec)
  1. 确定终止条件:在递归的过程中,如何算是递归结束了呢,当然是当前遍历的节点是空了,那么本层递归就要要结束了,所以如果当前遍历的这个节点是空,就直接return,代码如下:
if (cur == NULL) return;

确定单层递归的逻辑:前序遍历是中左右的循序,所以在单层递归的逻辑,是要先取中节点的数值,代码如下:

vec.push_back(cur->val);    // 中
traversal(cur->left, vec);  // 左
traversal(cur->right, vec); // 右

单层递归的逻辑就是按照中左右的顺序来处理的,这样二叉树的前序遍历,基本就写完了,再看一下完整代码:

前序遍历:

class Solution {
public:
    void traversal(TreeNode* cur, vector<int>& vec) {
        if (cur == NULL) return;
        vec.push_back(cur->val);    // 中
        traversal(cur->left, vec);  // 左
        traversal(cur->right, vec); // 右
    }
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root, result);
        return result;
    }
};

那么前序遍历写出来之后,中序和后序遍历就不难理解了,代码如下:

中序遍历:

void traversal(TreeNode* cur, vector<int>& vec) {
    if (cur == NULL) return;
    traversal(cur->left, vec);  // 左
    vec.push_back(cur->val);    // 中
    traversal(cur->right, vec); // 右
}

后序遍历:

void traversal(TreeNode* cur, vector<int>& vec) {
    if (cur == NULL) return;
    traversal(cur->left, vec);  // 左
    traversal(cur->right, vec); // 右
    vec.push_back(cur->val);    // 中
}

此时大家可以做一做leetcode上三道题目,分别是:

144.二叉树的前序遍历
给定一个二叉树的根节点 root ,返回 它的 前序 遍历 。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
 //递归解法
class Solution {
public:
    void traversal(TreeNode* node, vector<int>& result) {
		if (!node)return;		//如果节点为空
		result.push_back(node->val);
		traversal(node->left, result);
		traversal(node->right, result);
	}

	vector<int> preorderTraversal(TreeNode* root) {
		vector<int>result;
		traversal(root, result);
		return result;
	}
};

//迭代解法
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
		vector<int>result;
		stack<TreeNode*>myStack;
		if (root == nullptr) return result;

		TreeNode* cur = root;
		myStack.push(cur);
		while (!myStack.empty()) {
			TreeNode* temp = myStack.top();//处理节点
			myStack.pop();
			result.emplace_back(temp->val);
			if(temp->right) myStack.push(temp->right);//处理右孩子,栈是先进后出
			if (temp->left) myStack.push(temp->left);//处理左孩子
		}
		return result;
	}
};

145.二叉树的后序遍历
给定一个二叉树的根节点 root ,返回 它的 后序遍历 .

//递归解法

class Solution {
public:
    void traversal(TreeNode* node, vector<int>& result) {
		if (!node)return;
		traversal(node->left, result);
		traversal(node->right, result);
		result.push_back(node->val);
	}

	vector<int> postorderTraversal(TreeNode* root) {
		vector<int>result;
		traversal(root, result);
		return result;
	}
};

//迭代解法
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
		vector<int>result;
		stack<TreeNode*>myStack;
		if (root == nullptr) return result;

		TreeNode* cur = root;
		myStack.push(cur);
		while (!myStack.empty()) {
			TreeNode* temp = myStack.top();//处理节点
			myStack.pop();
			result.emplace_back(temp->val);
			if (temp->left) myStack.push(temp->left);//处理左孩子
			if (temp->right) myStack.push(temp->right);//处理右孩子	
		}
		reverse(result.begin(), result.end());
		return result;
	}
};

94.二叉树的中序遍历
给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。

//递归解法
class Solution {
public:
    void traversal(TreeNode* node, vector<int>& result) {
		if (!node)return;
		traversal(node->left, result);
		result.push_back(node->val);
		traversal(node->right, result);
	}

	vector<int> inorderTraversal(TreeNode* root) {
		vector<int>result;
		traversal(root, result);
		return result;
	}
};

//迭代解法
class Solution {
public:
	vector<int> inorderTraversal(TreeNode* root) {
		vector<int>result;
		stack<TreeNode*>myStack;
		TreeNode* cur = root;
		while (cur != nullptr || !myStack.empty()) {
			if (cur != nullptr) {
				myStack.push(cur);
				cur = cur->left;
			}
			else {
				cur = myStack.top();
				result.push_back(cur->val);
				myStack.pop();
				cur = cur->right;
			}
		}
		return result;
	}
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值