线索二叉树
2015-08-17 22:41
465 查看
线索二叉树分别在节点中子树为空时设为其前驱或者后继节点,其遍历中序线索二叉树效率会比较高一点。该程序可实现线索二叉树包括中序遍历等基本操作,代码如下:
xiansuotree.c主要为线索二叉树的基本操作函数
lcwxiansuo.c为主函数,主要实现其验证
该头文件包括基本的数据结构和函数的声明
运行结果如下:
建立了一个线索二叉树,然后生成中序线索二叉树,最后遍历线索二叉树
xiansuotree.c主要为线索二叉树的基本操作函数
[code]//start from the very beginning,and to create greatness //@author: Chuangwei Lin //@E-mail:979951191@qq.com //@brief: 线索二叉树的基本操作 #include "xiansuotree.h" ThreadBinTree *Previous=NULL; //前驱结点指针 /****************************************************** 函数名: 参数:bt为父结点,node为子结点,n=1表示添加左子树,n=2表示添加右子树 功能:添加数据到二叉树 *******************************************************/ int BinTreeAddNode(ThreadBinTree *bt,ThreadBinTree *node,int n) { 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; } /****************************************************** 函数名:BinTreeFind(ThreadBinTree *bt,DATA data) 参数:树节点,数据 功能:在二叉树中查找值为data的结点 *******************************************************/ ThreadBinTree *BinTreeFind(ThreadBinTree *bt,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(ThreadBinTree *bt) 参数:树节点 功能:清空二叉树,使之变为一棵空树 *******************************************************/ void BinTreeClear(ThreadBinTree *bt) { if(bt)//该节点不为空 { BinTreeClear(bt->left); //清空左子树 BinTreeClear(bt->right);//清空右子树 free(bt);//释放当前结点所占内存 bt=NULL; } return; } /****************************************************** 函数名:BinTreeThreading_LDR(ThreadBinTree *bt) 参数:树结点 功能:二叉树按中序线索化 *******************************************************/ void BinTreeThreading_LDR(ThreadBinTree *bt) { if(bt) //结点非空时,当前访问结点 { BinTreeThreading_LDR(bt->left); //递归调用,将左子树线索化 //bt->left为真就取SubTree(子树),否则为前驱 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(ThreadBinTree *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(ThreadBinTree *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->right; return prenode; //返回右下方的结点 } } /****************************************************** 函数名:ThreadBinTree_LDR(ThreadBinTree *bt,void (*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); } } /****************************************************** 函数名:oper(ThreadBinTree *p) 参数:树节点 功能:操作二叉树结点数据 *******************************************************/ void oper(ThreadBinTree *p) { printf("%c ",p->data); //输出数据 return; } /****************************************************** 函数名:InitRoot() 参数:无 功能:初始化二叉树的根 *******************************************************/ ThreadBinTree *InitRoot() { ThreadBinTree *node; if(node=(ThreadBinTree *)malloc( sizeof(ThreadBinTree))) //分配内存 { printf("\n输入根结点数据:"); scanf("%s",&node->data); node->left=NULL; node->right=NULL; return node; } return NULL; } /****************************************************** 函数名:AddNode(ThreadBinTree *bt) 参数:树节点 功能:增加特定父节点的子结点 *******************************************************/ void AddNode(ThreadBinTree *bt) { ThreadBinTree *node,*parent; DATA data; char select; if(node=(ThreadBinTree *)malloc(sizeof(ThreadBinTree))) //分配内存 { printf("\n输入二叉树结点数据:"); scanf("%s",&node->data); node->left=NULL; //设置左右子树为空 node->right=NULL; printf("输入父结点数据:"); scanf("%s",&data); parent=BinTreeFind(bt,data);//查找指定数据的结点 if(!parent)//若未找到指定数据的结点 { printf("未找到父结点!\n"); free(node); //释放创建的结点内存 return; } printf("1.添加到左子树\n2.添加到右子树\n"); do{ select=getchar(); select-='0'; if(select==1 || select==2) BinTreeAddNode(parent,node,select); //添加结点到二叉树 }while(select!=1 && select!=2); } return ; }
lcwxiansuo.c为主函数,主要实现其验证
[code]//start from the very beginning,and to create greatness //@author: Chuangwei Lin //@E-mail:979951191@qq.com //@brief: 线索二叉树操作验证函数 #include "xiansuotree.h" int main() { ThreadBinTree *root=NULL; //root为指向二叉树根结点的指针 char select; void (*oper1)(); //指向函数的指针 oper1=oper; //指向具体操作的函数 do{ printf("\n1.设置二叉树根元素 2.添加二叉树结点\n"); printf("3.生成中序线索二叉树 4.遍历线索二叉树\n"); printf("00.退出\n"); select=getchar(); 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; } select=getchar();//这里加一个去掉回车符 }while(select!='0'); BinTreeClear(root);//清空二叉树 root=NULL; return 0; }
该头文件包括基本的数据结构和函数的声明
[code]//start from the very beginning,and to create greatness //@author: Chuangwei Lin //@E-mail:979951191@qq.com //@brief: 线索二叉树基本操作的头文件 #include <stdio.h> #include <stdlib.h> typedef char DATA; //定义元素类型 //枚举 typedef enum { SubTree, //枚举值SubTree(子树)为0 Thread //Thread(线索)为1 }NodeFlag; typedef struct ThreadTree //定义线索二叉树结点类型 { DATA data; //元素数据 NodeFlag lflag; //左标志,其取值只有两种 NodeFlag rflag; //右标志 struct ThreadTree *left; //左子树结点指针 struct ThreadTree *right; //右子树结点指针 }ThreadBinTree; int BinTreeAddNode(ThreadBinTree *bt,ThreadBinTree *node,int n); ThreadBinTree *BinTreeFind(ThreadBinTree *bt,DATA data); void BinTreeClear(ThreadBinTree *bt); void BinTreeThreading_LDR(ThreadBinTree *bt); ThreadBinTree *BinTreeNext_LDR(ThreadBinTree *bt); ThreadBinTree *BinTreePrevious_LDR(ThreadBinTree *bt); void ThreadBinTree_LDR(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)); void oper(ThreadBinTree *p); ThreadBinTree *InitRoot(); void AddNode(ThreadBinTree *bt);
运行结果如下:
建立了一个线索二叉树,然后生成中序线索二叉树,最后遍历线索二叉树
相关文章推荐
- java的poi技术读取和导入Excel
- AES 加密位: 128位,加密模式:CBC, 填充模式:Zeros
- FTP定时批量下载文件(SHELL脚本及使用方法 ) (转)
- hdu 4920 Matrix multiplication (矩阵乘法)
- 用python在mysql中一次创建多个表
- 设计模式-创建型之单例模式
- C++对象模型——临时性对象 (第六章)
- NSOprationQueue 与 GCD 的区别与选用
- Mac快捷键
- Java集合(8)--HashMap源码分析
- some basic graph theoretical measures
- 解决 ionic 中的 CORS(跨域) 问题
- iOS AppsFlyer的使用注意事项
- 大话高富帅自定义Dialog
- 项目管理--项目进度管理
- C#开发工具介绍
- OD调试程序常用断点大全
- HTML5框架、背景和实体
- Sqlite学习笔记(二)&&性能测试
- FirstApp