先根,后子树;先左子树,后右子树
二叉树的根节点 a 入队
a 的子树,根节点 b 和 c 分别入队
然后 b 的子树的根节点入队(为空)
c 的子树的根节点入队
d 的子树的根节点入队(为空)
e 的子树的根节点入队
f 的子树的根节点入队(为空)
g的子树的根节点入队(为空)结束层序遍历,整个过程就是一层层的遍历,依靠一个队列来存放临时查找的结点。
二叉树线索化

问题的提出:当以二叉链表作为存储结构时,只能找到结点的左右孩子的信息,而不能直接找到结点的任一序列的前驱与后继信息,这种信息只有在遍历的动态过程中才能得到,为了能保存所需的信息,可增加标志域;

其中:  ltag=0,lchild 域指示结点的左孩子,ltag= 1,lchild 域指示结点的前驱,rtag=0,rchild 域指示结点的右孩子,rtag=1 ,rchild 域指示结点的后驱。

以这种结构构成的二叉链表作为二叉树的存储结构,叫做线索链表。其中指向结点前驱与后继的指针叫做线索,加上线索的二叉树称之为线索二叉树。

对二叉树以某种次序遍历使其变为线索二叉树的过程叫线索化

模仿线性表的存储结构,在二叉树的线索链表上也添加一个头结点,令其lchild域的指针指向二叉树的根结点,其rchild域的指针指向中序遍历时访问的最后一个结点,同时,令二叉树中序序列中的第一个结点lchild域的指针和最后一个结点rchild域的指针均指向头结点;就像为二叉树建立了一个双向线索链表,就好比人在一个圆圈上走路,有可能存在好走的可能性。

中序遍历序列为:D B E A H F C G

中序线索二叉树, ltag=0,lchild 域指示结点的左孩子,ltag= 1,lchild 域指示结点的前驱,rtag=0,rchild 域指示结点的右孩子,rtag=1 ,rchild 域指示结点的后驱,二叉树的二叉线索存储表示:

//二叉树的二叉线索存储表示:
typedef enum{Link, Thread
} PointerTag;
//Link == 0:指针,  Thread == 1:线索

typedef struct BiThrNode{int data;BiThrNode *lchild, *rchild;//左右孩子指针域PointerTag  LTag, Rtag;//左右指针或者线索的标记
} BiTreeNode, *BiThrTree;

中序遍历序列为:D B E A H F C G

先序线索二叉树

先序序列:  A B C D E F G H K

后续线索二叉树

后序序列:  D C B H K G F E A

如何遍历线索二叉树(中序遍历为例)

结点的后继:若是叶子结点,其右标志是“1”,即右链是线索,指示其后继;否则遍历其右子树时访问的第一个结点,即右子树中最左下的结点。

结点的前趋:若其左标志为“1”,则左链为线索,指示其前驱,否则遍历左子树时的最后访问的一个结点(左子树最右下的结点)为其前驱。

什么时候采用线索链表做存储结构?

程序中所用二叉树需要经常遍历或查找结点在遍历所得线性序列中的前驱和后继时。

线索链表的遍历算法(中序找后继法)

模仿线性表的存储结构,在二叉树的线索链表上也添加一个头结点,令其lchild域的指针指向二叉树的根结点,其rchild域的指针指向中序遍历时访问的最后一个结点,同时,令二叉树中序序列中的第一个结点lchild域的指针和最后一个结点rchild域的指针均指向头结点;就像为二叉树建立了一个双向线索链表

 1 //二叉树的二叉线索存储表示:
 2 typedef enum{
 3     Link, Thread
 4 } PointerTag;
 5 //Link == 0:指针,  Thread == 1:线索
 6
 7 //线索二叉树结点结构表示
 8 typedef struct BiThrNode{
 9     int data;
10     BiThrNode *lchild, *rchild;//左右孩子指针域
11     PointerTag  LTag, RTag;//左右指针或者线索的标记
12 } BiTreeNode, *BiThrTree;
13
14 //访问结点
15 bool visit(int data)
16 {
17     //访问函数
18     return true;
19 }
20
21 //中序找后继法,线索二叉树的遍历
22 bool InOrderTraverse_Thr(BiThrTree T)
23 {
24     //二叉线索树的中序遍历,T 是头结点,令其lchild域的指针指向二叉树的根结点
25     BiTreeNode *p = T->lchild;
26     //当遍历完毕的结束条件
27     while (p != T)
28     {
29         //p 结点的左标记为指针(ltag=0)。则左指针指向左孩子
30         while (p->LTag == Link)
31         {
32             p = p->lchild;
33         }
34         //中序遍历
35         //访问
36         visit(p->data);
37         //左边没有了,访问右边,p 结点的右标记是线索, rtag == 1.且其右孩子指针没有指向根节点的时候
38         while (p->RTag == Thread && p->rchild != T)
39         {
40             //访问的是p 的后继(也就是根节点)
41             p = p->rchild;
42             //访问
43             visit(p -> data);
44         }
45         //最后找右子树
46         p = p->rchild;
47     }
48
49     return true;
50 }

如何对二叉树进行线索化?
建立线索二叉树的过程,实质上就是在遍历的过程中,检查当前结点的左右指针是否为空,如果为空,将它们改为指向其前驱或后继的线索。
设指针pre始终指向刚刚访问过的结点,指针p指向当前正在访问的结点。即pre为p的前驱结点,p为pre的后继结点,则在线索化的过程中,访问结点p所做的处理如下(以中序线索化为例)

(1)建立p的前驱线索。若p->lchild为空,则将其左标志置1,并令p->lchild指向其前驱pre

(2)建立pre的后继线索。若pre->rchild为空,则将其右标志置1,并令pre->rchild指向其后继p

(3)将pre指向p刚刚访问过的结点,即pre=p

//二叉树的二叉线索存储表示:
typedef enum{Link, Thread
} PointerTag;
//Link == 0:指针,  Thread == 1:线索//线索二叉树结点结构表示
typedef struct BiThrNode{int data;BiThrNode *lchild, *rchild;//左右孩子指针域PointerTag  LTag, RTag;//左右指针或者线索的标记
} BiTreeNode, *BiThrTree;//访问结点
bool visit(int data)
{//访问函数return true;
}//对已经存在的二叉树进行中序线索化(递归方法)
void InThreading(BiThrTree p)
{//指向上一个刚刚访问过的结点BiTreeNode *pre;if (p){// 左子树线索化InThreading(p->lchild);//如果左子树为空,则加线索if (!p->lchild){//加线索p->LTag = Thread;//指向前驱结点p->lchild = pre;}//如果右子树为空if (!pre->rchild){//加线索pre->RTag = Thread;//指向后继结点pre->rchild = p;}// 保持 pre 指向 p 的前驱pre = p;// 右子树线索化InThreading(p->rchild);}
}//新建一个线索二叉树
bool InOrderThreading(BiThrTree Thrt, BiThrTree T)
{//指向上一个刚刚访问过的结点BiTreeNode *pre;// 新建头结点if (!(Thrt = (BiTreeNode*)malloc(sizeof(BiThrNode)))){exit(1);}//头结点新建成功Thrt->LTag = Link;Thrt->RTag = Thread;//右指针回指Thrt->rchild = Thrt;// 若二叉树空,则左指针回指if (!T){Thrt->lchild = Thrt;}else{Thrt->lchild = T;pre = Thrt;// 中序遍历进行中序线索化
        InThreading(T);pre->rchild = Thrt;pre->RTag = Thread;// 最后一个结点线索化Thrt->rchild = pre;}return true;
}

二叉树的层序遍历和二叉树的线索化相关推荐

  1. LeetCode 102二叉树的层序遍历103二叉树锯齿形遍历104二叉树的最大深度

    微信搜一搜:bigsai 大家都在关注的刷题.学习数据结构和算法宝藏项目 关注回复进群即可加入力扣打卡群,欢迎划水.近期打卡: LeetCode 97交错字符串(动态规划) LeetCode 98验证 ...

  2. 一次字节面试,被二叉树的层序遍历捏爆了

    前言 大家好,我是bigsai,在数据结构与算法中,二叉树无论是考研.笔试都是非常高频的考点内容,在二叉树中,二叉树的遍历又是非常重要的知识点,今天给大家讲讲二叉树的层序遍历. 这部分很多人可能会但是 ...

  3. LeetCode Algorithm 102. 二叉树的层序遍历

    102. 二叉树的层序遍历 Ideas 二叉树的层序遍历类似于图的广度优先搜索,都是要借助队列这种数据结构来实现. 首先将根节点添加到队列中,然后就是套BFS的模板,稍微改动一下. 只要队列不为空就循 ...

  4. 遍历children_二叉树:层序遍历登场!

    登场之后,我要打十个! 看完这篇文章虽然不能打十个,但是可以迅速打五个!而且够快! 102.二叉树的层序遍历 给你一个二叉树,请你返回其按 层序遍历 得到的节点值.(即逐层地,从左到右访问所有节点). ...

  5. 力扣刷题之二叉树的层序遍历

                                                      Welcome to you, 每日一刷系列 二叉树的层序遍历 二叉树的层序遍历II 二叉树的右视图 ...

  6. 代码随想录算法训练营Day15|Leetcode102二叉树的层序遍历、Leetcode226翻转二叉树、Leetcode101对称二叉树

    Day15打卡! 时长:2h 今日感想:今天主要学习了二叉树层次遍历的思路方法和应用.题目看似简单,实则有很多细节,有时间可以做做其他相似的推荐题目~ Leetcode102 二叉树的层序遍历 题目链 ...

  7. 代码随想录【day 14 二叉树】| 层序遍历 226.翻转二叉树 101.对称二叉树

    代码随想录[day 14 二叉树]| 层序遍历 226.翻转二叉树 101.对称二叉树 层序遍历 卡哥文解 视频讲解 题目链接:102.二叉树的层序遍历 解题思路 代码实现 题目链接:107.二叉树的 ...

  8. 二叉树的前序遍历,二叉树的中序遍历,二叉树的后序遍历,二叉树的层序遍历

    二叉树的前序遍历 144. 二叉树的前序遍历 - 力扣(LeetCode) (leetcode-cn.com) 给你二叉树的根节点 root ,返回它节点值的 前序 遍历. 示例 1: 输入:root ...

  9. 二叉树的层序遍历 II

    二叉树的层序遍历 II 给定一个二叉树,返回其节点值自底向上的层序遍历. (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历) 例如: 给定二叉树 [3,9,20,null,null,15,7] ...

最新文章

  1. 为什么说GAN很快就要替代现有摄影技术了?
  2. 【C#】允许泛型方法T返回空值Null
  3. SQLServer创建用户自定义数据库用户
  4. oracle学习之三--多表查询
  5. 汽车租赁系统java窗口_共享型汽车租赁系统(SSM+MySql)
  6. 基于RadeonRays的光线追踪全局光照实现方案
  7. 先序,中序,后序线索二叉树
  8. E百科 | 基于MEC的边缘AI服务
  9. js中解析json字符串
  10. 信息学奥赛C++语言:切蛋糕
  11. 【BZOJ1433】【codevs2347】假期的宿舍,最大流
  12. 自定义Exception异常
  13. 创建MOSS网站下的新闻
  14. php strpbrk,PHP 字符串
  15. python迭代器的设计
  16. 进程占用导致linux中命令无法执行
  17. python arp断网攻击_arp断网攻击,教您arp断网攻击怎么解决
  18. 笃情开源:我和 Apache DolphinScheduler 社区的故事
  19. ue4 获取屏幕中心点坐标
  20. (*^__^*) 感恩相伴,祝福相随 (*^__^*)

热门文章

  1. 驰骋工作流引擎是如何实现自动更新的?
  2. 使用Apache Commons Configuration读取配置信息
  3. VC模仿超炫QQ界面的实现
  4. JQuery Tables 的应用(一)
  5. java 连接 MySQL
  6. 如何提高UI自动化测试的质量
  7. 勘探院读取监控数据代码设计
  8. 在Unity3D中连接WCF服务端
  9. HTML5编程之旅 第4站 Forms
  10. 【经验总结】C#常用线程同“.NET研究”步方法应用场景和实现原理