线索二叉树操作

(1) 线索二叉树的表示:将每个节点中为空的做指针与右指针分别用于指针节点的前驱和后续,即可得到线索二叉树。

(2) 分类:先序线索二叉树,中序线索二叉树,后续线索二叉树

(3) 增加线索标志域后,二叉链表的结构如下:

typedef enum
{
SubTree,
Thread
}NodeFlag; //枚举值SubTree(子树)和Thread(线索)分别为0,1
typedef struct ThreadTree //定义线索二叉树结点类型
{
DATA data; //元素数据
NodeFlag lflag; //左标志
NodeFlag rflag; //右标志
struct ThreadTree *left; //左子树结点指针
struct ThreadTree *right; //右子树结点指针
}ThreadBinTree;

(4) 操作线索二叉树:

    a)   查找后续节点:

i.  若父节点P的右子树为空,则p->right为右线索,直接指向p的中序后续。

ii.  若父节点p的右子树不为空,则p的中序后续必是其右子树中第一个中序遍历到的节点。

    b)   查找前驱节点:

i. 若父节点p的左子树为空,则p->left为左线索,直接指向p的中序前驱节点

ii.   若父节点p的左子树不为空,则从p的左子树出发,沿该子树的右指针链表往下查找,直到一个没有右子树的节点为止,则该及诶按就是p 的中序前驱节点。

        c)  遍历线索二叉树:由于二叉树被线索化,遍历时可根据后续指针快速完成,而不使用递归调用即可完成。

(5) 对二叉树进行中序线索化。C语言实现代码如下:

/*
********************************************************************************
* 数据结构
*
*
*
* 作者: zhi-z
*
* QQ号: 2282643301
*
********************************************************************************
*文件名 : ThreadBinTree.c
*作用 : 线索二叉树 操作
*原理 :
********************************************************************************
*版本 作者 日期 说明
*V0.1 2016-10-3 初始版本
********************************************************************************
*/ #include <stdio.h>
#include <stdlib.h>
#define QUEUE_MAXSIZE 50 /********************************************************************************
*数据结构名 : ThreadTree
*参数 :
*作用 : 定义线索二叉树的数据结构
*内容 :
*
********************************************************************************/
typedef char DATA; //定义元素类型
typedef enum
{
SubTree,
Thread
}NodeFlag; //枚举值SubTree(子树)和Thread(线索)分别为0,1
typedef struct ThreadTree //定义线索二叉树结点类型
{
DATA data; //元素数据
NodeFlag lflag; //左标志
NodeFlag rflag; //右标志
struct ThreadTree *left; //左子树结点指针
struct ThreadTree *right; //右子树结点指针
}ThreadBinTree; ThreadBinTree *Previous=NULL; //前驱结点指针 /********************************************************************************
*函数名 : BinTreeInit
*参数 :node:线索二叉树的一个节点
*作用 : 初始化线索二叉树
*内容 :
*
********************************************************************************/
ThreadBinTree *BinTreeInit(ThreadBinTree *node) //初始化二叉树根结点
{
if(node!=NULL) //若二叉树根结点不为空
return node;
else
return NULL;
} /********************************************************************************
*函数名 : BinTreeAddNode
*参数 :bt为父结点,node为子结点,n=1表示添加左子树,n=2表示添加右子树
*作用 : 添加数据到二叉树
*内容 :
*
********************************************************************************/
int BinTreeAddNode(ThreadBinTree *bt,ThreadBinTree *node,int n) //添加数据到二叉树
//bt为父结点,node为子结点,n=1表示添加左子树,n=2表示添加右子树
{
if(bt==NULL)
{
printf("父结点不存在,请先设置父结点!\n");
return ;
}
switch(n)
{
case : //添加到左结点
if(bt->left) //左子树不为空
{
printf("左子树结点不为空!\n");
return ;
}else
bt->left=node;
break;
case ://添加到右结点
if( bt->right) //右子树不为空
{
printf("右子树结点不为空!\n");
return ;
}else
bt->right=node;
break;
default:
printf("参数错误!\n");
return ;
}
return ;
} /********************************************************************************
*函数名 : BinTreeLeft
*参数 :bt:为父结点
*作用 : 返回左子结点
*内容 :
*
********************************************************************************/
ThreadBinTree *BinTreeLeft(ThreadBinTree *bt) //返回左子结点
{
if(bt)
return bt->left;
else
return NULL;
} /********************************************************************************
*函数名 : BinTreeRight
*参数 :bt:为父结点
*作用 : 返回右子结点
*内容 :
*
********************************************************************************/
ThreadBinTree *BinTreeRight(ThreadBinTree *bt) //返回右子结点
{
if(bt)
return bt->right;
else
return NULL;
} /********************************************************************************
*函数名 : BinTreeIsEmpty
*参数 :bt:为父结点
*作用 : 检查二叉树是否为空,为空则返回1,否则返回0
*内容 :判断线索二叉树是否为空(操作与二叉树相同)
*
********************************************************************************/
int BinTreeIsEmpty(ThreadBinTree *bt) //检查二叉树是否为空,为空则返回1,否则返回0
{
if(bt)
return ;
else
return ;
} /********************************************************************************
*函数名 : BinTreeDepth
*参数 :bt:为父结点
*作用 : 求二叉树深度
*内容 :(操作与二叉树相同)
*
********************************************************************************/
int BinTreeDepth(ThreadBinTree *bt) //求二叉树深度
{
int dep1,dep2;
if(bt==NULL)
return ; //对于空树,深度为0
else
{
dep1 = BinTreeDepth(bt->left); //左子树深度 (递归调用)
dep2 = BinTreeDepth(bt->right); //右子树深度 (递归调用)
if(dep1>dep2)
return dep1 + ;
else
return dep2 + ;
}
} /********************************************************************************
*函数名 : BinTreeFind
*参数 :bt:为父结点,data:要查找的数据
*作用 : 在二叉树中查找值为data的结点
*内容 :(操作与二叉树相同)
*
********************************************************************************/
ThreadBinTree *BinTreeFind(ThreadBinTree *bt,DATA data) //在二叉树中查找值为data的结点
{
ThreadBinTree *p;
if(bt==NULL)
return NULL;
else
{
if(bt->data==data)
return bt;
else{ // 分别向左右子树递归查找
if(p=BinTreeFind(bt->left,data))
return p;
else if(p=BinTreeFind(bt->right, data))
return p;
else
return NULL;
}
}
} /********************************************************************************
*函数名 : BinTreeClear
*参数 :bt:为父结点
*作用 : 清空二叉树,使之变为一棵空树
*内容 :(操作与二叉树相同)
*
********************************************************************************/
void BinTreeClear(ThreadBinTree *bt) // 清空二叉树,使之变为一棵空树
{
if(bt)
{
BinTreeClear(bt->left); //清空左子树
BinTreeClear(bt->right);//清空右子树
free(bt);//释放当前结点所占内存
bt=NULL;
}
return;
} /********************************************************************************
*函数名 : BinTree_DLR
*参数 :bt:为父结点,(*oper)(ThreadBinTree *p):二叉树的操作
*作用 : 先序遍历
*内容 :
*
********************************************************************************/
void BinTree_DLR(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //先序遍历
{
if(bt)//树不为空,则执行如下操作
{
oper(bt); //处理结点的数据
BinTree_DLR(bt->left,oper);
BinTree_DLR(bt->right,oper);
}
return;
} /********************************************************************************
*函数名 : BinTree_LDR
*参数 :bt:为父结点,(*oper)(ThreadBinTree *p):二叉树的操作
*作用 : 中序遍历
*内容 :
*
********************************************************************************/
void BinTree_LDR(ThreadBinTree *bt,void(*oper)(ThreadBinTree *p)) //中序遍历
{
if(bt)//树不为空,则执行如下操作
{
BinTree_LDR(bt->left,oper); //中序遍历左子树
oper(bt);//处理结点数据
BinTree_LDR(bt->right,oper); //中序遍历右子树/
}
return;
} /********************************************************************************
*函数名 : BinTree_LRD
*参数 :bt:为父结点,(*oper)(ThreadBinTree *p):二叉树的操作
*作用 : 后序遍历
*内容 :
*
********************************************************************************/
void BinTree_LRD(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //后序遍历
{
if(bt)
{
BinTree_LRD(bt->left,oper); //后序遍历左子树
BinTree_LRD(bt->right,oper); //后序遍历右子树/
oper(bt); //处理结点数据
}
return;
} /********************************************************************************
*函数名 : BinTree_Level
*参数 :bt:为父结点,(*oper)(ThreadBinTree *p):二叉树的操作
*作用 : 按层遍历
*内容 :
*
********************************************************************************/
void BinTree_Level(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //按层遍历
{
ThreadBinTree *p;
ThreadBinTree *q[QUEUE_MAXSIZE]; //定义一个顺序栈
int head=,tail=;//队首、队尾序号
if(bt)//若队首指针不为空
{
tail=(tail+)%QUEUE_MAXSIZE;//计算循环队列队尾序号
q[tail] = bt;//将二叉树根指针进队
}
while(head!=tail) //队列不为空,进行循环
{
head=(head+)%QUEUE_MAXSIZE; //计算循环队列的队首序号
p=q[head]; //获取队首元素
oper(p);//处理队首元素
if(p->left!=NULL) //若结点存在左子树,则左子树指针进队
{
tail=(tail+)%QUEUE_MAXSIZE;//计算循环队列的队尾序号
q[tail]=p->left;//将左子树指针进队
} if(p->right!=NULL)//若结点存在右孩子,则右孩子结点指针进队
{
tail=(tail+)%QUEUE_MAXSIZE;//计算循环队列的队尾序号
q[tail]=p->right;//将右子树指针进队
}
}
return;
} /********************************************************************************
*函数名 : BinTreeThreading_LDR
*参数 :bt:为父结点
*作用 : 二叉树按中序线索化
*内容 :
*
********************************************************************************/
void BinTreeThreading_LDR(ThreadBinTree *bt) //二叉树按中序线索化
{
if(bt) //结点非空时,当前访问结点
{
BinTreeThreading_LDR(bt->left); //递归调用,将左子树线索化
bt->lflag=(bt->left)?SubTree:Thread; //设置左指针域的标志
bt->rflag=(bt->right)?SubTree:Thread;//设置右指针域的标志
if(Previous) //若当前结点的前驱Previous存在
{
if(Previous->rflag==Thread) //若当前结点的前驱右标志为线索
Previous->right=bt;//设Previous的右线索指向后继
if(bt->lflag==Thread) //若当前结点的左标志为线索
bt->left=Previous;//设当前结点的左线索指向中序前驱
}
Previous=bt;//让Previous保存刚访问的结点
BinTreeThreading_LDR(bt->right);//递归调用,将右子树线索化
}
} /********************************************************************************
*函数名 : BinTreeNext_LDR
*参数 :bt:为父结点
*作用 : 求指定结点的后继
*内容 :
*
********************************************************************************/
ThreadBinTree *BinTreeNext_LDR(ThreadBinTree *bt) //求指定结点的后继
{
ThreadBinTree *nextnode;
if(!bt) return NULL; //若当前结点为空,则返回空
if(bt->rflag==Thread) //若当前结点的右子树为空
return bt->right; //返回右线索所指的中序后继
else{
nextnode=bt->right; //从当前结点的右子树开始查找
while(nextnode->lflag==SubTree) //循环处理所有左子树不为空的结点
nextnode=nextnode->left;
return nextnode; //返回左下方的结点
}
} /********************************************************************************
*函数名 : BinTreePrevious_LDR
*参数 :bt:为父结点
*作用 : 求指定结点的前驱
*内容 :
*
********************************************************************************/
ThreadBinTree *BinTreePrevious_LDR(ThreadBinTree *bt) //求指定结点的前驱
{
ThreadBinTree *prenode;
if(!bt) return NULL; //若当前结点为空,则返回空
if(bt->lflag==Thread) //若当前结点的左子树为空
return bt->left; //返回左线索所指的中序后继
else{
prenode=bt->left; //从当前结点的左子树开始查找
while(prenode->rflag==SubTree) //循环处理所有右子树不为空的结点
prenode=prenode->left;
return prenode; //返回左下方的结点
}
} /********************************************************************************
*函数名 : ThreadBinTree_LDR
*参数 :bt:为父结点 ,(*oper)(ThreadBinTree *p):二叉树的操作
*作用 :遍历中序线索二叉树
*内容 :
*
********************************************************************************/
void ThreadBinTree_LDR(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //遍历中序线索二叉树
{
if(bt) //二叉树不为空
{
while(bt->lflag==SubTree)//有左子树
bt=bt->left; //从根往下找最左下结点,即中序序列的开始结点
do{
oper(bt); //处理结点
bt=BinTreeNext_LDR(bt);//找中序后继结点
}while(bt);
}
}

数据结构之线索二叉树——C语言实现的更多相关文章

  1. javascript实现数据结构:线索二叉树

    遍历二叉树是按一定的规则将树中的结点排列成一个线性序列,即是对非线性结构的线性化操作.如何找到遍历过程中动态得到的每个结点的直接前驱和直接后继(第一个和最后一个除外)?如何保存这些信息? 设一棵二叉树 ...

  2. 【PHP数据结构】完全二叉树、线索二叉树及树的顺序存储结构

    在上篇文章中,我们学习了二叉树的基本链式结构以及建树和遍历相关的操作.今天我们学习的则是一些二叉树相关的概念以及二叉树的一种变形形式. 完全二叉树 什么叫完全二叉树呢?在说到完全二叉树之前,我们先说另 ...

  3. 数据结构之---C语言实现线索二叉树

    //线索二叉树,这里在二叉树的基础上增加了线索化 //杨鑫 #include <stdio.h> #include <stdlib.h> typedef char ElemTy ...

  4. 【Java】 大话数据结构(9) 树(二叉树、线索二叉树)

    本文根据<大话数据结构>一书,对Java版的二叉树.线索二叉树进行了一定程度的实现. 另: 二叉排序树(二叉搜索树) 平衡二叉树(AVL树) 二叉树的性质 性质1:二叉树第i层上的结点数目 ...

  5. 数据结构《9》----Threaded Binary Tree 线索二叉树

    对于任意一棵节点数为 n 的二叉树,NULL 指针的数目为  n+1 , 线索树就是利用这些 "浪费" 了的指针的数据结构. Definition: "A binary ...

  6. 线索二叉树的理解和实现(Java)

    线索二叉树的基本概念 我们按某种方式对二叉树进行遍历,将二叉树中所有节点排序为一个线性序列,在该序列中,除第一个结点外每个结点有且仅有一个直接前驱结点:除最后一个结点外每一个结点有且仅有一个直接后继结 ...

  7. [线索二叉树] [LeetCode] 不需要栈或者别的辅助空间,完成二叉树的中序遍历。题:Recover Binary Search Tree,Binary Tree Inorder Traversal

    既上篇关于二叉搜索树的文章后,这篇文章介绍一种针对二叉树的新的中序遍历方式,它的特点是不需要递归或者使用栈,而是纯粹使用循环的方式,完成中序遍历. 线索二叉树介绍 首先我们引入“线索二叉树”的概念: ...

  8. 《数据结构与算法分析:C语言描述》读书笔记

    我们数据结构的课用了这本英文教材,作者是Mark Allen Weiss.总体来说比<算法导论>简单很多,但内容上交集非常大.其实是因为去掉了大多数证明和数学,对于没有耐心看符号和公式的人 ...

  9. 【数据结构与算法】多种语言(VB、C、C#、JavaScript)系列数据结构算法经典案例教程合集目录

    目录 1. 专栏简介 2. 专栏地址 3. 专栏目录 1. 专栏简介 2. 专栏地址 「 刘一哥与GIS的故事 」之<数据结构与算法> 3. 专栏目录 [经典回放]多种语言系列数据结构算法 ...

随机推荐

  1. 大家一起做训练 第一场 E Number With The Given Amount Of Divisors

    题目来源:CodeForce #27 E 题目意思和题目标题一样,给一个n,求约数的个数恰好为n个的最小的数.保证答案在1018内. Orz,这题训练的时候没写出来. 这道题目分析一下,1018的不大 ...

  2. TP3.2整合uplodify文件上传

    HTML中:<style>#img_upload-queue{width:120px;float:left;} /*uploadify的上传进度条样式,前面的img_upload是根据上传 ...

  3. LG3804 【模板】后缀自动机

    题意 给定一个只包含小写字母的字符串\(S\), 请你求出 \(S\) 的所有出现次数不为 \(1\) 的子串的出现次数乘上该子串长度的最大值. 对于\(100\%\) 的数据,\(|S| \leq ...

  4. streamsets rest api 转换 graphql

    原理很简单,就是使用swagger api 生成schema 然后代理请求处理api 调用 参考项目 https://github.com/rongfengliang/streamsets-graph ...

  5. sql 分组后显示每组的前几条记录

    sql 分组后显示每组的前几条记录 如   表中记录是             code       serialno             A1               1           ...

  6. kettle的资源库

    在kettle中的转换或者作业等资源的存储的仓库称为资源库:分为文件资源库.数据库资源库. 一个转换或者作业可以属于某个资源库或者一个单独的文件形态存在. 一.数据库资源库 1.1在mysql中创建一 ...

  7. js模板引擎之juicer,特别好用

    中文文档地址 https://www.npmjs.com/package/juicer Juicer基础知识:语法2  http://blog.163.com/lvshutao@126/blog/st ...

  8. 前端基础之HTML快速入门

    什么是 HTML? HTML 是用来描述网页的一种语言. HTML 指的是超文本标记语言 (Hyper Text Markup Language) HTML 不是一种编程语言,而是一种标记语言 (ma ...

  9. STORJ 有实际应用

    STORJ 有实际应用,Filezilla 支持 STORJ 的分布式协议.

  10. 笔记本设置 2K 显示屏 Intel HD Graphics 3000

    收了一台 32英寸的显示器,接到笔记 本只有 1920x1080,心想没得救了,要换笔记本才能用了. 在网上找了一圈,找到一篇说 Intel HD Graphics 3000 可以支持到 2560x1 ...