二叉树算法在DS18B20地址搜索中的运用

二叉树算法在DS18B20地址搜索中的运用
二叉树算法在DS18B20地址搜索中的运用

二叉树算法在DS18B20地址搜索中的运用①盛磊葛照君(杭州师范大学钱江学院浙江杭州 310036)

摘要:讨论单总线上挂接多个DS18B20时的自动识别方法。根据DS18B20二叉树算法编码特征,阐述了序列号识别过程,多点扫描和动态建树过程,以及在应用系统中的信息存储方式,对使用DS18B20

实现多点温度检测具有十分重要的意义。

关键词:二叉树;多点扫描;编码优化;DS18B20

Binary Tree Algorithm in DS18B20 Address Search

SHENG Lei, GE Zhao-Jun

(Hangzhou Normal University, Hangzhou 310036, China)

Abstract: This article discusses automatic identification method in a single bus with a number of DS18B20.

According to the characteristics of DS18B20 binary tree coding algorithm, the identification process of the

series number is described together with that of multi-point scanning and dynamic contribution to the

process, as well as in the application of system information storage means. It has of great significance to

the use of multi-point temperature DS18B20.

Keywords: binary tree algorithm; multi-point scanning; optimize code; DS18B20

1 引言

随着科学技术的发展和进步,温度控制技术在工业控制、家用电器、医学仪器等多个领域中都有广泛的运用。传统的多点多总线系统在实际运用中操作繁琐,而且不利于程序控制。同时为了克服模拟传感器与微处理器接口需要信号调理电路等弊端,在现代工业中多采用数字传感器,例如DS18B20。DS18B20优点在于运用独特的一线总线方式传输信息[1],从而使得在多点温度检测中可最大程度简化系统布线。

DS18B20在多点温度测量中应用的关键在于传感器的识别,DS18B20设计者使用了48位二进制数作为器件的序列号,并提供用户运用二叉树算法进行搜索。在实际应用中具体如何实现,十分重要。本文以处理器MCS-51单片机为例,对单总线上的多个DS18B20的地址识别予以具体分析。其中文献[2]给出了基于单片机的多点温度测量系统结构的一种设计方案。

①收稿时间:2009-06-03 2 数据存储和总线识别方法

2.1 存储方法

DALLAS公司每一个数字温度传感器内均固化一个64 位产品序列号(最低8 位是产品代码,其后48 位是器件序列号,最后8位是前56位循环冗余校验码),存放于器件ROM[3,4]。手册[5]规定应用时只有获得该序列号才能对传感器进行各种操作。一般,对48位器件序列号以6个存储单元为一组依次存储在应用系统的RAM中。当一线总线上传感器数量较多时,应用系统应考虑有足够多的存储单元存放传感器的序列号。

假设现有5个DS18B20,存放于首地址为0000H的单片机片外RAM单元,各DS18B20的64位序列号在RAM中的存放地址分配如表1所示:在识别完成后最终的传感器序列号信息将被依次存放在0000H~0027H单元中。

表1 地址存储分配实例表

位置编号存储地址单元

1 0000H~0007H

2 0008H~000FH

3 0010H~0017H

4 0018H~001FH

5 0020H~0027H

2.2 总线识别步骤

根据DALLAS规定,单总线数字传感器的操作必须按照以下步骤进行:

(1) 微处理器发出复位脉冲(脉宽为480us~690us)进行初始化,一线总线上的传感器则发出存在脉冲(脉宽为60us~240us)[6]做出响应;

(2) 微处理器向一线总线发SEARCH(搜索) ROM 命令(F0H)[6];

(3) 微处理器通过一线总线读一位(数据),过程如下[7]:

①每个DS18B20把各自ROM 中的第一位放到一线总线上,产生“线与”,由微处理器读取“线与”结果;

②每个DS18B20把各自ROM 中的第一位的补码放到总线上,微处理器再次读得“线与”结果;

③微处理器根据读取的两位“线与”结果,可得出如下结论:

* “00”:表明总线上有传感器连着,且在该数据位上它们的值发生冲突,产生“混码”;

* “01”:表明该数据位上的值均为“0”;

* “10”:表明该数据位上的值均为“1”;

* “11”:表明该数据位上没有传感器相连。

④微处理器通过算法判断,将“0”或者“1”写到总线上,选中总线上与该位相符的传感器。

⑤通过软件重复以上步骤,直到完整读取64位序列号。

3 二叉树搜索算法的实现

3.1 建立扫描二叉树

在一线总线上所挂传感器数量很多的情况下,微处理器读取位码时产生的混码可能性会很大。为了在最短的时间内遍历到所有传感器的序列号,采用二叉树搜索算法可使处理更合理。

按照该算法,将序列号扫描过程中产生的混码作为结点,构造出一棵二叉树。假设结点的左分支为该混码点数值“0”的扩展方向,结点的右分支为该混码点数值“1”的扩展方向,该二叉树的结点(即混码点)必定存在左右分支。显然,该二叉树是一棵满二叉树。假定有三个DS18B20的前若干位代码如下:

① 01011001……

② 01110110……

③ 01110001……

③⑥

根据算法可以建立如图1的二叉树。

图1 二叉树搜索算法建立的二叉树

该算法的搜索方式采用先序遍历(即先左后右),即先0码后1码的原则。因此,从根结点开始到每个叶结点的最短路径就对应着一个传感器序列号。同时,该二叉树又是一动态二叉树,结点(混码点)也是边搜索边生成的。因此,每搜索完一个传感器的序列号后,该二叉树都可能较前一次搜索完时的状态将发生很大的变化。

3.2 二叉树的线性存储

应用系统无需存储整个二叉树所有信息,但是可以考虑将树结点按照一定的顺序存储关键信息。在整个搜索过程中,保存每个混码点的状态,并对于每个混码点,根据先序遍历的结点顺序,依次将其状态存储在应用系统RAM中。假定结点状态如下:

* “00H”:表示该结点(混码点)已经发送过“0”;

* “01H”:表示该结点(混码点)即发送过“0”,也发送过“1”;

* “11H”:表示空结点或者根结点。

须注意的是:以上的状态和每次传感器读入的两位“线与”结果是两个不同的概念。此处所指的结点

状态是预先假设的(也可根据实际情况定义)。而微处理器从传感器读入的两位“线与”结果根据传感器该位的固有值而定。这两个概念绝不能混淆,在算法实现过程,这两个概念的运用是有序结合的。

在处理过程可定义R0作为指针指出当前搜索结点;PRST表示尾结点指针。该线性存储方式可表示如图2所示:

图2 二叉树线性存储实例

3.3 二叉搜索算法中混码点处理

按照二叉树先序遍历的特点,每个从根结点到各叶结点的最短路径,分别对应着一个DS18B20序列号。

在扫描过程中,根据满二叉树和先序遍历的特点,每次扩展的结点必定是先序遍历的线性存储的尾结点,非尾结点均按照前次选择的路序(即“0”或者“1”)进行发送选择。

在每次开始新的序列号搜索之前,必须先由R0指向首结点的下一个结点。

当二叉树搜索算法遇到混码点时,按照如下步骤进行判断和处理:

(1) 首先判断线性存储中的当前结点R0状态是否为空结点,即R0结点的状态是否为11H。

(2) 如果(R0)=11H,则表明该混码点未存储在该线性存储中。因此,需要将该混码点添加到该线性存储中。添加结点过程包括:

①首先将当前R0指针状态设为“00H”,表明该结点发送过“0”。同时将“0”送入进位位C中,即(R0)=00H,C=0;

②如果该结点为空结点,根据该算法实现过程,这时R0和PRST必定指向同一个结点。在添加完该结点状态后,我们将R0和PRST指针都向后移一位,即R0=R0+1,PRST=PRST+1;

③同时将当前R0和PRST指针状态设为“11H”,即(R0)=11H,(PRST)=11H。

如果(R0)≠11H,则表明该混码点已经存储在该线性存储中。因此需要对当前混码点在该线性存储中的结点位置和状态进行判断。

A. 如果该结点不是尾结点,即R0

a. 如果R0指针的状态为“00H”,即(R0)=00H,表明该结点在前次已经发送过“0”,将“0”送入进位位C中,即C=0;

b. 如果R0指针的状态为“01H”,即(R0)=01H,表明该结点在前次已经发送过“1”,将“1”送入进位位C中,即C=1;

c. 将R0指针后移一位,即R0=R0+1。

B. 如果该结点是尾结点,即R0=PRST,我们将对该结点进行扩展。由于尾结点状态必定为“00H”,表明前次发送过“0”,因此,本次应当对其进行右分支扩展,发送选择“1”状态。

a. 首先将R0指针状态设为“01H”,表明该结点发送过“0”和“1”。同时将“1”送入进位位C 中,即(R0)=01H,C=1。

b. 这时R0和PRST必定指向同一个结点。在扩展完该结点状态后,我们将R0和PRST指针都向后移一位,即R0=R0+1,PRST=PRST+1。

c. 同时将当前R0和PRST指针状态设为“11H”,即(R0)=11H,(PRST)=11H。发送该进位位C的值至总线,进行选择。

3.4 尾节点处理

每当扫描完成一个64位序列号之后,都要对该线性存储进行调整,删除当前已经进行过“0”和“1”扩展的结点,即结点状态为“01H”的尾结点,同时将PRST指向从尾结点开始向前搜索到的第一个非“01H”状态的结点。整个处理过程可分为以下几个步骤:

(1) 将当前尾结点设为空结点,即(R0)=11H。

(2) 将R0指针向前移一位,即R0=R0-1。

(3) 判断当前R0指针状态是否为“01H”:

①如果当前结点状态为“01H”,即(R0)=01H,则表明该混码点已经发送过“0”和“1”的状态,在后续的扫描过程中,已经没有可以扩展的需要,因此需要将该结点从当前线性存储中删除,并将当前结点设为空结点,重新回到步骤(1);

②如果当前结点状态为非“01H”,即(R0)<>01H,则表明该混码点已经发送过“0”,

在后

续的扫描过程中,如果该结点为“00H”,则可以作为尾结点,继续进行右分支扩展。

(4) 将当前PRST指向当前R0指针,即PRST=R0。

(5) 判断当前线性存储尾结点PRST(或者R0)的状态是否“11H”:

①如果尾结点为“01H”,则表明该线性存储中还有可用结点存在,返回继续进行下一个序列号的扫描;

②如果尾结点为“11H”,即(PRST)=11H,则表明当前线性存储中尾结点为空结点,该线性存储中已经不存在任何可用结点。换而言之,所有的序列号信息都已经扫描完成。

4 结语

采用二叉树算法,对大数量多个DS18B20进行

(上接第142页)

值和有效期得情况下,与LI提出的算法得时间复杂度相同,即最大时间复杂度为O( +mn)空间复杂度为O(mn)。

6 RT0基本语法

在RT0的基础上提出了基于证书时间域和改进的信任度证书链搜索算法,将时间考虑到了证书和信任度的更新中,并在此基础上对信任的传递深度通过信任阀值进行了控制,符合信任得主观性。随着证书内容的增多,比如证书有效性的增加,如何存储更有效;对带有参数的基于角色的访问控制[9]等都需要进一步研究。

参考文献

1 Li NH, Winsborough WH, Mitchell JC. Distributed credential chain discovery in trust management (full version). New York: ACM Press, 2001.156-165.

2 张志勇,黄涛.信任管理中基于角色的委托授权研究进展.计算机应用研究, 2008,25(6):1601-1605. 序列号搜索和地址重新编码,运用于粮库作多点温度数据采集,取得良好效果。实践证明,这一方法在相关领域中应用具有很高的实际使用价值和发展前景。

参考文献

1 沈二波,王爱民,杨红卫.基于DS18B20的远程粮仓温控系统.微计算机信息, 2008,10(1):211-213.

2 刘卫,刘定良.基于DS18B20设计的多点测温系统. 长沙民政职业技术学院学报, 2007,3:92-95.

3 陈良光,刘剑亮.DS18X20 在多点测温中的编码优化技术.传感器技术, 2001,9:55-57.

4 陈良光,宋荷庆,金华频.数字式温度传感器原理及其应用.中国仪器仪表,2001,(1):15-18.

5 DS18B20中文资料. pdf. https://www.360docs.net/doc/e714638051.html,/ down_view.asp?id=314

6 DS18B20.pdf. https://www.360docs.net/doc/e714638051.html,/DS18B20. pdf

7 罗文广.单总线数字温度传感器的自动识别技术.电子产品世界, 2002,8.B:68-71.

3 陈博,李明楚,任一支.基于信任度的改进凭证连发现算法.计算机工程, 2008,34(22):174-176.

4 祝胜林,杨波,张明武.信任管理中证书链发现的研究.计算机工程与应用, 2007,43(8):111-113.

5 廖俊国,洪帆,朱更明,杨秋伟.基于信任度的授权委托模型.计算机学报, 2006,29(8):1265-1270.

6 刘鹏,刘欣,陈钟.信任管理综述.计算机工程与应用, 2004,32:38-43.

7 Li NH, Winsborough WH, Mitchell JC. Distributed Credential Chain Discovery in Trust Management. Journal of Computer Security, 2003, 11(1):35-86.

8 程男男,杨波.一种带有信任度的基于角色的信任管理模型.计算机应用研究, 2006,23(1):100-102.

9 Zhu X, Wang S, Hong F, et al. Distributed credential chain discovery in trust-management with parame- terizeed roles. Chinese Journal of Computers, 2006,29 (8):1266-1270.

3 n

创建一个二叉树并输出三种遍历结果

实验报告 课程名称数据结构 实验项目实验三--创建一个二叉树并输出三种遍历结果 系别■计算机学院 _________________ 专业_______________ 班级/学号_____________ 学生姓名___________ 实验日期— 成绩______________________________ 指导 教师

实验题目:实验三创建一个二叉树并输出三种遍历结果 实验目的 1)掌握二叉树存储结构; 2)掌握并实现二叉树遍历的递归算法和非递归算法; 3)理解树及森林对二叉树的转换; 4)理解二叉树的应用一哈夫曼编码及WPL计算。 实验内容 1)以广义表或遍历序列形式创建一个二叉树,存储结构自选; 2)输出先序、中序、后序遍历序列; 3)二选一应用题:1)树和森林向二叉树转换;2)哈夫曼编码的应用问题。 题目可替换上述前两项实验内容) 设计与编码 1)程序结构基本设计框架 (提示:请根据所选定题目,描述程序的基本框架,可以用流程图、界面描述图、 框图等来表示) 2)本实验用到的理论知识遍历二叉树,递归和非递归的方法 (应用型

(提示:总结本实验用到的理论知识,实现理论与实践相结合。总结尽量简明扼要,并与本次实验密切相关,要求结合自己的题目并阐述自己的理解和想法) 3) 具体算法设计 1) 首先,定义二叉树的存储结构为二叉链表存储,每个元素的数 据类型Elemtype,定义一棵二叉树,只需定义其根指针。 2) 然后以递归的先序遍历方法创建二叉树,函数为CreateTree(),在输 入字符时要注意,当节点的左孩子或者右孩子为空的时候,应当输入一 个特殊的字符(本算法为“ #”),表示左孩子或者右孩子为空。 3) 下一步,创建利用递归方法先序遍历二叉树的函数,函数为 PreOrderTreeQ,创建非递归方法中序遍历二叉树的函数,函数为 InOrderTree(),中序遍历过程是:从二叉树的根节点开始,沿左子树 向下搜索,在搜索过程将所遇到的节点进栈;左子树遍历完毕后,从 栈顶退出栈中的节点并访问;然后再用上述过程遍历右子树,依次类 推,指导整棵二叉树全部访问完毕。创建递归方法后序遍历二叉树的 函数,函数为LaOrderTree()。 (提示:该部分主要是利用C、C++ 等完成数据结构定义、设计算法实现各种操作,可以用列表分步形式的自然语言描述,也可以利用流程图等描述) 4) 编码 #include #include #include typedef char DataType; #define MaxSize 100 typedef struct Node { DataType data; struct Node *lchild; struct Node *rchild; } *BiTree,BitNode;

二叉树的各种算法

二叉树的各种算法.txt男人的承诺就像80岁老太太的牙齿,很少有真的。你嗜烟成性的时候,只有三种人会高兴,医生你的仇人和卖香烟的。 /*用函数实现如下二叉排序树算法: (1)插入新结点 (2)前序、中序、后序遍历二叉树 (3)中序遍历的非递归算法 (4)层次遍历二叉树 (5)在二叉树中查找给定关键字(函数返回值为成功1,失败0) (6)交换各结点的左右子树 (7)求二叉树的深度 (8)叶子结点数 Input 第一行:准备建树的结点个数n 第二行:输入n个整数,用空格分隔 第三行:输入待查找的关键字 第四行:输入待查找的关键字 第五行:输入待插入的关键字 Output 第一行:二叉树的先序遍历序列 第二行:二叉树的中序遍历序列 第三行:二叉树的后序遍历序列 第四行:查找结果 第五行:查找结果 第六行~第八行:插入新结点后的二叉树的先、中、序遍历序列 第九行:插入新结点后的二叉树的中序遍历序列(非递归算法) 第十行:插入新结点后的二叉树的层次遍历序列 第十一行~第十三行:第一次交换各结点的左右子树后的先、中、后序遍历序列 第十四行~第十六行:第二次交换各结点的左右子树后的先、中、后序遍历序列 第十七行:二叉树的深度 第十八行:叶子结点数 */ #include "stdio.h" #include "malloc.h" #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0

#define INFEASIBLE -1 #define OVERFLOW -2 typedef int Status; typedef int KeyType; #define STACK_INIT_SIZE 100 // 存储空间初始分配量 #define STACKINCREMENT 10 // 存储空间分配增量 #define MAXQSIZE 100 typedef int ElemType; typedef struct BiTNode{ ElemType data; struct BiTNode *lchild,*rchild;//左右孩子指针 } BiTNode,*BiTree; Status SearchBST(BiTree T,KeyType key,BiTree f,BiTree &p) { if(!T){p=f;return FALSE;} else if(key==T->data){p=T;return TRUE;} else if(keydata)return SearchBST(T->lchild,key,T,p); else return(SearchBST(T->rchild,key,T,p)); } Status InsertBST(BiTree &T,ElemType e) { BiTree s,p; if(!SearchBST(T,e,NULL,p)) { s=(BiTree)malloc(sizeof(BiTNode)); s->data=e;s->lchild=s->rchild=NULL; if(!p)T=s; else if(edata)p->lchild=s; else p->rchild=s; return TRUE; } else return FALSE; } Status PrintElement( ElemType e ) { // 输出元素e的值 printf("%d ", e ); return OK; }// PrintElement

第6章树和二叉树习题

第六章 树和二叉树 一、选择题 1.算术表达式a+b*(c+d/e )转为后缀表达式后为( B ) A .ab+cde/* B .abcde/+*+ C .abcde/*++ D .2. 设有一表示算术表达式的二叉树(见下图), 它所表示的算术表达式是( C ) A. A*B+C/(D*E)+(F-G) B. (A*B+C)/(D*E)+(F-G) C. (A*B+C)/(D*E+(F-G )) D. A*B+C/D*E+F-G 3. 设树T 的度为4,其中度为1,2,3和4的结点个数分别为4,2,1 ,1 则T 中的叶子数为( D ) A .5 B .6 C .7 D .8 4. 在下述结论中,正确的是( D ) ①只有一个结点的二叉树的度为0; ②二叉树的度为2; ③二叉树的左右子树可任意 交换; ④深度为K 的完全二叉树的结点个数小于或等于深度相同的满二叉树。 A .①②③ B .②③④ C .②④ D .①④ 5. 设森林F 对应的二叉树为B ,它有m 个结点,B 的根为p,p 的右子树结点个数为n,森林F 中第一棵树的结点个数是( A ) A .m-n B .m-n-1 C .n+1 D .条件不足,无法确定 6.若一棵二叉树具有10个度为2的结点,5个度为1的结点,则度为0的结点个数是( B ) A .9 B .11 C .15 D .不确定 7.设森林F 中有三棵树,第一,第二,第三棵树的结点个数分别为M1,M2和M3。与森林F 对应的二叉树根结点的右子树上的结点个数是( D )。 A .M1 B .M1+M2 C .M3 D .M2+M3 8.一棵完全二叉树上有1001个结点,其中叶子结点的个数是( E ) A . 250 B . 500 C .254 D .505 E .以上答案都不对 9. 有关二叉树下列说法正确的是( B ) A .二叉树的度为2 B .一棵二叉树的度可以小于2 C .二叉树中至少有一个结点的度为2 D .二叉树中任何一个结点的度都为2 10.二叉树的第I 层上最多含有结点数为( C ) A .2I B . 2I-1-1 C . 2I-1 D .2I -1 11. 一个具有1025个结点的二叉树的高h 为( C ) A .11 B .10 C .11至1025之间 D .10至1024之间 12.一棵二叉树高度为h,所有结点的度或为0,或为2,则这棵二叉树最少有( B )结点 A .2h B .2h-1 C .2h+1 D .h+1 13. 一棵树高为K 的完全二叉树至少有( C )个结点 A .2k –1 B. 2k-1 –1 C. 2k-1 D. 2 k 14.对二叉树的结点从1开始进行连续编号,要求每个结点的编号大于其左、右孩子的编号,同一结点的左右孩子中,其左孩子的编号小于其右孩子的编号,可采用( C )次序的遍历 实现编号。 A .先序 B. 中序 C. 后序 D. 从根开始按层次遍历 15.一棵二叉树的前序遍历序列为ABCDEFG ,它的中序遍历序列可能是( B )

数据结构C语言实现二叉树三种遍历

实验课题一:将下图中得二叉树用二叉链表表示: 1用三种遍历算法遍历该二叉树,给出对应得输出结果; 2写一个函数对二叉树搜索,若给出一个结点,根据其就是否属于该树,输出true或者f alse。 3写函数完成习题4、31(C++版)或4、28(C版教科书)。 #include "stdio、h" #include”malloc、h" typedefstruct BiTNode { char data; structBiTNode *lchild,*rchild; }BiTNode,*BiTree; BiTree Create(BiTreeT) { char ch; ch=getchar(); if(ch=='#’) T=NULL; else { T=(BiTNode *)malloc(sizeof(BiTNode)); T-〉data=ch; T->lchild=Create(T—〉lchild); T—〉rchild=Create(T-〉rchild); } return T; } int node(BiTree T) { int sum1=0,a,b; ?if(T) { if(T!=NULL) ??sum1++;

?a=node(T->lchild); sum1+=a; b=node(T—>rchild); sum1+=b; ?} return sum1; } int mnode(BiTree T) { ?int sum2=0,e,f; if(T) { ?if((T->lchild!=NULL)&&(T-〉rchild!=NULL))?sum2++; ?e=mnode(T-〉lchild); sum2+=e; f=mnode(T-〉rchild); sum2+=f; ?} return sum2; } void Preorder(BiTree T) { if(T) { printf("%c”,T->data); Preorder(T—>lchild); Preorder(T-〉rchild); } } int Sumleaf(BiTree T) { int sum=0,m,n; if(T) { if((!T-〉lchild)&&(!T-〉rchild)) sum++; m=Sumleaf(T->lchild); sum+=m; n=Sumleaf(T—>rchild); sum+=n; } return sum; }

二叉树的层次遍历算法

二叉树层次遍历算法实现 问题描述 对任意输入的表示某二叉树的字符序列,完成二叉树的层次遍历算法,并输出其遍历结果。 注:所需Queue ADT的实现见附录。 输入描述 从键盘上输入一串字符串,该字符串为二叉树的先序遍历结果,其中如果遍历到空树时用字符”#”代替。 输出描述 从显示器上输出二叉树的按层次遍历结果。 输入与输出示例 输入: +A##/*B##C##D## 输出: +A/*DBC 输入: ABD##GJ###CFH##I### 输出: ABCDGFJHI 附录(仅供参考): #include #include #define TRUE 1 #define FALSE 0 #define MAX_QUEUE_SIZE 100

//注:需要定义ElementType类型,如果是二叉树, // 则应定义为指向二叉树中结点的指针类型 //格式如: // typedef Tree ElementType; // 队列存储结构采用循环队列 struct QueueRecord; typedef struct QueueRecord *Queue; int IsEmpty(Queue Q); int IsFull(Queue Q); Queue CreateQueue(int MaxElements); void DisposeQueue(Queue Q); void MakeEmpty(Queue Q); int Enqueue(ElementType X, Queue Q); ElementType Front(Queue Q); int Dequeue(Queue Q, ElementType &X); #define MinQueueSize ( 5 ) struct QueueRecord { int Capacity; int Front; int Rear; ElementType *Array; }; int IsEmpty(Queue Q) { return ((Q->Rear + 1)% Q->Capacity == Q->Front); } int IsFull(Queue Q) { return ((Q->Rear + 2) % Q->Capacity == Q->Front); } Queue CreateQueue(int MaxElements) { Queue Q; if (MaxElements < MinQueueSize) return NULL; Q = (Queue)malloc(sizeof(struct QueueRecord));

二叉树遍历C语言(递归,非递归)六种算法

数据结构(双语) ——项目文档报告用两种方式实现表达式自动计算 专业: 班级: 指导教师: 姓名: 学号:

目录 一、设计思想 (01) 二、算法流程图 (02) 三、源代码 (04) 四、运行结果 (11) 五、遇到的问题及解决 (11) 六、心得体会 (12)

一、设计思想 二叉树的遍历分为三种方式,分别是先序遍历,中序遍历和后序遍历。先序遍历实现的顺序是:根左右,中序遍历实现的是:左根右,后续遍历实现的是:左右根。根据不同的算法分,又分为递归遍历和非递归遍历。 递归算法: 1.先序遍历:先序遍历就是首先判断根结点是否为空,为空则停止遍历,不为空则将左子作为新的根结点重新进行上述判断,左子遍历结束后,再将右子作为根结点判断,直至结束。到达每一个结点时,打印该结点数据,即得先序遍历结果。 2.中序遍历:中序遍历是首先判断该结点是否为空,为空则结束,不为空则将左子作为根结点再进行判断,打印左子,然后打印二叉树的根结点,最后再将右子作为参数进行判断,打印右子,直至结束。 3.后续遍历:指针到达一个结点时,判断该结点是否为空,为空则停止遍历,不为空则将左子作为新的结点参数进行判断,打印左子。左子判断完成后,将右子作为结点参数传入判断,打印右子。左右子判断完成后打印根结点。 非递归算法: 1.先序遍历:首先建立一个栈,当指针到达根结点时,打印根结点,判断根结点是否有左子和右子。有左子和右子的话就打印左子同时将右子入栈,将左子作为新的根结点进行判断,方法同上。若当前结点没有左子,则直接将右子打印,同时将右子作为新的根结点判断。若当前结点没有右子,则打印左子,同时将左子作为新的根结点判断。若当前结点既没有左子也没有右子,则当前结点为叶子结点,此时将从栈中出栈一个元素,作为当前的根结点,打印结点元素,同时将当前结点同样按上述方法判断,依次进行。直至当前结点的左右子都为空,且栈为空时,遍历结束。 2.中序遍历:首先建立一个栈,定义一个常量flag(flag为0或者1),用flag记录结点的左子是否去过,没有去过为0,去过为1,默认为0.首先将指针指向根结点,将根结点入栈,然后将指针指向左子,左子作为新的结点,将新结点入栈,然后再将指针指向当前结点的左子,直至左子为空,则指针返回,flag置1,出栈一个元素,作为当前结点,打印该结点,然后判断flag,flag为1则将指针指向当前结点右子,将右子作为新的结点,结点入栈,再次进行上面的判断,直至当前结点右子也为空,则再出栈一个元素作为当前结点,一直到结束,使得当前结点右子为空,且栈空,遍历结束。 3.后续遍历:首先建立两个栈,然后定义两个常量。第一个为status,取值为0,1,2.0代表左右子都没有去过,1代表去过左子,2,代表左右子都去过,默认为0。第二个常量为flag,取值为0或者1,0代表进左栈,1代表进右栈。初始时指针指向根结点,判断根结点是否有左子,有左子则,将根结点入左栈,status置0,flag置0,若没有左子则判断结点有没有右子,有右子就把结点入右栈,status置0,flag置1,若左右子都没有,则打印该结点,并将指针指向空,此时判断flag,若flag为0,则从左栈出栈一个元素作为当前结点,重新判断;若flag为1则从右栈出栈一个元素作为当前结点,重新判断左右子是否去过,若status 为1,则判断该结点有没有右子,若有右子,则将该结点入右栈,status置1,flag置1,若没有右子,则打印当前结点,并将指针置空,然后再次判断flag。若当前结点status为2,且栈为空,则遍历结束。若指针指向了左子,则将左子作为当前结点,判断其左右子情况,按上述方法处理,直至遍历结束。

二叉树遍历算法的实现

二叉树遍历算法的实现 题目:编制二叉树遍历算法的实现的程序 一.需求分析 1.本演示程序中,二叉树的数据元素定义为非负的整型(unsigned int)数据,输 入-1表示该处没有节点 2.本演示程序输入二叉树数据均是按先序顺序依次输入 3.演示程序以用户和计算机对话方式执行,即在计算机终端上显示“提示信息” 之后,由用户在键盘上输入演示程序中规定的运算命令;相应的输入数据和运 算结果显示在其后 4.本实验一共包括三个主要程序,分别是:1)二叉树前序,中序,后序遍历递归 算法实现2)二叉树前序中序遍历非递归算法实现3)二叉树层次遍历算法实现 5.本程序执行命令包括:1)构建二叉树2)二叉树前序递归遍历3)二叉树中序 递归遍历4)二叉树后序递归遍历5)二叉树前序非递归遍历6)二叉树中序非 递归遍历7)二叉树层次遍历 6.测试数据 (1)7 8 -1 9 10 -1 -1 -1 6 11 -1 -1 12 13 -1 -1 14 -1 -1 (2)1 -1 -1 (3)7 8 -1 -1 9 -1 -1 二.概要设计 1.为实现二叉树的遍历算法,我们首先给出如下抽象数据类型 1)二叉树的抽象数据类型 ADT BiTree{ 数据对象D:D是具有相同特性的数据元素的集合 数据关系R: 若D=Φ,则R=Φ,称BiTree是空二叉树; 若D≠Φ,则R={H},H是如下二元关系: (1)在D中存在唯一的成为根的数据元素root,它在关系H下无前驱; (2)若D-{H}≠Φ,则存在D-{root}={D1,D r},且D1∩D r=Φ (3)若D1≠Φ,则D1中存在唯一的元素x1,∈H,且存在D1上的 关系H1?H;若Dτ≠Φ,则D r中存在唯一的元素x r,∈ H,且存在D r上的关系H r?H;H={,,H1,H r}; (4)(D1,{H1})是符合本定义的二叉树,成为根的左子树,(D r,{H r})是 一颗符合本定义的二叉树,成为根的右字树。 基本操作P: InitBiTree(&T); 操作结果:构造空二叉树 DestroyBiTree(&T) 初始条件;二叉树存在 操作结果:销毁二叉树 CreateBiTree(&T,definition);

二叉树的建立及几种简单的遍历方法

#include "stdio.h" #include "stdlib.h" #define STACK_INIT_SIZE 100 //栈存储空间初始分配量 #define STACKINCREMENT 10 //存储空间分配增量 //------二叉树的存储结构表示------// typedef struct BiTNode{ int data; struct BiTNode *lchild,*rchild; }BiTNode,*BiTree; //-----顺序栈的存储结构表示------// typedef struct{ BiTree *top; BiTree *base; int stacksize; }SqStack; //*************************************************** //构造一个空栈s SqStack *InitStack(); //创建一颗二叉树 BiTree CreatBiTree(); //判断栈空 int StackEmpty(SqStack *S); //插入元素e为新的栈顶元素 void Push(SqStack *S,BiTree p); //若栈不为空,则删除s栈顶的元素e,将e插入到链表L中void Pop(SqStack *S,BiTree *q); //非递归先序遍历二叉树 void PreOrderTraverse(BiTree L); //非递归中序遍历二叉树 void InOrderTraverse(BiTree L); //非递归后序遍历二叉树 void PostOrderTraverse(BiTree L); //递归后序遍历二叉树 void PostOrder(BiTree bt); //递归中序遍历二叉树 void InOrder(BiTree bt); //递归先序遍历二叉树 void PreOrder(BiTree bt); //***************************************************

输入某棵二叉树的广义表形式,建立该二叉树并按层次遍历该二叉树队列形式

掌握二叉树的二叉链表存储结构;掌握二叉树的遍历规则;利用二叉树的二叉链表存储结构实现二叉树的建树操作;利用二叉树的二叉链表存储结构实现二叉树层次遍历操作 二叉树采用二叉链表结构表示。设计并实现如下算法:输入某棵二叉树的广义表形式,建立该二叉树,并按层次遍历该二叉树----队列形式 #include #include #include #define STACK_MAX_SIZE 30 #define QUEUE_MAX_SIZE 30 typedef struct BitNode{ char data; struct BitNode *lchild; struct BitNode *rchild; }BitNode,*BiTree;; typedef struct node { BitNode *data; }node,*queue; typedef struct Queue { node *base; int front; int rear; }Queue; void InitQueue(Queue *Q) { Q->base=(queue)malloc(QUEUE_MAX_SIZE*sizeof(node)); Q->front=Q->rear=0; }

int EmptyQueue(Queue *Q) { if(Q->front==Q->rear) return 1; else return 0; } void EnQueue(Queue *Q,BitNode *e) { Q->base[Q->rear].data=e; Q->rear++; } BiTree DeQueue(Queue *Q) { int m; m=Q->front; Q->front++; return (Q->base[m].data); } char a[50]; BiTree CreatBiTree(BiTree T) { BiTree p; BiTree s[STACK_MAX_SIZE]; int top = -1; int flag; int i = 0; T=NULL; while(a[i]!='#') { switch(a[i]) {case' ':break; case '(': top++;

二叉树的遍历算法实验报告

二叉树实验报告 09信管石旭琳 20091004418 一、实验目的: 1、理解二叉树的遍历算法及应用 2、理解哈夫曼树及其应用。 3、掌握哈夫曼编码思想。 二、实验内容: 1、建立二叉树二叉链表 2、实现二叉树递归遍历算法(中序、前序、后序) 3、求二叉树高度 4、求二叉树结点个数 5、求二叉树叶子个数 6、将序号为偶数的值赋给左子树 三、主要程序: #include #include typedef int ElemType; struct BiTNode { ElemType data; struct BiTNode *lch,*rch; }BiTNode,*BiTree; struct BiTNode *creat_bt1(); struct BiTNode *creat_bt2(); void preorder (struct BiTNode *t); void inorder (struct BiTNode *t); void postorder (struct BiTNode *t); void numbt (struct BiTNode *t); int n,n0,n1,n2; void main() { int k; printf("\n\n\n"); printf("\n\n 1.建立二叉树方法1(借助一维数组建立)"); printf("\n\n 2.建立二叉树方法2(先序递归遍历建立)"); printf("\n\n 3.先序递归遍历二叉树"); printf("\n\n 4.中序递归遍历二叉树"); printf("\n\n 5.后序递归遍历二叉树"); printf("\n\n 6.计算二叉树结点个数"); printf("\n\n 7.结束程序运行");

数据结构课程设计--按层次遍历二叉树

数据结构课程设计--按层次遍历二叉树学号: 题目按层次遍历二叉树学院计算机科学与技术专业计算机科学与技术 班级 姓名 指导教师 2013年6月20日 1 1问题描述及要求 (4) 1.1问题描述 (4) 1.2任务要求.................................. 4 2 开发平台及所使用软件.............................. 4 3 程序设计思路.. (5) 3.1二叉树存储结构设计 (5) 3.2题目算法设

计 (5) 3.2.1 建立二叉树 (5) 3.2.2 遍历二叉树 (5) 3.3.3 按要求格式输出已建立的二叉 树 (6) 3.3 测试程序................................ 6 4 调试 报告.................................... 6 5 经验和体会.................................. 6 6 源程序清单及运行结果 (7) 6.1 源程序清单 (7) 6.2 运行结果................................ 9 7 参考文献................................... 10 本科生课程设计成绩评定表 (11) 2 课程设计任务书 学生姓名:专业班级:计科ZY1102班指导教师:工作单位:计算机科学系题目: 按层次遍历二叉树 初始条件:

编写按层次顺序(同一层自左至右)遍历二叉树的算法。 (1)二叉树采用二叉链表作为存储结构。 ⑵按严蔚敏《数据结构习题集(C语言版)》p44面题6.69所指定的格式输出建立的二叉树。 (3)输出层次遍历结果。 (4)自行设计测试用例。 要求完成的主要任务: (包括课程设计工作量及其技术要求,以及说明书撰写等具体要求) 课程设计报告按学校规定格式用A4纸打印(书写),并应包含如下内容:1.问题描述 简述题目要解决的问题是什么。 2. 设计 存储结构设计、主要算法设计(用类C/C++语言或用框图描述)、测试用例设计; 3. 调试报告 调试过程中遇到的问题是如何解决的; 对设计和编码的讨论和分析。 4. 经验和体会(包括对算法改进的设想) 5. 附源程序清单和运行结果。源程序要加注释。如果题目规定了测试数据,则运行结 果要包含这些测试数据和运行输出。 说明: 1. 设计报告、程序不得相互抄袭和拷贝; 若有雷同,则所有雷同者成绩均为0 分。 2. 凡拷贝往年任务书或课程设计充数者,成绩一律无效,以0 分记。时间安排: 1(第17周完成,验收时间由指导教师指定

层次遍历二叉树

课程设计 题目按层次遍历二叉树 学院计算机科学与技术 专业计算机科学与技术 班级0801 姓名陈新 指导教师孙玉芬 2012 年 6 月20 日

课程设计任务书 学生姓名:专业班级: 指导教师:孙玉芬工作单位:计算机科学系 题目: 按层次遍历二叉树 初始条件: 编写按层次顺序(同一层自左至右)遍历二叉树的算法。 (1)二叉树采用二叉链表作为存储结构。 (2)按题集p44面题6.69所指定的格式输出建立的二叉树。 (3)输出层次遍历结果。 (4)测试用例自己设计。 要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求) 课程设计报告按学校规定格式用A4纸打印(书写),并应包含如下内容: 1、问题描述 简述题目要解决的问题是什么。 2、设计 存储结构设计、主要算法设计(用类C语言或用框图描述)、测试用例设计; 3、调试报告 调试过程中遇到的问题是如何解决的;对设计和编码的讨论和分析。 4、经验和体会(包括对算法改进的设想) 5、附源程序清单和运行结果。源程序要加注释。如果题目规定了测试数据,则运行结果要包含这些测试数据和运行输出, 6、设计报告、程序不得相互抄袭和拷贝;若有雷同,则所有雷同者成绩均为0分。 时间安排: 1、第19周完成。 2、6月21日8:00到计算中心检查程序、交课程设计报告、源程序。 指导教师签名: 系主任(或责任教师)签名:年月日

数据结构课程设计 ——按层次遍历二叉树 1问题描述及要求 1.1问题描述 编写按层次顺序(同一层自左至右)遍历二叉树的算法。 1.2任务要求 编写按层次顺序(同一层自左至右)遍历二叉树的算法。 (1)二叉树采用二叉链表作为存储结构。 (2)按题集p44面题6.69所指定的格式输出建立的二叉树。 (3)输出层次遍历结果。 (4)测试用例自己设计。 2开发平台及所使用软件 Windows 7.0 , Visual C++6.0 3程序设计思路 3.1二叉树存储结构设计 typedef char ElemType; //二叉树结点值的类型为字符型 typedef struct BiTNode{ //二叉树的二叉链表存储表示 ElemType date; struct BiTNode *lchild,*rchild; //左右孩子指针 } BiTNode,*BiTree; 3.2题目算法设计 3.2.1建立二叉树 void CreateBinTree(BinTree &T){ //按先序次序输入,构造二叉链表表示的二叉树T char ch; ch=getchar(); //输入函数。 if(ch==’’) T=NULL; //输入空格时为空 else{ if(!(T=(BiTNode *)malloc(sizeof(BiTNode)))) printf("%c" "结点建立失败!") ; T->data=ch; CreateBinTree(T->lchild); CreateBinTree(T->rchild);

二叉树三种遍历算法代码_

二叉树三种遍历算法的源码 二叉树三种遍历算法的源码背诵版 本文给出二叉树先序、中序、后序三种遍历的非递归算法,此三个算法可视为标准算法,直接用于考研答题。 1.先序遍历非递归算法 #define maxsize 100 typedef struct { Bitree Elem[maxsize]; int top; }SqStack; void PreOrderUnrec(Bitree t) { SqStack s; StackInit(s); p=t; while (p!=null || !StackEmpty(s)) { while (p!=null) //遍历左子树 { visite(p->data); push(s,p); p=p->lchild; }//endwhile if (!StackEmpty(s)) //通过下一次循环中的内嵌while实现右子树遍历 { p=pop(s); p=p->rchild; }//endif }//endwhile }//PreOrderUnrec 2.中序遍历非递归算法 #define maxsize 100 typedef struct { Bitree Elem[maxsize];

int top; }SqStack; void InOrderUnrec(Bitree t) { SqStack s; StackInit(s); p=t; while (p!=null || !StackEmpty(s)) { while (p!=null) //遍历左子树 { push(s,p); p=p->lchild; }//endwhile if (!StackEmpty(s)) { p=pop(s); visite(p->data); //访问根结点 p=p->rchild; //通过下一次循环实现右子树遍历}//endif }//endwhile }//InOrderUnrec 3.后序遍历非递归算法 #define maxsize 100 typedef enum{L,R} tagtype; typedef struct { Bitree ptr; tagtype tag; }stacknode; typedef struct { stacknode Elem[maxsize]; int top; }SqStack; void PostOrderUnrec(Bitree t)

JAVA实现二叉树的前序遍历、中序遍历、后序遍历和层次遍历算法

本文由我司收集整编,推荐下载,如有疑问,请与我司联系JAVA 实现二叉树的前序遍历、中序遍历、后序遍历和层次遍历算法 JAVA 实现二叉树的前序遍历、中序遍历、后序遍历和层次遍历算法如图所 示一颗二叉树,用JAVA 实现二叉树的前序遍历、中序遍历、后序遍历和层次遍历 算法 定义树节点 public class TreeNode { int data; TreeNode leftChild; TreeNode rightChild; TreeNode(){ this.leftChild=null; this.rightChild=null; this.data=-1; TreeNode(int data){ this.leftChild=null; this.rightChild=null; this.data=data; public TreeNode(int data, TreeNode leftChild, TreeNode rightChild) { this.data = data; this.leftChild = leftChild; this.rightChild = rightChild; //其它代码省略……二叉树的前序遍历、中序遍历、后 序遍历和层次遍历算法设计 package com.bean.binarytreedemo;import java.util.ArrayList;import java.util.LinkedList;import java.util.List;import java.util.Queue;import java.util.Stack; //给定一个一维数组,表示二叉树节点的值private int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; private static List TreeNode nodeList = null; public void createBinTree() { nodeList = new LinkedList TreeNode // 将一个数组的值依次转换为Node 节点for (int nodeIndex = 0; nodeIndex array.length; nodeIndex++) { nodeList.add(new TreeNode(array[nodeIndex])); // 对前lastParentIndex-1 个父节点按照父节点与孩子节点的数字关系建立二叉树for (int parentIndex = 0; parentIndex array.length / 2 - 1; parentIndex++) { // 左孩子nodeList.get(parentIndex).leftChild = nodeList .get(parentIndex * 2 + 1); // 右孩子nodeList.get(parentIndex).rightChild = nodeList .get(parentIndex * 2 + 2); // 最后一个父节点:因为最后一个父节点可能没 有右孩子,因此单独拿出来处理int lastParentIndex = array.length / 2 - 1; // 左孩子nodeList.get(lastParentIndex).leftChild = nodeList .get(lastParentIndex * 2 + 1); // 右孩子,如果数组的长度为奇数才建立右孩子if (array.length % 2 == 1) {

二叉树遍历课程设计心得【模版】

目录 一.选题背景 (1) 二.问题描述 (1) 三.概要设计 (2) 3.1.创建二叉树 (2) 3.2.二叉树的非递归前序遍历示意图 (2) 3.3.二叉树的非递归中序遍历示意图 (2) 3.4.二叉树的后序非递归遍历示意图 (3) 四.详细设计 (3) 4.1创建二叉树 (3) 4.2二叉树的非递归前序遍历算法 (3) 4.3二叉树的非递归中序遍历算法 (4) 4.4二叉树的非递归后序遍历算法 (5) 五.测试数据与分析 (6) 六.源代码 (6) 总结 (10) 参考文献: (11)

一.选题背景 二叉树的链式存储结构是用指针建立二叉树中结点之间的关系。二叉链存储结构的每个结点包含三个域,分别是数据域,左孩子指针域,右孩子指针域。因此每个结点为 由二叉树的定义知可把其遍历设计成递归算法。共有前序遍历、中序遍历、后序遍历。可先用这三种遍历输出二叉树的结点。 然而所有递归算法都可以借助堆栈转换成为非递归算法。以前序遍历为例,它要求首先要访问根节点,然后前序遍历左子树和前序遍历右子树。特点在于所有未被访问的节点中,最后访问结点的左子树的根结点将最先被访问,这与堆栈的特点相吻合。因此可借助堆栈实现二叉树的非递归遍历。将输出结果与递归结果比较来检验正确性。。 二.问题描述 对任意给定的二叉树(顶点数自定)建立它的二叉链表存贮结构,并利用栈的五种基本运算(置空栈、进栈、出栈、取栈顶元素、判栈空)实现二叉树的先序、中序、后序三种遍历,输出三种遍历的结果。画出搜索顺序示意图。

三.概要设计 3.1.创建二叉树 3.2.二叉树的非递归前序遍历示意图 图3.2二叉树前序遍历示意图3.3.二叉树的非递归中序遍历示意图 图3.3二叉树中序遍历示意图

队列实现二叉树遍历

#include #include #include #define OVERFLOW 2 #define OK 1 #define ERROR 0 typedef struct BiTNode //定义二叉树{ char data; struct BiTNode *lchild; struct BiTNode *rchild; }BiTNode,*BiTree ; typedef struct QNode//队列节点结构体 { BiTree data; struct QNode *next; }QNode,*QueuePtr; typedef struct //队列 { QueuePtr front; QueuePtr rear; /* 队头、队尾指针*/ }LinkQueue; char CreateBiTree(BiTree&T) //创建二叉树{ char ch; scanf("%c",&ch); if(ch=='#') T=NULL; else{ if(!(T=(BiTree)malloc(sizeof(BiTNode)))) exit(OVERFLOW); T->data=ch; CreateBiTree(T->lchild); CreateBiTree(T->rchild); } return OK; } void visit(BiTree T) { if(T->data!='#')

printf("%c",T->data); } void PreOrder(BiTree T)//先序遍历 { if(T) { visit(T); PreOrder(T->lchild); PreOrder(T->rchild); } } void InOrder(BiTree T)//中序遍历 { if(T) { InOrder(T->lchild); visit(T); InOrder(T->rchild); } } void PostOrder(BiTree T)//后序遍历 { if(T) { PostOrder(T->lchild); PostOrder(T->rchild); visit(T); } } void InitQueue(LinkQueue *Q){ (*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode)); if((*Q).front) (*Q).front->next=NULL; } int QueueEmpty(LinkQueue Q){ if(Q.front==Q.rear)return 0; return 1; }

相关文档
最新文档