二叉树的遍历(非递归)
创始人
2024-05-09 14:00:28
0

二叉树的遍历

遍历二叉树, 是指按一定的规则和顺序访问二叉树的所有结点, 使每一个结点都被访问一次, 而且只被访问一次.

由于二叉树是非线性结构, 因此, 二叉树的遍历实质上是将二叉树的各个结点排列成一个线性序列.

DFS: 前序, 中序及后序.

BFS: 是指沿着二叉树的宽度优先遍历二叉树的结点, 即从上到下从左到右逐层遍历二叉树的结点.

前序遍历

访问根结点(N), 前序遍历左子树(L), 前序遍历右子树®, 也即NLR.

也可以是NRL, 因为这两种遍历方法都是先访问根结点, 所以没有区别, 掌握其中一种, 另一种也随之掌握.

image-20230109211219716

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

非递归思路: 二叉树的前序遍历

  1. 对于给定根结点root, 依次从根结点root向左路结点遍历, 直到curr为空并在遍历途中访问对应结点的val, 然后将结点依次入栈.
  2. 当curr为空时, pop栈顶结点, 将栈顶结点的右子树根结点赋值给curr, 并继续转换成从根向左路遍历.
	// 二叉树的前序非递归遍历vector preorderTraversal(TreeNode* root) {stack st;vector v;TreeNode* curr=root;while(curr!=nullptr||!st.empty()){   while(curr!=nullptr){v.push_back(curr->val);st.push(curr);curr=curr->left;}TreeNode* top=st.top();st.pop();curr=top->right;/*// 当curr为空时,遍历左路结点的右子树if(curr==nullptr){TreeNode* top=st.top();st.pop();curr=top->right;}else // 当curr不为空时,遍历左路结点{v.push_back(curr->val);st.push(curr);curr=curr->left;}*/}return v;}

中序遍历

中序遍历左子树, 访问根结点, 中序遍历右子树, 也即LNR.

或者RNL.

image-20230109212500640

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

非递归思路: 二叉树的中序遍历

  1. 中序非递归与前序非递归思路相似, 只是访问结点的val时机不同.
  2. 对于给定根结点root, 依次从根结点root向左路结点遍历, 直到curr为空并在遍历途中将结点依次入栈.
  3. 当curr为空时, pop栈顶结点, 先访问栈顶结点的val, 再将栈顶结点的右子树根结点赋值给curr, 并继续转换成从根向左路遍历.
	vector inorderTraversal(TreeNode* root) {std::vector v;std::stack st;TreeNode* curr=root;// 思路与前序遍历相似while(curr!=nullptr || !st.empty()){while(curr!=nullptr){st.push(curr);curr=curr->left;}TreeNode* top=st.top();st.pop();// 只是访问TreeNode的val时机不同v.push_back(top->val);curr=top->right;}return v;// vector v;// stack st;// TreeNode* curr=root;// while(curr!=nullptr || !st.empty())// {//     if(curr!=nullptr)//     {//         st.push(curr);//         curr=curr->left;//     }//     else//     {//         TreeNode* top=st.top();//         st.pop();//         v.push_back(top->val);//         curr=top->right;//     }// }// return v;}

后序遍历

**后序遍历左子树, 后序遍历右子树, 访问根结点, 也即LRN. **

或者RLN.

image-20230109213035617

给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历

非递归思路: 二叉树的后序遍历

  1. 后序遍历与前中序遍历有一定差异, 在后序遍历过程中, 需要prev来记录访问结点的前一个, 用来判定该不该访问根结点.
  2. 对于给定根结点root, 依次从根结点root向左路结点遍历, 直到curr为空并在遍历途中将结点依次入栈.
  3. 当curr为空时, 根据栈顶结点的右孩子right, 来判断是否pop. 如果right为空或者right为prev说明右子树为空或者右子树访问完, 所以可以pop,并访问该栈顶结点的val, 最后更新prev.
  4. 如果以上两点不满足, 则说明右子树还未访问, 栈顶元素还不能pop, 需要更新curr为栈顶结点的右孩子继续访问.
	vector postorderTraversal(TreeNode* root) {TreeNode* curr=root;TreeNode* prev=nullptr; // 记录遍历结点的前一个vector v;stack st;while(curr!=nullptr || !st.empty()){while(curr!=nullptr){st.push(curr); // 将结点入栈curr=curr->left;}TreeNode* top=st.top();// 当右子树为空或者右子树被访问过,才popif(top->right==nullptr || top->right==prev){prev=top;v.push_back(top->val);st.pop();}else // 否则先访问右子树,等右子树访问完成,才反过来访问根,不能pop{curr=top->right;}} /*while(curr!=nullptr|| !st.empty()){if(curr!=nullptr){st.push(curr);curr=curr->left;}else{TreeNode* top=st.top();// 当右子树为空或者右子树被访问过,才popif(top->right==nullptr || top->right==prev){    v.push_back(top->val);st.pop();prev=top;}else{curr=top->right;}}}*/return v;}

层序遍历

层序遍历就是根据二叉树的结构从上到下从左到右逐层遍历二叉树的结点.

image-20230109214951059

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

基本思路: 二叉树的层序遍历

  1. 初始化一个队列, 并把根结点入队.
  2. 当队列非空时, 循环执行步骤3到步骤5, 否则遍历结束.
  3. 出队一个结点, 并访问该结点.
  4. 若该结点的左子树非空, 则将其左子树入队.
  5. 若该结点的右子树非空, 则将其右子树入队.

需要注意: 当某一层走完时, 该层的下一层也随之全部进入队列中.

	vector> levelOrder(TreeNode* root) {queue q;vector> vv;int levelSize=0; // 记录某一层有多少个结点if(root!=nullptr){q.push(root);++levelSize; // 刚开始根结点这一层就一个结点}while(!q.empty()){vector v;// 将该层的结点都遍历完for(size_t i=0;iTreeNode* front=q.front();q.pop();v.push_back(front->val);if(front->left!=nullptr){q.push(front->left);}if(front->right!=nullptr){q.push(front->right);}}// 遍历完成,队列中的个数就是下一层结点的个数levelSize=q.size(); vv.push_back(v);}return vv;}if(front->right!=nullptr){q.push(front->right);}}// 遍历完成,队列中的个数就是下一层结点的个数levelSize=q.size(); vv.push_back(v);}return vv;}

相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...