Java数据结构与算法(3) 寻找中序遍历时的下一个结点
来源:互联网 发布:淘宝e客服怎么设置 编辑:程序博客网 时间:2024/06/11 16:10
前言
今天一天没有什么状态,学习效率太低了。今天重新温习了一下树的遍历,如何寻找中序遍历的下一个结点。接下来的计划是学习
Spring Boot
和 算法与数据结构。
思路
算法与数据结构是我最薄弱的一环。每次写关于算法的代码时,都无法下手,经常陷入到逻辑的死胡同里。真心感觉自己的逻辑能力好差,思路混乱。程序员最重要的是思考和逻辑能力,只有把思路理清楚了,代码才能一气呵成。
- 中序遍历:首先按照中序遍历的方式去访问根结点的左子树,然后访问根结点,最后按照中序遍历的方式去访问根结点的右子树。
首先看图
P
表示父结点,N
代表子结点。L
表示N
的左子树,R
表示N
的右子树。- 我们肯定是采用递归的方式。当结点是
L
的时候,无关。当R != null
的时候,我们返回R
结点下面的第一个结点,即下一个结点。如果R == null
的时候,我们下一个结点肯定是要往上面走,在P != null
下的情况,如果N
是P
的左子树,那么下一个结点就是N
。如果N
不是P
的左子树的话,我们需要一直往父亲结点走,直到是某一个结点的左子树,下一个结点即为所求。
代码实现
- 定义一个
MyTreeNode.java
。包含以下属性:结点的值,左子树,右子树,父亲结点。
public class MyTreeNode { private final char value; private MyTreeNode left; private MyTreeNode right; private MyTreeNode parent; public MyTreeNode(char value) { super(); this.value = value; this.left = null; this.right = null; this.parent = null; } public MyTreeNode getLeft() { return left; } public void setLeft(MyTreeNode left) { this.left = left; if (left != null) { this.left.setParent(this); } } public MyTreeNode getRight() { return right; } public void setRight(MyTreeNode right) { this.right = right; if (right != null) { this.right.setParent(this); } } public MyTreeNode getParent() { return parent; } private void setParent(MyTreeNode parent) { this.parent = parent; } public char getValue() { return value; }}
我们自己手动去创建一根这样的树。
显而易见,前序遍历是ABDEGCF
,中序遍历是DBGEACF
,后序遍历是DGEBFCA
。如何通过前序遍历和中序遍历推出树的结构呢?其实很简单,前序遍历中第一个元素肯定是根结点。我们在从中序遍历中找到该根结点,那么根结点左边的元素就是左子树,右边的元素就是右子树呢。然后递归的给每一个结点设置左子树和右字数,一根完整的二叉树就形成了。简单轻松,贴上代码。
public class MyTreeNodeCreator { public static MyTreeNode sampleTree() { MyTreeNode root = new MyTreeNode('A'); root.setLeft(new MyTreeNode('B')); root.setRight(new MyTreeNode('C')); root.getLeft().setLeft(new MyTreeNode('D')); root.getLeft().setRight(new MyTreeNode('E')); root.getLeft().getRight().setLeft(new MyTreeNode('G')); root.getRight().setRight(new MyTreeNode('F')); return root; } public static String displayBehindTree(String font, String mid) { if (StringUtils.isEmpty(font)) { return ""; } char rootValue = font.charAt(0); int index = mid.indexOf(rootValue); return displayBehindTree(font.substring(1, index + 1), mid.substring(0, index)) + displayBehindTree(font.substring(index + 1), mid.substring(index + 1)) + rootValue; } public static MyTreeNode behindTree(String font, String mid) { if (StringUtils.isEmpty(font)) { return null; } char rootValue = font.charAt(0); int index = mid.indexOf(rootValue); MyTreeNode root = new MyTreeNode(rootValue); root.setLeft(behindTree(font.substring(1, index + 1), mid.substring(0, index))); root.setRight(behindTree(font.substring(index + 1), mid.substring(index + 1))); return root; } public static void behindOrder(MyTreeNode node) { if (node == null) { return; } behindOrder(node.getLeft()); behindOrder(node.getRight()); System.out.print(node.getValue() + " "); }}
- 接着我们根据二叉树,寻找中序遍历时的下一个结点。先一般后特殊,要进行边界控制,每次必须向前推进循环不变式中涉及的变量值。
public class InOrder { public MyTreeNode next(MyTreeNode node) { if (node == null) { return null; } if (node.getRight() != null) { return first(node.getRight()); } else { while (node.getParent() != null && node.getParent().getLeft() != node) { node = node.getParent(); } return node.getParent(); } } /** * Gets first node * * @param node * @return */ public MyTreeNode first(MyTreeNode node) { if (node == null) { return null; } MyTreeNode curNode = node; while (curNode.getLeft() != null) { curNode = curNode.getLeft(); } return curNode; }}
- 核心代码完成,我们开始写测试
demo
。我们需要编写测试用例,要遵守BCDE
原则,以保证被测试模块的交付质量。B
:Border
,边界值测试,包括循环边界,特殊取值,特殊时间点,数据顺序等。C
:Correct
,正确的输入,并得到预期的结果。D
:Design
,与设计文档相结合,来编写单元测试。E
:Error
,强制错误信息的输入(如:非法数据,异常流程,非业务允许输入等),并得到预期的结果。
运行Demo
,输出和我们预期一样的结果。
public class Demo { private static InOrder inOrder = new InOrder(); public static void main(String[] args) { printMidTree(); } public static void printBehindTree() { MyTreeNode root = MyTreeNodeCreator.behindTree("ABDEGCF", "DBGEACF"); MyTreeNodeCreator.behindOrder(root); MyTreeNodeCreator.behindOrder(MyTreeNodeCreator.behindTree("ABCD", "ABCD")); } public static void printMidTree() { MyTreeNode sampleTree = MyTreeNodeCreator.sampleTree(); display(sampleTree); display(MyTreeNodeCreator.behindTree("", "")); display(MyTreeNodeCreator.behindTree("A", "A")); display(MyTreeNodeCreator.behindTree("AB", "BA")); display(MyTreeNodeCreator.behindTree("ABCD", "DCBA")); display(MyTreeNodeCreator.behindTree("ABCD", "ABCD")); } public static void display(MyTreeNode sampleTree) { for (MyTreeNode root = inOrder.first(sampleTree); root != null; root = inOrder.next(root)) { System.out.print(root.getValue()); } System.out.println(" "); }}
尾言
我感觉数据结构和算法,思路是最重要的。只要有思路了,代码就水到渠成。没有思路,任何华丽的代码都是徒劳的。
虽然有些数据结构和算法已经掌握了,但是想要简单形象的表达出来,对于我来说还是十分困难的。继续加油。
阅读全文
0 0
- Java数据结构与算法(3) 寻找中序遍历时的下一个结点
- 数据结构与算法分析笔记与总结(java实现)--二叉树18:二叉树的下一个结点
- 数据结构与算法分析笔记与总结(java实现)--二叉树8:寻找错误结点练习题
- 牛客网 | 寻找下一个结点
- 寻找下一个结点
- 寻找下一个结点
- 寻找下一个结点
- 寻找下一个结点
- 二叉树寻找给定结点p的下一个结点
- 【算法】求二叉树的下一个结点
- 二叉树的下一个结点java实现
- 【数据结构与算法】寻找最大的K个数
- 找出二叉树的下一个结点(算法)
- 数据结构与算法分析笔记与总结(java实现)--二叉树21:二叉搜索树的第k个结点
- 程序员面试金典--面试22之寻找二叉树中指定结点的下一个结点
- 数据结构-java与c实现带头结点的单链表
- 数据结构与算法的实现 —— 结点定义与数据结构的选择
- 数据结构与算法分析笔记与总结(java实现)--链表6:两个链表找公共结点问题
- face_recogniton+python2 安装步骤,一切妥妥的
- 基于opencv3的手写板
- 关于java编程的三层架构
- springMVC整合Junit4进行单元测试-2
- 数据结构与算法分析(Java语言描述)(5)—— 归并排序
- Java数据结构与算法(3) 寻找中序遍历时的下一个结点
- 网站性能优化和关键渲染路径
- vim 保存文件“readonly option is set”的解决方法
- [开发规范] Git分支使用规范
- Exploratory Testing(探索测试)
- MATLAB中:冒号用法
- RdioGroup 里面点击事件
- 实现html页面及css3动画
- 全卷机神经网络图像分割(U-net)-keras实现