遍历二叉树

在二叉树的一些应用中,常常要求在树中查找具有某种特征的结点。这就提出遍历二叉树的问题,即如何按某条搜索路径巡访树中每个结点,使得每个结点均被访问一次,而且仅被访问一次。遍历对线性结构来说,是一个容易解决的问题。而对二叉树则不然,由于二叉树是一种非线性结构,每个结点都可能有两颗子树,因而需要寻找一种规律,以便使二叉树上的结点能排列在一个线性队列上,从而便于遍历。

回顾二叉树的递归定义可知,二叉树是由3个基本单元组成:根结点、左子树和右子树。因此,若能依次遍历这三部分,便是遍历了整个二叉树。例如以L、D、R分别表示遍历左子树、访问根结点和遍历右子树,则可有DLR、LDR、LRD、DRL、RDL、RLD这6种遍历二叉树的方案。若限定先左后右、则只有3种情况,分别称之为前(根)序遍历、中(根)序遍历和后(根)序遍历。基于二叉树的递归定义,可得下述遍历二叉树的递归算法定义。

1. 前序遍历二叉树的操作:

若二叉树为空,则空操作返回;否则

1.1.访问根结点中的数据;

1.2.前序遍历左子树;

1.3.前序遍历右子树。

前序遍历二叉树代码如下:

// 前序遍历二叉树
void pre_order_traversal(BTreeNode* root)
{// 二叉树不为空if( root != NULL ){// 访问根结点中的数据并打印printf("%c, ", ((struct Node*)root)->v);// 前序遍历左子树pre_order_traversal(root->left);// 前序遍历右子树pre_order_traversal(root->right);}
}

2.中序遍历二叉树的操作:

若二叉树为空,则空操作返回;否则

2.1.中序遍历左子树;

2.2.访问根结点中的数据;

2.3.中序遍历右子树。

中序遍历二叉树代码如下:

// 中序遍历二叉树
void middle_order_traversal(BTreeNode* root)
{// 二叉树不为空if( root != NULL ){// 中序遍历左子树middle_order_traversal(root->left);// 访问根结点中的数据并打印printf("%c, ", ((struct Node*)root)->v);// 中序遍历右子树middle_order_traversal(root->right);}
}

3.后序遍历二叉树的操作:

若二叉树为空,则空操作返回;否则

3.1.中序遍历左子树;

3.2.中序遍历右子树;

3.3.访问根结点中的数据。

后序遍历二叉树代码如下:

// 后序遍历二叉树
void post_order_traversal(BTreeNode* root)
{// 二叉树不为空if( root != NULL ){// 后序遍历左子树post_order_traversal(root->left);// 后序遍历右子树post_order_traversal(root->right);// 访问根结点中的数据并打印printf("%c, ", ((struct Node*)root)->v);}
}

从上述二叉树遍历的定义可知,3种遍历算法之不同处仅在于访问根结点和遍历左、右子树的先后关系。

对二叉树进行遍历的搜索路径除了上述前序、中序和后序外,还可以从上到下、从左到右按层次进行。

4.层次遍历二叉树的操作:

若二叉树为空,则空操作返回;否则

4.1. 访问根结点中的数据;

4.2. 访问第二层所有结点的数据;

4.3. 访问第三层所有结点的数据;

4.4. 。。。。。。

显然,层次遍历二叉树不能使用递归的方法,那我们应该怎么办你?我们可以应用队列来实现,队列相关内容参考数据结构之链式队列的优化。首先将根结点入列,然后循环查找队列中是否有元素,有元素就出列一次,再将出列元素代表的结点的左右子树入列,周而复始,直至队列中没有元素为止。实现代码如下:

// 层次遍历二叉树
void level_order_traversal(BTreeNode* root)
{// 二叉树不为空if( root != NULL ){// 创建队列LinkQueue* queue = LinkQueue_Create();// 队列创建成功if( queue != NULL ){// 将二叉树根结点入列LinkQueue_Append(queue, root);// 队列长度不为零,即队列中有元素while( LinkQueue_Length(queue) > 0 ){// 将结点元素出列struct Node* node = (struct Node*)LinkQueue_Retrieve(queue);// 打印出列的元素printf("%c, ", node->v);// 将结点的左右子树入列LinkQueue_Append(queue, node->header.left);LinkQueue_Append(queue, node->header.right);}}// 销毁队列LinkQueue_Destroy(queue);}
}

验证代码如下:

int main(int argc, char *argv[])
{// 创建二叉树BTree* tree = BTree_Create();// 定义二叉树内容struct Node n1 = {{NULL, NULL}, 'A'};struct Node n2 = {{NULL, NULL}, 'B'};struct Node n3 = {{NULL, NULL}, 'C'};struct Node n4 = {{NULL, NULL}, 'D'};struct Node n5 = {{NULL, NULL}, 'E'};struct Node n6 = {{NULL, NULL}, 'F'};// 插入二叉树BTree_Insert(tree, (BTreeNode*)&n1, 0, 0, 0);BTree_Insert(tree, (BTreeNode*)&n2, 0x00, 1, 0);BTree_Insert(tree, (BTreeNode*)&n3, 0x01, 1, 0);BTree_Insert(tree, (BTreeNode*)&n4, 0x00, 2, 0);BTree_Insert(tree, (BTreeNode*)&n5, 0x02, 2, 0);BTree_Insert(tree, (BTreeNode*)&n6, 0x02, 3, 0);// 显示整体二叉树printf("Full Tree: \n");BTree_Display(tree, printf_data, 4, '-');// 测试前序遍历二叉树功能printf("Pre Order Traversal:\n");pre_order_traversal(BTree_Root(tree));printf("\n");    // 测试中序遍历二叉树功能printf("Middle Order Traversal:\n");middle_order_traversal(BTree_Root(tree));printf("\n");// 测试后序遍历二叉树功能    printf("Post Order Traversal:\n");post_order_traversal(BTree_Root(tree));printf("\n");    // 测试层次遍历二叉树功能printf("Level Order Traversal:\n");level_order_traversal(BTree_Root(tree));printf("\n");// 销毁二叉树BTree_Destroy(tree);return 0;
}

显然,遍历二叉树的算法中的基本操作是访问结点,则不论按哪一种次序进行遍历,对含有n个结点的二叉树,其时间复杂度均为O(n)。所需辅助空间为遍历过程中栈的最大容量,即树的深度,在最坏情况下为n,则空间复杂度也为O(n)。

通过以上代码发现,二叉树仅仅比单链表多了一个指针域,但其遍历算法的种类却增加了很多 。递归定义的数据结构采用递归的算法进行遍历往往能达到简单可靠的效果 。

遍历二叉树代码:遍历二叉树C实现代码

数据结构之遍历二叉树相关推荐

  1. 数据结构入门----遍历二叉树和线索二叉树

    遍历二叉树(Traversing Binary Tree) 二叉树的遍历是指从根结点出发,按照某种次序访问二叉树中的所有结点,使得每个结点被访问一次且仅被访问一次. 实际应用中,查找树中符合条件的结点 ...

  2. sdut 3341数据结构实验之二叉树二:遍历二叉树

    数据结构实验之二叉树二:遍历二叉树 Time Limit: 1000MS Memory Limit: 65536K Problem Description 已知二叉树的一个按先序遍历输入的字符序列,如 ...

  3. 数据结构34:二叉树前序遍历、中序遍历和后序遍历

    链式存储结构存储的二叉树,对树中结点进行逐个遍历时,由于是非线性结构,需要找到一种合适的方式遍历树中的每个结点. 递归思想遍历二叉树 之前讲过,树是由根结点和子树部分构建的,对于每一棵树来说,都可以分 ...

  4. 数据结构与算法-- 二叉树后续遍历序列校验

    二叉树后续遍历序列校验 题目:输入一个整数数组,判断改数组是否是某个二叉搜索树的后续遍历结果,如果是返回true否则false,假设输入数组的任意两个数字不相同. 例如输入{5,7,6,9,11,10 ...

  5. 【数据结构】——构建二叉树,遍历二叉树

    二叉树的数据结构: 1 typedef struct BiTree{ 2 char item; 3 struct BiTree *lchild,*rchild; 4 }BiTree; 构建一个二叉树: ...

  6. javascript数据结构与算法--二叉树遍历(中序)

    javascript数据结构与算法--二叉树遍历(中序) 中序遍历按照节点上的键值,以升序访问BST上的所有节点 代码如下: /**二叉树中,相对较小的值保存在左节点上,较大的值保存在右节点中*** ...

  7. 数据结构实验之二叉树五:层序遍历 // oj3344 队列+二叉树 // 先序 --层次

    原题链接:oj3344 数据结构实验之二叉树五:层序遍历 Description 已知一个按先序输入的字符序列,如abd,eg,cf,(其中,表示空结点).请建立二叉树并求二叉树的层次遍历序列. In ...

  8. //数据结构:先序、中序、后序遍历二叉树。输入数据:abd##eg###c#f#h##

    //数据结构:先序.中序.后序遍历二叉树.输入数据:abd##eg###c#f#h## #include <stdio.h> #include <stdlib.h> //定义数 ...

  9. 数据结构-中序遍历二叉树(基于C++)

    二叉树是一种常见的数据结构,它由节点和边组成,每个节点最多有两个子节点,分别称为左子节点和右子节点.二叉树的遍历是指按照一定的顺序访问二叉树中的所有节点,常见的遍历方式有前序遍历.中序遍历和后序遍历. ...

最新文章

  1. GraphSAGE: GCN落地必读论文
  2. 李飞飞高徒Andrej Karpathy用AI撰写内心独白:我的“进化”之路
  3. (转载)IE 浏览器的创新
  4. Apache端口设置多域名和转发请求(虚拟域名)
  5. VTK:PolyData之ExtractSelectionCells
  6. 常系数齐次线性递推学习笔记
  7. 使用Spring Boot和MongoDB快速进行Web应用原型设计
  8. python创建一个包,如何从python包创建一个osx应用程序/ dmg?
  9. Vue3 Composition API(三)——生命周期钩子、Provide函数 和 Inject函数、封装Hook案例、setup顶层编写方式
  10. UVa 1394 约瑟夫问题的变形
  11. linux mysql 主从数据库_【Linux】【MySQL】MySQL主从数据库
  12. 输入图像四通道 输出图像四通道
  13. 加强网站安全、重构公司的门户网站项目(C# VS2003)
  14. 在 Delphi 下使用 DirectSound (1): 枚举播放设备
  15. 页面之间传递参数的几种方法荟萃(经典)
  16. 网页制作 网页下拉菜单HTML+CSS制作
  17. 电赛笔记【msp430简介——基于msp430f5529】
  18. 数据分析-项目实战:Kaggle泰坦尼克号(Titanic)沉船幸存者预测(易懂快速上手版)-二元分类-自读
  19. 新房怎么做到全屋网络覆盖?
  20. 互联网日报 | 4月14日 星期三 | 贾跃亭被终身禁入证券市场;天猫4月19日起降低开店门槛;小米正式迈入游戏手机细分赛道...

热门文章

  1. php h5读写数据库,H5学习_番外篇_PHP数据库操作
  2. php 标签页切换,vue.js实现标签页切换效果
  3. uniapp 子组件 props拿不到数据_谈一谈使用 webpack 开发时,Vue 组件之间的数据传递...
  4. matlab第七章符号对象,MATLAB语言:第七章 MATLAB符号计算
  5. 非结构化文件转移服务器,非结构化数据存储管理方法,服务器和系统 Unstructured data storage management method, and a system server...
  6. C#关键字详解第一节
  7. iOS开发之Xcode常用调试技巧总结
  8. console对象及js函数
  9. E/Trace: error opening trace file: No such file or directory
  10. 简单博弈论总结加例题解析