IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 二叉树前序、中序、后序以及层序遍历方法 -> 正文阅读

[数据结构与算法]二叉树前序、中序、后序以及层序遍历方法

一、递归

1.1 前序遍历

void preprder(TreeNode* root, vector<int> &ans) {
	if(root == nullptr) return;
	ans.push_back(root -> val);
	pre(root -> left, ans);
	pre(root -> right, ans);
}

1.2 中序遍历

void inorder(TreeNode* root, vector<int> &ans) {
	if(root == nullptr) return;
	pre(root -> left, ans);
	ans.push_back(root -> val);
	pre(root -> right, ans);
}

1.3 后序遍历

void inorder(TreeNode* root, vector<int> &ans) {
	if(root == nullptr) return;
	pre(root -> left, ans);
	pre(root -> right, ans);
	ans.push_back(root -> val);
}

二、迭代

2.1 前序遍历

vector<int> preorderTraversal(TreeNode* root) {
	vector<int> ans;
	if(root == nullptr) return ans;
	stack<TreeNode*> stk;//保存迭代过程中指向节点的指针。用途:遇空节点时返回上一个节点
	while(!stk.empty() || root != nullptr) {
		while(root != nullptr) { //一直往左子树搜索
			ans.push_back(root->val);//访问当前root指向的节点
			stk.push(root);//保留返回的路径,注意栈中的元素均已被访问
			root = root -> left;
		}
		//循环结束,root指空,stk.top()指向当前子树最左面节点
		root = stk.top();
		//stk.top()指向的节点已经被访问过了
		//stk.top()节点的左子树所有节点已经均被访问,所以删除栈顶元素
		stk.pop();
		//前序遍历:根,左,右, 所以接下来向右子树迭代
		root = root -> right;//向右子树迭代
	}
	return ans;
}

2.2 中序遍历

vector<int> inorderTraversal(TreeNode* root) {
	vector<int> ans;
	if(root == nullptr) return ans;
	stack<TreeNode*> stk;
	while (root != nullptr || !stk.empty()) {
		while (root != nullptr) {
			//ans.push_back(root -> val); 注意与先序遍历的差别
			stk.push(root);
			root = root->left;
		}
		root = stk.top();
		stk.pop();
		//在前序遍历中,下面一行代码在上方的循环中
		ans.push_back(root->val);//中序遍历:左,根,右。
		root = root->right;
	}
	return ans;
}

2.3 后序遍历

2.3.1 方法一

vector<int> postorderTraversal(TreeNode *root) {
	vector<int> ans;
	if (root == nullptr) {
		return ans;
	}
	stack<TreeNode*> stk;
	TreeNode *prev = nullptr;//指向最近访问的节点
	while (root != nullptr || !stk.empty()) {
		while (root != nullptr) {
			stk.push(root);
			root = root->left;
		}
		root = stk.top();//root指向最左边的结点
		stk.pop();//结点出栈
		//后序遍历:左,右,根
		//如果右结点为空,或右结点已经被访问,则访问该节点
		if (root->right == nullptr || root->right == prev) {
			ans.push_back(root->val);//右结点空,则访问目前结点
			prev = root;//prev记录最近访问的节点
			root = nullptr;//置空,防止下次循环指针入栈
		} else {//还有右结点
			stk.push(root);//根节点重新入栈
			root = root->right;//迭代右子树
		}
	}
	return res;
}

2.3.2 方法二

用一个辅助栈记录访问路径。后序遍历,树中每一个节点需要进栈三次,出栈三次,第一次出栈是遍历节点左子树,第二次出栈是遍历节点右子树,第三次出栈是访问节点。

vector<int> postorderTraversal(TreeNode* root) {
	vector<int> ans;
	if(root == nullptr) return ans;
	stack<pair<TreeNode*,int>> stk;//pair<TreeNode*,int>,second记录进栈次数
	stk.push({root, 0});//根节点进栈
	while(!stk.empty()) {
		pair<TreeNode*,int> p = stk.top();//出栈
		stk.pop();//节点出栈
		if(p.second == 0) {//节点第一次出栈,访问其左子树
			stk.push({p.first, 1});//原节点进栈,修改进出栈记录,0->1
			if(p.first->left != nullptr) {
				stk.push({p.first->left, 0});//左子节点进栈,准备遍历其左子树
			}
		}
		if(p.second == 1) {//节点第二次出栈,访问其右子树
			stk.push({p.first, 2});
			if(p.first->right != nullptr) {
				stk.push({p.first->right, 0});
			}
		}
		if(p.second == 2) {//节点第三次出栈,访问该节点
			ans.push_back(p.first->val);//访问节点
		}
	}
	return ans;
}

三、层序遍历

vector<vector<int>> levelOrder(TreeNode* root) {
	vector<vector<int>> ans;
	vector<int> tmp;//保留每一层的元素
	if(root == nullptr) return ans;
	queue<TreeNode*> q;
	q.push(root);
	tmp.push_back(root->val);//保留第零层元素
	//int level = 0; 当前处于第0层
	while(!q.empty()) {
		ans.push_back(tmp);//当前层元素均保留在了tmp中
		//level++; 进入下一层
		int currentSize = q.size();//当前层元素个数
		tmp.clear();//清空当前层元素,以便记录下一层元素
		for(int i = 0; i < currentSize; i++) { //遍历当层所有元素
			TreeNode* p = q.front();
			q.pop();//元素出队
			if(p->left != nullptr) {
				q.push(p->left);//下层的元素入队
				tmp.push_back(p->left->val);//记录下层元素
			}
			if(p->right != nullptr) {
				q.push(p->right);
				tmp.push_back(p->right->val);
			}
		}
	}
	return ans;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-10 22:50:47  更:2022-03-10 22:51:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 13:25:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码