数据结构之线索二叉树--所有功能结合
2012-09-09 19:57
633 查看
#include <stdio.h>
#include <stdlib.h>
#define QUEUE_MAXSIZE 50
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; //前驱结点指针
ThreadBinTree *BinTreeInit(ThreadBinTree *node) //初始化二叉树根结点
{
if(node!=NULL) //若二叉树根结点不为空
return node;
else
return NULL;
}
int BinTreeAddNode(ThreadBinTree *bt,ThreadBinTree *node,int n) //添加数据到二叉树
//bt为父结点,node为子结点,n=1表示添加左子树,n=2表示添加右子树
{
if(bt==NULL)
{
printf("父结点不存在,请先设置父结点!\n");
return 0;
}
switch(n)
{
case 1: //添加到左结点
if(bt->left) //左子树不为空
{
printf("左子树结点不为空!\n");
return 0;
}else
bt->left=node;
break;
case 2://添加到右结点
if( bt->right) //右子树不为空
{
printf("右子树结点不为空!\n");
return 0;
}else
bt->right=node;
break;
default:
printf("参数错误!\n");
return 0;
}
return 1;
}
ThreadBinTree *BinTreeLeft(ThreadBinTree *bt) //返回左子结点
{
if(bt)
return bt->left;
else
return NULL;
}
ThreadBinTree *BinTreeRight(ThreadBinTree *bt) //返回右子结点
{
if(bt)
return bt->right;
else
return NULL;
}
int BinTreeIsEmpty(ThreadBinTree *bt) //检查二叉树是否为空,为空则返回1,否则返回0
{
if(bt)
return 0;
else
return 1;
}
int BinTreeDepth(ThreadBinTree *bt) //求二叉树深度
{
int dep1,dep2;
if(bt==NULL)
return 0; //对于空树,深度为0
else
{
dep1 = BinTreeDepth(bt->left); //左子树深度 (递归调用)
dep2 = BinTreeDepth(bt->right); //右子树深度 (递归调用)
if(dep1>dep2)
return dep1 + 1;
else
return dep2 + 1;
}
}
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;
}
}
}
void BinTreeClear(ThreadBinTree *bt) // 清空二叉树,使之变为一棵空树
{
if(bt)
{
BinTreeClear(bt->left); //清空左子树
BinTreeClear(bt->right);//清空右子树
free(bt);//释放当前结点所占内存
bt=NULL;
}
return;
}
void BinTree_DLR(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //先序遍历
{
if(bt)//树不为空,则执行如下操作
{
oper(bt); //处理结点的数据
BinTree_DLR(bt->left,oper);
BinTree_DLR(bt->right,oper);
}
return;
}
void BinTree_LDR(ThreadBinTree *bt,void(*oper)(ThreadBinTree *p)) //中序遍历
{
if(bt)//树不为空,则执行如下操作
{
BinTree_LDR(bt->left,oper); //中序遍历左子树
oper(bt);//处理结点数据
BinTree_LDR(bt->right,oper); //中序遍历右子树/
}
return;
}
void BinTree_LRD(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //后序遍历
{
if(bt)
{
BinTree_LRD(bt->left,oper); //后序遍历左子树
BinTree_LRD(bt->right,oper); //后序遍历右子树/
oper(bt); //处理结点数据
}
return;
}
void BinTree_Level(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //按层遍历
{
ThreadBinTree *p;
ThreadBinTree *q[QUEUE_MAXSIZE]; //定义一个顺序栈
int head=0,tail=0;//队首、队尾序号
if(bt)//若队首指针不为空
{
tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列队尾序号
q[tail] = bt;//将二叉树根指针进队
}
while(head!=tail) //队列不为空,进行循环
{
head=(head+1)%QUEUE_MAXSIZE; //计算循环队列的队首序号
p=q[head]; //获取队首元素
oper(p);//处理队首元素
if(p->left!=NULL) //若结点存在左子树,则左子树指针进队
{
tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列的队尾序号
q[tail]=p->left;//将左子树指针进队
}
if(p->right!=NULL)//若结点存在右孩子,则右孩子结点指针进队
{
tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列的队尾序号
q[tail]=p->right;//将右子树指针进队
}
}
return;
}
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);//递归调用,将右子树线索化
}
}
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; //返回左下方的结点
}
}
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; //返回左下方的结点
}
}
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);
}
}
void oper(ThreadBinTree *p) //操作二叉树结点数据
{
printf("%c ",p->data); //输出数据
return;
}
ThreadBinTree *InitRoot() //初始化二叉树的根
{
ThreadBinTree *node;
if(node=(ThreadBinTree *)malloc(sizeof(ThreadBinTree))) //分配内存
{
printf("\n输入根结点数据:");
scanf("%s",&node->data);
node->left=NULL;
node->right=NULL;
return BinTreeInit(node);
}
return NULL;
}
void AddNode(ThreadBinTree *bt)
{
ThreadBinTree *node,*parent;
DATA data;
char select;
if(node=(ThreadBinTree *)malloc(sizeof(ThreadBinTree))) //分配内存
{
printf("\n输入二叉树结点数据:");
fflush(stdin);//清空输入缓冲区
scanf("%s",&node->data);
node->left=NULL; //设置左右子树为空
node->right=NULL;
printf("输入父结点数据:");
fflush(stdin);//清空输入缓冲区
scanf("%s",&data);
parent=BinTreeFind(bt,data);//查找指定数据的结点
if(!parent)//若未找到指定数据的结点
{
printf("未找到父结点!\n");
free(node); //释放创建的结点内存
return;
}
printf("1.添加到左子树\n2.添加到右子树\n");
do{
select=getch();
select-='0';
if(select==1 || select==2)
BinTreeAddNode(parent,node,select); //添加结点到二叉树
}while(select!=1 && select!=2);
}
return ;
}
int main()
{
ThreadBinTree *root=NULL; //root为指向二叉树根结点的指针
char select;
void (*oper1)(); //指向函数的指针
oper1=oper; //指向具体操作的函数
do{
printf("\n1.设置二叉树根元素 2.添加二叉树结点\n");
printf("3.生成中序线索二叉树 4.遍历线索二叉树\n");
printf("0.退出\n");
select=getch();
switch(select){
case '1': //设置根元素
root=InitRoot();
break;
case '2': //添加结点
AddNode(root);
break;
case '3'://生成中序线索二叉树
BinTreeThreading_LDR(root);
printf("\n生成中序线索二叉树完毕!\n");
break;
case '4'://遍历中序线索二叉树
printf("\n中序线索二叉树遍历的结果:");
ThreadBinTree_LDR(root,oper1);
printf("\n");
break;
case '0':
break;
}
}while(select!='0');
BinTreeClear(root);//清空二叉树
root=NULL;
getch();
return 0;
}
#include <stdlib.h>
#define QUEUE_MAXSIZE 50
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; //前驱结点指针
ThreadBinTree *BinTreeInit(ThreadBinTree *node) //初始化二叉树根结点
{
if(node!=NULL) //若二叉树根结点不为空
return node;
else
return NULL;
}
int BinTreeAddNode(ThreadBinTree *bt,ThreadBinTree *node,int n) //添加数据到二叉树
//bt为父结点,node为子结点,n=1表示添加左子树,n=2表示添加右子树
{
if(bt==NULL)
{
printf("父结点不存在,请先设置父结点!\n");
return 0;
}
switch(n)
{
case 1: //添加到左结点
if(bt->left) //左子树不为空
{
printf("左子树结点不为空!\n");
return 0;
}else
bt->left=node;
break;
case 2://添加到右结点
if( bt->right) //右子树不为空
{
printf("右子树结点不为空!\n");
return 0;
}else
bt->right=node;
break;
default:
printf("参数错误!\n");
return 0;
}
return 1;
}
ThreadBinTree *BinTreeLeft(ThreadBinTree *bt) //返回左子结点
{
if(bt)
return bt->left;
else
return NULL;
}
ThreadBinTree *BinTreeRight(ThreadBinTree *bt) //返回右子结点
{
if(bt)
return bt->right;
else
return NULL;
}
int BinTreeIsEmpty(ThreadBinTree *bt) //检查二叉树是否为空,为空则返回1,否则返回0
{
if(bt)
return 0;
else
return 1;
}
int BinTreeDepth(ThreadBinTree *bt) //求二叉树深度
{
int dep1,dep2;
if(bt==NULL)
return 0; //对于空树,深度为0
else
{
dep1 = BinTreeDepth(bt->left); //左子树深度 (递归调用)
dep2 = BinTreeDepth(bt->right); //右子树深度 (递归调用)
if(dep1>dep2)
return dep1 + 1;
else
return dep2 + 1;
}
}
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;
}
}
}
void BinTreeClear(ThreadBinTree *bt) // 清空二叉树,使之变为一棵空树
{
if(bt)
{
BinTreeClear(bt->left); //清空左子树
BinTreeClear(bt->right);//清空右子树
free(bt);//释放当前结点所占内存
bt=NULL;
}
return;
}
void BinTree_DLR(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //先序遍历
{
if(bt)//树不为空,则执行如下操作
{
oper(bt); //处理结点的数据
BinTree_DLR(bt->left,oper);
BinTree_DLR(bt->right,oper);
}
return;
}
void BinTree_LDR(ThreadBinTree *bt,void(*oper)(ThreadBinTree *p)) //中序遍历
{
if(bt)//树不为空,则执行如下操作
{
BinTree_LDR(bt->left,oper); //中序遍历左子树
oper(bt);//处理结点数据
BinTree_LDR(bt->right,oper); //中序遍历右子树/
}
return;
}
void BinTree_LRD(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //后序遍历
{
if(bt)
{
BinTree_LRD(bt->left,oper); //后序遍历左子树
BinTree_LRD(bt->right,oper); //后序遍历右子树/
oper(bt); //处理结点数据
}
return;
}
void BinTree_Level(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //按层遍历
{
ThreadBinTree *p;
ThreadBinTree *q[QUEUE_MAXSIZE]; //定义一个顺序栈
int head=0,tail=0;//队首、队尾序号
if(bt)//若队首指针不为空
{
tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列队尾序号
q[tail] = bt;//将二叉树根指针进队
}
while(head!=tail) //队列不为空,进行循环
{
head=(head+1)%QUEUE_MAXSIZE; //计算循环队列的队首序号
p=q[head]; //获取队首元素
oper(p);//处理队首元素
if(p->left!=NULL) //若结点存在左子树,则左子树指针进队
{
tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列的队尾序号
q[tail]=p->left;//将左子树指针进队
}
if(p->right!=NULL)//若结点存在右孩子,则右孩子结点指针进队
{
tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列的队尾序号
q[tail]=p->right;//将右子树指针进队
}
}
return;
}
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);//递归调用,将右子树线索化
}
}
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; //返回左下方的结点
}
}
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; //返回左下方的结点
}
}
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);
}
}
void oper(ThreadBinTree *p) //操作二叉树结点数据
{
printf("%c ",p->data); //输出数据
return;
}
ThreadBinTree *InitRoot() //初始化二叉树的根
{
ThreadBinTree *node;
if(node=(ThreadBinTree *)malloc(sizeof(ThreadBinTree))) //分配内存
{
printf("\n输入根结点数据:");
scanf("%s",&node->data);
node->left=NULL;
node->right=NULL;
return BinTreeInit(node);
}
return NULL;
}
void AddNode(ThreadBinTree *bt)
{
ThreadBinTree *node,*parent;
DATA data;
char select;
if(node=(ThreadBinTree *)malloc(sizeof(ThreadBinTree))) //分配内存
{
printf("\n输入二叉树结点数据:");
fflush(stdin);//清空输入缓冲区
scanf("%s",&node->data);
node->left=NULL; //设置左右子树为空
node->right=NULL;
printf("输入父结点数据:");
fflush(stdin);//清空输入缓冲区
scanf("%s",&data);
parent=BinTreeFind(bt,data);//查找指定数据的结点
if(!parent)//若未找到指定数据的结点
{
printf("未找到父结点!\n");
free(node); //释放创建的结点内存
return;
}
printf("1.添加到左子树\n2.添加到右子树\n");
do{
select=getch();
select-='0';
if(select==1 || select==2)
BinTreeAddNode(parent,node,select); //添加结点到二叉树
}while(select!=1 && select!=2);
}
return ;
}
int main()
{
ThreadBinTree *root=NULL; //root为指向二叉树根结点的指针
char select;
void (*oper1)(); //指向函数的指针
oper1=oper; //指向具体操作的函数
do{
printf("\n1.设置二叉树根元素 2.添加二叉树结点\n");
printf("3.生成中序线索二叉树 4.遍历线索二叉树\n");
printf("0.退出\n");
select=getch();
switch(select){
case '1': //设置根元素
root=InitRoot();
break;
case '2': //添加结点
AddNode(root);
break;
case '3'://生成中序线索二叉树
BinTreeThreading_LDR(root);
printf("\n生成中序线索二叉树完毕!\n");
break;
case '4'://遍历中序线索二叉树
printf("\n中序线索二叉树遍历的结果:");
ThreadBinTree_LDR(root,oper1);
printf("\n");
break;
case '0':
break;
}
}while(select!='0');
BinTreeClear(root);//清空二叉树
root=NULL;
getch();
return 0;
}
相关文章推荐
- SQLServer中查询表结构(表主键 、列说明、列数据类型、所有表名)的Sql语句
- 标准功能模块组件 -- “文档管理组件,网络文档管理,网络存储”,B/S版本组件可独立运行,也可集成到其他项目里,数据结构清晰思路严谨
- Redis学习笔记(一)之数据结构与丰富功能
- EXTJS学习系列提高篇:第二篇(转载)作者殷良胜,结合EXT2.2+C#.net实现将数据导入Excel的功能
- 数据结构——顺序表的创建及功能函数
- java虚拟机运行时数据区结构和功能分析
- ListView结合DataPager实现分页的功能(数据绑定时)
- 数据结构——交换二叉树中所有结点的左右子树(所有结点换位置)
- 将DataTable 覆盖到 SQL某表(包括表结构及所有数据)
- 数据结构之线索二叉树
- Spark独门秘籍:打造结构一体化、功能多元化的高效数据流水线
- 数据结构——算法(030)(在所有小写字母串大写字母前排)
- 【C++】输出比输入数值小的所有素数(数据结构实验2)
- 数据结构——前序线索二叉树及其前序遍历
- 数据结构之线索二叉树
- 标准功能模块组件 -- “文档管理组件,网络文档管理,网络存储”,B/S版本组件可独立运行,也可集成到其他项目里,数据结构清晰思路严谨
- MySQL入门--显示指定数据表的字段结构、插入指定字段的值(记录)、查看指定表中指定字段的所有记录
- 数据结构与算法学习之路:迷宫问题——回溯思想找出所有路径
- struts2+spring+mybatis结合easyUI_datagrid开发之显示所有数据
- 动画演示 Delphi 2007 IDE 功能[6] - 快速查看 Delphi 所有的核心数据类型