当前位置: 首页 > news >正文

从域名到网站辽宁建设工程信息网查询官网

从域名到网站,辽宁建设工程信息网查询官网,衡水城乡建设局网站首页,做网站的时候怎么照片路径二叉树的递归遍历二叉树的非递归遍历写法层序遍历 递归怎么写? 按照三要素可以保证写出正确的递归算法: 1.确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且…
  • 二叉树的递归遍历
  • 二叉树的非递归遍历写法
  • 层序遍历

递归怎么写?

按照三要素可以保证写出正确的递归算法:

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

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

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


前置必会

一定要会自己写出树的类定义

public class TreeNode{TreeNode left;TreeNode right;int val;TreeNode(){}TreeNode(int val){this.val = val}TreeNode(int val,TreeNode right,TreeNode left){this.val = val;this.left = left;this.right = right;
}

144.二叉树的前序遍历

递归写法

class Solution {public List<Integer> preorderTraversal(TreeNode root) {List<Integer> result = new ArrayList<>();dfs(root,result);return result;}void dfs(TreeNode root,List<Integer> result){if(root==null){return;}result.add(root.val);dfs(root.left,result);dfs(root.right,result);}}

非递归写法:
我认为就是记思路。
1.用一个栈作为辅助。
2.前序遍历是根左右,每次先处理的是中间节点,那么先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子。之所以是反过来是因为,这样出栈的时候才是根左右的顺序。直接来看图模拟
请添加图片描述
即每次在处理根节点的时候,将根节点出队,然后将其右孩子先进栈,再将左孩子进栈。
这样进行处理之后,出栈的结果就会是前序遍历的结果。

如果还是不懂,我建议直接结合代码,然后结合上面图,记下来这个做法。我觉得这个直接想是不好想的。

非递归其实就是用辅助数据结构,配合循环

class Solution {public List<Integer> preorderTraversal(TreeNode root) {//结果集List<Integer> result = new ArrayList<>();//特判if(root == null){return result;}//创建辅助栈Deque<TreeNode> st = new ArrayDeque<>();//根节点先入栈st.push(root);//当栈不空的时候while(!st.isEmpty()){//先处理根节点,即将根节点出栈。这就对应着根TreeNode node = st.pop();//将出栈的根节点加入结果集result.add(node.val);//先将右节点加入栈中,可以这么想,早点加入,那么就晚点出。所以右节点出的时候,要比左节点晚,那么这里出也就是和上面节点出栈一个道理。所以这里就完成了根左右里面的根左。因为左节点进的晚,出的就早。if(node.right!=null){st.push(node.right);}//然后才是到左节点,晚点进就可以早点出。if(node.left!=null){st.push(node.left);}}return result;}
}

这是我第二写总结的流程:
1.初始化
创建一个空的结果列表
创建一个辅助栈
将根节点压入栈中

2.主循环: 当栈不为空时,执行以下操作:

a. 处理当前节点:
从栈中弹出一个节点
将该节点的值添加到结果列表中

b. 压入子节点:
如果该节点有右子节点,将右子节点压入栈中
如果该节点有左子节点,将左子节点压入栈中
返回结果列表

这种方法的关键点在于
根节点最先被处理,这符合前序遍历的"根-左-右"顺序。
右子节点先于左子节点入栈,这确保了左子节点会先于右子节点被处理。
这种非递归方法的优点是:

避免了递归调用的开销
对于深度很大的树,可以防止栈溢出
实现简单,易于理解
与中序遍历的非递归方法相比,前序遍历的非递归实现更为直观,因为它可以直接按照遍历顺序处理节点,而不需要像中序遍历那样先到达最左节点。

145.二叉树的后序遍历

递归写法

class Solution {public List<Integer> postorderTraversal(TreeNode root) {List<Integer> result  = new ArrayList<>();dfs(root,result);return result;}public void dfs(TreeNode root,List<Integer> result){if(root==null){return;}dfs(root.left,result);dfs(root.right,result);result.add(root.val);}
}

非递归写法:
这个解法是一个技巧解。
由于前序遍历是根左右,而后续遍历是左右根。所以如果调整一下前序遍历的顺序,先加左节点,再加右节点,那么得到的结果就是按根右左规则得到的。所以此时做翻转,那么得到的结果就是按左右根得到的结果。与后序遍历的结果不谋而合。
所以解法就是线序遍历调整左右入栈方式,然后再对最终结果做翻转。

class Solution {public List<Integer> postorderTraversal(TreeNode root) {Deque<TreeNode> st = new ArrayDeque<>();List<Integer> result = new ArrayList<>();if(root==null){return result;}st.push(root);while(!st.isEmpty()){TreeNode node = st.pop();result.add(node.val);if(node.left!=null){st.push(node.left);}if(node.right!=null){st.push(node.right);}}Collections.reverse(result);return result;}
}

94.二叉树的中序遍历

递归写法

class Solution {public List<Integer> inorderTraversal(TreeNode root) {List<Integer> result = new ArrayList<>();dfs(root,result);return result;}public void dfs(TreeNode root,List<Integer> result){if(root==null){return;}dfs(root.left,result);result.add(root.val);dfs(root.right,result);}
}

非递归写法:
看这个图,然后结合图片,记下这个做法:
请添加图片描述
1.初始化
创建一个空的结果列表和一个空的栈
将当前节点设置为根节点

2.主循环: 当当前节点不为空或栈不为空时,执行以下操作:

a. 左子树遍历
如果当前节点不为空
将当前节点压入栈
移动到左子节点

b. 节点处理
如果当前节点为空(即已经到达最左端)
从栈中弹出一个节点
将该节点的值添加到结果列表中
将当前节点移动到右子节点

3.返回结果列表

这种方法模拟了递归的过程:

首先尽可能深入地遍历左子树
然后处理节点本身
最后遍历右子树
使用栈来保存已经遍历过的父节点,以便在处理完左子树后能够回溯。

还是按代码思维走一遍,又和自己想的还是有一点区别。

class Solution {public List<Integer> inorderTraversal(TreeNode root) {//结果集List<Integer> result = new ArrayList<>();//特判if(root==null){return result;}//辅助栈Deque<TreeNode> st = new ArrayDeque<>();//用一个遍历指针指向rootTreeNode cur = root;//这里就是进递归处理的逻辑,循环条件决定了能不能递归处理下去。//cur!=null表明这个元素不空,可以进栈,!st.isEmpty(),是用来回溯的,表明栈中还有走过的元素需要进行处理。所以栈中走过的元素没处理完也要继续处理。while(cur!=null || !st.isEmpty()){//根据中序,左根右的走法,需要一路向最左下走。走的过程就一直入栈,保存之前的状态。如果cur==null,说明走到最左下的节点的左分支上了,也就是null。if(cur!=null){st.push(cur);cur = cur.left;}else{//不能继续往左走了才处理这里,这里就是开始回溯,回溯一下回到最左下的节点,此节点并不是null。那就把这个元素出栈,把这个元素的val加入结果集。由于每个元素都要左根右,这里处理了根节点,那还要往右节点走。下一波显然cur还是null,那么此时就会弹出沿着路线返回的根节点,往后都是这样。注意是依靠弹出的节点进行转移,因为栈里面的节点才是记录先前的状态,别自己瞎写一个。cur = st.pop();result.add(cur.val);cur = cur.right;}}//当st里面为空的时候,就是所有节点都处理完的时候。return result;}
}

102.二叉树的层序遍历

用队列。
看一个图就懂了。请添加图片描述
队列先进先出,符合一层一层遍历的逻辑。
下面的代码就是二叉树层序遍历的模板题,会这个模板,之后遇到只要是层序遍历的题,随便杀。

总的来说,这个解法看完,里面的len的处理我是当时没想到的。

class Solution {public List<List<Integer>> levelOrder(TreeNode root) {List<List<Integer>> result = new ArrayList<>();checkFun(root,result);return result;}public void checkFun(TreeNode node,List<List<Integer>> result){//特判if(node==null){return;}//辅助队列Deque<TreeNode> que = new ArrayDeque<>();//根节点先入队que.offerLast(node);//队列不空就代表流程还没有结束while(!que.isEmpty()){//记录一层元素的结果集List<Integer> itemList = new ArrayList<Integer>();//在一开始先记录长度,该长度即队列目前的长度,就是该层元素的个数。//记录len就是为了做一个界限,即处理完这一层元素后,就要收集一次结果集。int len = que.size();//这个循环做依次将该层元素出队,并扩展其左右节点加入队列当中。while(len>0){//先出队TreeNode tmpNode = que.pollFirst();//加入结果集itemList.add(tmpNode.val);//扩展左右节点,加入队列中。if(tmpNode.left!=null){que.offerLast(tmpNode.left);}if(tmpNode.right!=null){que.offerLast(tmpNode.right);}//做完之后该层元素数量要-1len--;}//处理完一层后记录一次结果。result.add(itemList);}}
}

107.二叉树的层序遍历Ⅱ

在上题的基础上将结果集翻转就结束了。

class Solution {public List<List<Integer>> levelOrderBottom(TreeNode root) {List<List<Integer>> result = new ArrayList<>();checkFun(root,result);Collections.reverse(result);return result;}public void checkFun(TreeNode node,List<List<Integer>> result){if(node==null){return;}Deque<TreeNode> que = new ArrayDeque<>();que.offerLast(node);while(!que.isEmpty()){List<Integer> itemList = new ArrayList<Integer>();int len = que.size();while(len>0){TreeNode tmpNode = que.pollFirst();itemList.add(tmpNode.val);if(tmpNode.left!=null){que.offerLast(tmpNode.left);}if(tmpNode.right!=null){que.offerLast(tmpNode.right);}len--;}result.add(itemList);}}
}
http://www.yayakq.cn/news/314572/

相关文章:

  • 网站全景图怎么做寻花问柳专注做一家男人最爱的网站
  • 世安建设集团有限公司网站网站推广费用ihanshi
  • 广州天河网站制作cms做的电影网站
  • 广州网站建设技术托管优酷 做视频网站还能成功吗
  • 如何查看网站开发公司网站建设投标书免费
  • 衡水网站建设联系电话怎么做的网站怎么放上网
  • 固原地网站seo免费电视剧在线观看网站
  • 专门做求职课程的网站长宁区网站制作
  • 网站建设 国家技术规范九亭微信网站建设
  • 单页面网站怎么做WordPress允许评论编辑
  • 大酒店网站源代码网络服务商机构域名
  • 怎么做公司的网站建设网站后如何做后台
  • 网站友情链接查询如何改wordpress文章模板
  • 能源产品网站建设多少钱在线电影网站建设
  • 网站项目团队介绍怎么写wordpress搜索页面模板
  • 大连做网站的修改wordpress的站点地址
  • 买奢侈品代工厂做的产品的网站名舆情app免费
  • 什么网站做视频给钱校园网络平台建设方案
  • 网站快慢由什么决定南通网站制作专家
  • 没有备案的网站能否帮网上支付企业注册成立网址
  • 群晖wordpress外网泉州网站排名优化
  • 建设阅读网站的目的wordpress彩色美化
  • 三亚北京网站建设东莞一站式网站推广运营
  • 河北网站制作公司哪家专业重庆招聘信息最新招聘2021
  • 网站代码编辑器wordpress支持多少并发
  • 上海工商网站官网加强网站建设技术培训
  • 涿州市建设局网站tp类似wordpress
  • 泉州建设网站公司哪家好微网站开发费用
  • 网站建设算什么资产app开发公司的管理机制
  • 云南网站建设熊掌号浙江网商银行电话