线索二叉树

定义:

对于n个结点的二叉树,在二叉链存储结构中有n+1个空链域,利用这些空链域存放在某种遍历次序下该结点的前驱结点和后继结点的指针,这些指针称为线索,加上线索的二叉树称为线索二叉树。

特点:

利用线索二叉树进行遍历时,不必采用堆栈处理,可看做是对线性结构进行访问,速度比一般二叉树的遍历速度快,且节约存储空间。并且任意一个结点都能直接找到它的前驱和后继结点。 但是结点的插入和删除麻烦,且速度也较慢。

中序线索二叉树

存储结构为
lc ltag data rtag rc
typedef struct tbtNode
{char data;//结点中的信息struct tbtNode* lc;//指向左孩子结点struct tbtNode* rc;//指向右孩子结点int ltag, rtag;//左右指针标识
}tbtNode;

当某个结点的ltag等于0时,表示该结点的lc指针不为空,即它有左孩子;当ltag等于1时,表示该结点的lc为空指针,这时就将其设置为线索。指向该结点在中序遍历中的直接前驱。
同理rtag指向该结点在中序遍历中的直接后继。
当ltag/rtag为1时,lc/rc由原来的空指针被修改为指向该结点的前驱/后继。

算法思路:

1,进行中序线索化时,初始化所有ltag和rtag都为0;
2,采用p指针指向当前结点,采用pre指针指向当前结点的前一个结点。
3,初始将pre置为NULL,通过递归入栈找到中序遍历中的第一个结点p,对它的lc和ltag修改,令其ltag=1;lc=pre;然后对pre赋值为p, 而p将被赋值为它在中序遍历中的下一个结点。
第一种情况:若p没有右子树,那么p应该被赋值为它的父结点,这通过退栈操作来完成。
第二张情况:若p有右子树,则需要将p->lc递归入栈找到p->lc结点最左边的结点
4,函数执行到最后,pre指向中序遍历的最后一个结点。需要将pre->rtag=1;pre->rc=NULL;至此结束。

线索化代码实现:

在这采用两个函数来实现中序线索化,注意!inThread函数的pre参数为对指针的引用。

void createInThread(tbtNode* p)//创建中序线索二叉树
{tbtNode* pre = NULL;if (p != NULL){inThread(p, pre);//传递pre指针的引用,否则inThread运行完毕后,pre仍为NULLpre->rc = NULL;//此时pre为二叉树中序遍历最后一个结点,其右子树定为空pre->rtag = 1;}
}
void inThread(tbtNode* p, tbtNode*& pre)//对pre指针的引用
{if (p != NULL){inThread(p->lc, pre);//对p的左子树递归调用if (p->lc == NULL ){p->lc = pre;p->ltag = 1;}if (pre != NULL&&pre->rc == NULL){pre->rc = p;pre->rtag = 1;}pre = p;p = p->rc;inThread(p, pre);//对当前p的左子树递归调用}
}

在中序线索二叉树中求后继的代码如下:

tbtNode* next(tbtNode* p)
{if (p != NULL){if (p->rtag == 1)return p->rc;tbtNode* temp = p->rc;while (temp->ltag==0)//判定条件不能写成temp->lc != NULLtemp = temp->lc;return temp;}
}

附上一个完整的例子:

#include<iostream>
typedef struct tbtNode
{char data;//结点中的信息struct tbtNode* lc;//左孩子结点struct tbtNode* rc;//右孩子结点int ltag, rtag;//左右指针标识
}tbtNode;tbtNode* initial(char* ele, int num);//用数组初始化一棵树(创建一棵完全二叉树)
void createInThread(tbtNode* p);//创建中序线索二叉树
void inThread(tbtNode* p, tbtNode*& pre);//对二叉树进行线索化
tbtNode* next(tbtNode* p);//求p结点的后继结点
void inOrder(tbtNode* p);//中序遍历(中序线索二叉树)
int main()
{using namespace std;char data[6] = { 'a', 'b', 'c', 'd', 'e', 'f' };tbtNode* p = initial(data, 6);createInThread(p);cout << "中序线索树遍历:";inOrder(p);cout << endl;return 0;
}
tbtNode* initial(char* ele, int num)
{if (num<1)return NULL;tbtNode* temp = new tbtNode[num];int i = 0;while (i < num)//将所有结点的左右子树置为空,左右标识均置为0{temp[i].lc = NULL;temp[i].rc = NULL;temp[i].ltag = 0;temp[i].rtag = 0;++i;}i = 0;while (i < num/2)//通过完全二叉树的顺序存储来创建树的结构{if (2*i+1<num)temp[i].lc = temp + 2 * i + 1;if (2*i+2<num)temp[i].rc = temp + 2 * i + 2;++i;}for (i = 0; i < num; i++)//对树中的每个结点赋值temp[i].data = ele[i];return temp;
}
void createInThread(tbtNode* p)
{tbtNode* pre = NULL;if (p != NULL){inThread(p, pre);//传递pre指针的引用,否则inThread运行完毕后,pre仍为NULLpre->rc = NULL;//此时pre为二叉树中序遍历最后一个结点,其右子树定为空pre->rtag = 1;}
}
void inThread(tbtNode* p, tbtNode*& pre)//对pre指针的引用
{if (p != NULL){inThread(p->lc, pre);//对p的左子树递归调用if (p->lc == NULL ){p->lc = pre;p->ltag = 1;}if (pre != NULL&&pre->rc == NULL){pre->rc = p;pre->rtag = 1;}pre = p;p = p->rc;inThread(p, pre);//对当前p的左子树递归调用}
}
tbtNode* next(tbtNode* p)
{if (p != NULL){if (p->rtag == 1)return p->rc;tbtNode* temp = p->rc;while (temp->ltag==0)//判定条件不能写成temp->lc != NULLtemp = temp->lc;return temp;}
}
void inOrder(tbtNode* p)
{if (p != NULL){while (p->ltag == 0)p = p->lc;//查找中序遍历第一个结点while (p != NULL)//类似链表的顺序访问进行中序遍历{std::cout << p->data << ' ';p = next(p);}}
}
后序线索二叉树

关于后序线索二叉树,在这里只介绍如何求p结点的后继。
一,如果p->rtag为1,那么p的后继为p->rc
二,若p->rtag为0时:
1,若p结点是它的父结点f的右孩子,那么父结点f为p的后继。
2,若若p结点是它的父结点f的左孩子:a,若p没有右兄弟,那么父结点f为p的后继。b,若p有右兄弟,那么p的后继为在右兄弟上后序遍历得到的第一个结点。(有些累,敲不懂了…无代码~)

线索二叉树(c/c++)相关推荐

  1. 数据结构与算法(6-4)线索二叉树

    优势:便于在中序遍历下,查找前驱和后继. 前驱/后继含义:AB中,A是B前驱,B是A后继. ltag=0时:lchild指向左孩子                ltag=1时:lchild指向前驱 ...

  2. 重拾算法(3)——用458329个测试用例全面测试二叉树和线索二叉树的遍历算法

    重拾算法(3)--用458329个测试用例全面测试二叉树和线索二叉树的遍历算法 在"上一篇"和"上上一篇"中,我给出了二叉树和线索二叉树的遍历算法.给出算法容易 ...

  3. 线索二叉树代码实现 - 数据结构和算法49

    线索二叉树代码实现 让编程改变世界 Change the world by program   程序参考代码:http://bbs.fishc.com/forum-112-1.html [buy] 获 ...

  4. 【线索二叉树详解】数据结构06(java实现)

    线索二叉树 1. 线索二叉树简介 定义: 在二叉树的结点上加上线索的二叉树称为线索二叉树. 二叉树的线索化: 对二叉树以某种遍历方式(如先序.中序.后序或层次等)进行遍历,使其变为线索二叉树的过程称为 ...

  5. 线索二叉树原理及前序、中序线索化(Java版)

    转载 原文地址:https://blog.csdn.net/UncleMing5371/article/details/54176252 一.线索二叉树原理 前面介绍二叉树原理及特殊二叉树文章中提到, ...

  6. 【数据结构-树】2.二叉树遍历与线索二叉树(图解+代码)

    一.二叉树的定义及其主要特征 1.1 二叉树的概念 二叉树是另一种树形结构,其特点是每个结点最多含两棵子树(也就是说,二叉树的度≤2). 二叉树是一种有序树,若将其左.右子树颠倒,则成为另一颗不同的二 ...

  7. 为什么说线索二叉树是一种物理结构

    1 数据结构三要素中的两个要素分别为 数据的逻辑结构 数据的存储结构,也称物理结构 它们的精确定义是: 数据的逻辑结构 数据元素之间的逻辑关系,与数据的存储无关. 数据的存储结构 数据结构在计算机中的 ...

  8. 线索二叉树(基于链表存储树结点)

    有以下场景 如果使用中序遍历,那么得到的顺序是:HDIBEAFCG,可以得知A的前驱结点为E,后继结点为F.但是,这种关系的获得是建立在完成遍历后得到的.如果我们每次想得到某个节点的前驱或者后继,都要 ...

  9. 我这么讲线索二叉树,我三岁大的表弟笑了笑

    目录: 1.线索二叉树的由来 2.线索二叉树的概念和结构 3.二叉树的线索化 4.中序线索二叉树的代码实现 5.遍历线索二叉树 1.线索二叉树的由来 我问表弟下面的一个问题: 在n个结点一个二叉链表中 ...

最新文章

  1. 从头开始学习Unity着色器
  2. linux机器启动pg数据库命令,Linux下创建Postgresql数据库的方法步骤
  3. python爬虫代码提取图片中的文字_python识别图像并提取文字的实现方法
  4. why is the configuration.js being loaded?
  5. C++学习之路 | PTA乙级—— 1030 完美数列 (25 分)(精简)
  6. perl CGI::Session
  7. slam无人车清除地图残影
  8. 计算机电路基础答案刘怀望,计算机电路基础
  9. android studio 圆形头像,Android Studio实现带边框的圆形头像
  10. 浮点数I-EEE规范
  11. Json与List、Map、entity的互相转化
  12. 人工智能02 机器进化
  13. 互联网产品经理的职责
  14. 网络直播课程:神马是敏捷?(直播时间:2014-7-14 20:00-21:00)
  15. Launcher壁纸来源
  16. html多张图片合在一块,多张照片怎么拼在一起?10张以上多图拼图方法 超简单! (全文)...
  17. java -g_【JVM】7、深入理解Java G1垃圾收集器
  18. 百度搜索资源平台上线,业内大佬送祝福!
  19. GreenPlum 介绍
  20. Office project 2019安装

热门文章

  1. 设计模式(七):桥接模式
  2. JS详细入门教程(上)
  3. 用XCA(X Certificate and key management)可视化程序管理SSL 证书(2)--生成SSL证书请求...
  4. 快学Java NIO
  5. 深入cocos2d-x中的touch事件
  6. pythonsqlite3教程_使用 Python 在线操作 sqlite3
  7. C语言经典例1-无重复数字的三位数
  8. 【错误记录】Android Studio 编译报错 ( Deprecated Gradle features were used in this build, making it incompat )
  9. 【Android 逆向】Dalvik 函数抽取加壳 ( 类加载流程分析 | DexPathList#findClass 函数分析 | DexFile#loadClassBinaryName 函数 )
  10. 【错误记录】Kotlin 编译报错 ( Type mismatch: inferred type is String? but String was expected )