最近在学习TDD。 看了那个fibonacci 的TDD过程。 我就想:咋能TDD出树的遍历算法呢? 我来试一下。当作练习了~ (树的知识有些忘了,先贴些基础- -#做准备)
数据结构知识——树的三种不同遍历算法解析- -- -
树的遍历是树的一种重要的运算。所谓遍历是指对树中所有结点的系统的访问,即依次对树中每个结点访问一次且仅访问一次。树的3种最重要的遍历方式分别称为前序遍历、中序遍历和后序遍历。以这3种方式遍历一棵树时,若按访问结点的先后次序将结点排列起来,就可分别得到树中所有结点的前序列表,中序列表和后序列表。相应的结点次序分别称为结点的前序、中序和后序。
树的这3种遍历方式可递归地定义如下:
如果T是一棵空树,那么对T进行前序遍历、中序遍历和后序遍历都是空操作,得到的列表为空表。
如果T是一棵单结点树,那么对T进行前序遍历、中序遍历和后序遍历都只访问这个结点。这个结点本身就是要得到的相应列表。
否则,设T如图6所示,它以n为树根,树根的子树从左到右依次为T1,T2,..,Tk,那么有:
对T进行前序遍历是先访问树根n,然后依次前序遍历T1,T2,..,Tk。
对T进行中序遍历是先中序遍历T1,然后访问树根n,接着依次对T2,T2,..,Tk进行中序遍历。
对T进行后序遍历是先依次对T1,T2,..,Tk进行后序遍历,最后访问树根n。
图6 树T
前序遍历和中序遍历可形式地依次描述如下
三种遍历可以形式地描述如下,其中用到了树的ADT操作:
Procedure Preorder_Traversal(v:NodeType); {前序遍历算法}
begin
Visite(v); {访问节点v}
i:=Leftmost_Child(v);
while i<>∧ do
begin
Preorder_Traversal(i);{从左到右依次访问v的每一个儿子节点i}
i:=Right_Sibling(i);
end;
end;
Procedure Inorder_Traversal(v:NodeType); {中序遍历算法}
begin
if Leftmost_Child(v)=∧ {判断v是否是叶节点}
then Visite(v)
else
begin
Inorder_Traversal(Leftmost_Child(v)); {中序遍历v的左边第一个儿子节点}
Visite(v); {访问节点v}
i:=Right_Sibling(Leftmost_Child(v)); {i=v的左边第二个儿子}
while i<>∧ do
begin
Inorder_Traversal(i);
{从左边第二个开始到最右边一个为止依次访问v的每一个儿子节点i}
i:=Right_Sibling(i);
end;
end;
end;
Procedure Postorder_Traversal(v:NodeType); {后序遍历算法}
begin
i:=Leftmost_Child(v);
while i<>∧ do
begin
Preorder_Traversal(i);{从左到右依次访问v的每一个儿子节点i}
i:=Right_Sibling(i);
end;
Visite(v); {访问节点v}
end;
为了将一棵树中所有结点按某种次序列表,只须对树根调用相应过程。例如对图7中的树进行前序遍历、中序遍历和后序遍历将分别得到前序列表:A B E F I J C D G H;中序列表:E B I F J A C G D H;后序列表:E I J F B C G H D A。
图7 一棵树
下面介绍一种方法可以产生上述3种遍历方式的结点列表。设想我们从树根出发,依逆时针方向沿树的外缘绕行(例如围绕图7中的树绕行的路线如图8所示)。绕行途中可能多次经过同一结点。如果我们按第一次经过的时间次序将各个结点列表,就可以得到前序列表;如果按最后一次经过的时间次序列表,也就是在即将离开某一结点走向其父亲时将该结点列出,就得到后序列表。为了产生中序列表,要将叶结点与内部结点加以区别。叶结点在第一次经过时列出,而内部结点在第二次经过时列出。
图8 树的遍历
在上述3种不同次序的列表方式中,各树叶之间的相对次序是相同的,它们都按树叶之间从左到右的次序排列。3种列表方式的差别仅在于内部结点之间以及内部结点与树叶之间的次序有所不同。
一棵树进行前序列表或后序列表有助于查询结点间的祖先子孙关系。假设结点v在后序列表中的序号(整数)为postorder(v),我们称这个整数为结点v的后序编号。例如在图7中,结点E,I和J的后序编号分别为1,2和3。
结点的后序编号具有这样的特点:设结点v的真子孙个数为desc(v),那么在以v为根的子树中的所有结点的后序编号恰好落在postorder(v)- desc(v)与postorder(v)之间。因此为了检验结点x是否为结点y的子孙,我们只要判断它们的后序编号是否满足:
postorder(y)-desc(y)≤postorder(x)≤postorder(y)
前序编号也具有类似的性质。
Trackback=http://publishblog.blogchina.com/blog/tb.b?diaryID=1833654
分享到:
相关推荐
### TDD-CDMA在无线通信中的应用 #### 一、引言 TDD-CDMA(时分双工-码分多址)是无线通信技术中的一个重要分支,它结合了时分双工(TDD)与码分多址(CDMA)两种技术的特点,为移动通信系统提供了高效的数据传输解决...
TDD-CDMA 技术及在 4G 中的应用 TDD-CDMA 技术是第四代无线通信系统(4G)中的一种关键技术。TDD-CDMA 是一种 Time Division Duplexing Code Division Multiple Access(时分双工码分多址)技术,具有高频谱效率、...
在这个名为"TDD-learn-demo1"的项目中,我们看到的是一个学习TDD的具体实例,特别是针对`ProtoStuffUtil`类的测试。 `ProtoStuffUtil`类可能是一个处理序列化和反序列化任务的工具类,它可能与Google的Protocol ...
我的博客 学习TDD(4)--实例2:基于ZooKeeper的服务器注册和探测类[实战ServerRegister]及 学习TDD(5)--实例2:基于ZooKeeper的服务器注册和探测类[实战ServerDetector] 的配套代码
TDD-LTE(时分双工LTE)是LTE的一个变种,它利用时间分复用的方式实现上行链路和下行链路的数据传输。本培训教程将深入探讨TDD-LTE的关键概念和技术细节,帮助读者全面理解这一领域的核心知识。** 1. **LTE概述** ...
`laravel-tdd-docs` 是一个专门为 Laravel 开发者准备的资源,旨在帮助他们更好地理解和应用 TDD。 1. **TDD 的核心原则** TDD 的基础包括三个步骤:红(Red)、绿(Green)、重构(Refactor)。首先,编写一个...
根据文件信息,该文件是关于使用Swift 4进行iOS开发的测试驱动开发(TDD)的书籍,书名为《Test-Driven iOS Development with Swift 4 (Third Edition)》。该书的作者是Dominik Hauser博士,他完成物理学博士学业后...
标题 "ses-tdd-exercise-1-template-源码.rar" 提示我们这是一个关于软件开发的练习项目,可能涉及测试驱动开发(TDD)的概念。在这个练习中,"template" 指的可能是一个模板项目,用于指导开发者进行TDD实践。源码...
TDD-LTE基本原理,LTE关键技术,LTE系统结构,LTE入门学习资料
### 测试驱动开发(TDD)在Django与...以上内容涵盖了本书《tdd-for-web-development-with-django-and-selenium》的部分关键知识点,这些知识点不仅对学习Django和Selenium有帮助,同时也适用于更广泛的Web开发领域。
【标题】"estudo-test-TDD--algaworks" 是一个与测试驱动开发(Test-Driven Development, TDD)相关的学习项目,很可能基于Java编程语言。TDD是一种软件开发方法论,强调在编写实际功能代码之前,先编写测试用例,...
kata-tdd-1-BINH-NGUYEN-VAN kata 首先,我们必须安装grunt插件以帮助运行此演示: 1.打开命令行 2.转到目录:“ kata-tdd-1-BINH-NGUYEN-VAN” 3.键入命令:npm install 4.运行命令:grunt serve 问题 Q1:在...
在IT行业中,Test-Driven Development(TDD)是一种软件开发实践,它强调通过编写测试用例来驱动功能代码的编写。在这个场景下,"KATA-TDD --- TENNIS"是一个针对TDD技术的编程练习,旨在帮助开发者熟悉并掌握TDD的...
TDD-LTE技术基本原理的介绍。PPT格式 更简洁明了
TDD Cli转换器 TDD研究-从/到任何货币的CLI转换器 入门 这些说明将为您提供在本地计算机上运行并运行的项目的副本,以进行开发和测试。 有关如何在实时系统上部署项目的注释,请参阅部署。 先决条件 您需要什么东西...