线索二叉树

来源:互联网 发布:新浪微博怎么修改域名 编辑:程序博客网 时间:2024/05/29 14:05

线索二叉树分别在节点中子树为空时设为其前驱或者后继节点,其遍历中序线索二叉树效率会比较高一点。该程序可实现线索二叉树包括中序遍历等基本操作,代码如下:
xiansuotree.c主要为线索二叉树的基本操作函数

//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为主函数,主要实现其验证

//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;}

该头文件包括基本的数据结构和函数的声明

//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);

运行结果如下:
这里写图片描述
建立了一个线索二叉树,然后生成中序线索二叉树,最后遍历线索二叉树
这里写图片描述

1 0