最全的二叉树数据结构算法

#include<stdio.h>
#include<stdlib.h>
#define DataType char
typedef struct node{
    DataType data;
    struct node *lchild,*rchild;
}BinTNode;
typedef BinTNode * BinTree ;
/*************************************
 * 函数作用:创建树结构(非递归)
 * 函数名:CreateTree
 * 参数列表:char *str
 * 输入示例:a(b(c(d,e),f),g)
 * 返回类型:BinTNode
*************************************/
BinTNode * CreateTree(char *str)
{
    BinTNode *St[100];//创建一个指针数组,这个数组是一个用来确定创建的子树的父亲是谁
    BinTNode *p=NULL;//创建一个指针等于空
    int top,k,j=0;//top是栈顶指针,k是创建左右孩子的标志位,j是取字符数组的索引
    top = -1;//置空栈
    char ch = str[j];//获取str中的一个字符
    BinTNode *b = NULL;//创建头指针
    while(ch!='\0')//如果不是字符串结束符
    {
        switch (ch)//根据字符进行判断
        {
            case '(':++top;St[top]=p;k=1;break;//如果是左括号,说明开始了一个新的非空子树,将上一轮子树压入堆栈,
            case ')':--top;break;//如果是右括号说明一个子树结束,栈指针回到
            case ',':k = 2;break;//如果是逗号说明要创建这棵子树的右孩子了
            default:
                p=(BinTNode *)malloc(sizeof(BinTNode));/*如果符号是一个元素则开辟空间*/
                p->data=ch;//并把新开辟的空间中的data赋值为这个元素
                p->lchild = p->rchild = NULL;//将新开辟的空间的左右子树都置为空
                if(b == NULL)//如果表达式为真说明此时树的头指针还没有指向任何节点
                {
                    b=p;//如果创建树时头指针还没有指向任何东西就将头指针指向这棵树,因为这棵树是所有树的父亲
                }
                else//否则头指针已经指向了某个节点
                {
                    switch (k)
                    {
                        case 1:St[top]->lchild = p;break;//将此树的父亲的左孩子指针指向这棵树
                        case 2:St[top]->rchild = p;break;//将此树的父亲的右孩子指针指向这棵树
                    }
                }
                break;//退出switch
        }
        j++;//j++为取下一个字符做准备
        ch = str[j];//取下一个字符
    }
    return b;
}
/*************************************
 * 函数作用:创建树结构(非递归)
 * 函数名:CreateBinTree
 * 参数列表:BinTree bt
 * 输入示例:abcdefjh@#
 * 返回类型:BinTree
*************************************/
BinTree CreateBinTree(BinTree bt)
{
    BinTNode *Q[100];//定义一个队列,用来保存树的关系
    BinTNode *s;//用来为下面开辟空间而准备的野指针
    int front,rear;//定义队列的头尾指针
    char ch;//用来保存字符数据的中间变量
    ch = getchar();//获取第一个字符
    bt = NULL;//将二叉树置空
    front = 0;//将对头指针置为0
    rear = 0;//将队尾指针置为0,队尾和队首指针指在一起表示队列是空的
    while(ch!='#')//如果不是结束符
    {
        if (ch!='@')//如果不是空节点
        {
            s = (BinTNode *)malloc(sizeof(BinTNode));//申请一个树节点的空间
            s->data=ch;//把树的数据域赋值为ch
            s->lchild = s->rchild = NULL;//将树的左右子树置空
            Q[rear]=s;//将在这个节点压入队列
            ++rear;//队尾指针自增
            if(rear==1)//如果rear是1代表这个节点是跟节点
            {
                bt = s;//把这个节点连接在头节点上
            }
            else//如果这个节点不是头节点
            {
                if(s!=NULL && Q[front]!=NULL)//并且这个节点                        s!=NULL有用么 头指针不为空有什么用
                {
                    if(rear % 2 == 0)//如果这个节点可以整除2说明这个节点必然是左子树(树的左儿子在序列中是2n(n代表这个树的序号))
                    {
                        Q[front]->lchild=s;//将头指针的左儿子指向这棵树
                    }
                    else//否则说明这个节点应该是右子树
                    {
                        Q[front]->rchild=s;//将右儿子指向这个节点
                    }
                    
                }
                if(rear %2 != 0)//如果已经输入完一颗子树也就是输入完了这棵子树的左右两个孩子
                {
                    ++front;//换下一棵空着的树
                }
            }
        }
        ch = getchar();//获取下一个字符
    }
    return bt;//循环结束返回头节点
}
/*************************************
 * 函数作用:树的前序遍历
 * 函数名:Preorder
 * 参数列表:BinTree bt
 * 返回类型:void
*************************************/
void Preorder(BinTree bt)
{
    if(bt!=NULL)
    {
        printf("%c",bt->data);
        if(bt->lchild || bt->rchild)//这个节点不是子叶节点
        {
            printf("(");
            Preorder(bt->lchild);
            printf(",");
            Preorder(bt->rchild);
            printf(")");
        }
    }
}
/*************************************
 * 函数作用:树的中序遍历
 * 函数名:Inorder
 * 参数列表:BinTree bt
 * 返回类型:void
*************************************/
void Inorder(BinTree bt)
{
    if(bt!=NULL)
    {
        Inorder(bt->lchild);
        printf("%c",bt->data);
        Inorder(bt->rchild);
    }
}
/*************************************
 * 函数作用:树的后序遍历
 * 函数名:Postorder
 * 参数列表:BinTree bt
 * 返回类型:void
*************************************/
void Postorder(BinTree bt)
{
    if(bt!=NULL)
    {
        Postorder(bt->lchild);
        Postorder(bt->rchild);
        printf("%c",bt->data);
    }
}
/*************************************
 * 函数作用:树的中序遍历(非递归)
 * 函数名:Inorder1
 * 参数列表:BinTree bt
 * 返回类型:void
*************************************/
void Inorder1(BinTree bt)
{
    BinTNode *ST[100];//用指针数组来模拟栈
    int top = 0;//初始化栈顶指针
    ST[top]=bt;//把头节点压入堆栈
    do{
        while(ST[top]!=NULL)//把跟节点和所有左子树都压入堆栈
        {
            ++top;//栈顶指针加一
            ST[top] = ST[top-1]->lchild;//将上一个节点的左子树压入堆栈
        }
        --top;//全部压入后top指向了一个空节点,所以回退到上一个右元素的节点
        if(top>=0)//回退后如果不是-1也就是说树不是一个元素没有
        {
            printf("%c",ST[top]->data);//访问这个节点,因为这个节点已经没有左子树了
            ST[top] = ST[top]->rchild;//将这个子树的右子树压入堆栈,下一次循环会把右子树的所有左子树压入堆栈
        }
    }while(top != -1);
}
/*************************************
 * 函数作用:树的前序遍历(非递归)
 * 函数名:Preorder1
 * 参数列表:BinTree bt
 * 返回类型:void
*************************************/
void Preorder1(BinTree bt)
{
    BinTNode *ST[100];//用指针数组来模拟栈
    BinTNode *s = bt;//定义临时指针指向bt
    int top = 0;//初始化栈顶指针
    if(s!=NULL)//如果这棵树不是个空树
    {
        while(top>=0)
        {
            printf("%c",s->data);//访问节点
            if(s->rchild!=NULL)
                ST[top++] = s->rchild;//并把右子树压入堆栈
            if(s->lchild!=NULL)
                s = s->lchild;//s指向这棵树的左子树
            else
                s = ST[--top];
        }
    }
}
/*************************************
 * 函数作用:树的后序遍历(非递归)
 * 函数名:Postorder1
 * 参数列表:BinTree bt
 * 返回类型:void
*************************************/
void Postorder1(BinTree bt)
{
    BinTNode *ST[100];//用指针数组来模拟栈
    BinTNode *s = bt;//定义临时指针指向bt
    int topl = 0,topr = 99;//初始化栈顶指针
    if(s!=NULL)//如果这棵树不是个空树
    {
        while(topr<=99)
        {
            ST[topl++] = s;
            if(s->lchild == NULL && s->rchild == NULL)
            {
                s = ST[++topr];
                continue;
            }
            if(s->lchild!=NULL)
                ST[topr--] = s->lchild;
            if(s->rchild!=NULL)
                s = s->rchild;
        }
        while(1)
        {
            --topl;
            if(topl>=0)
                printf("%c",ST[topl]->data);
            else
                break;
        }   
    }
}       
/*************************************
 * 函数作用:树的层序遍历
 * 函数名:TransLevel
 * 参数列表:BinTree bt
 * 返回类型:void
*************************************/
void TransLevel(BinTree bt)
{
    BinTNode *ST[100];//用指针数组来模拟栈
    BinTNode *s = bt;//定义临时指针指向bt
    int h = 0,l = 0;
    if(s!=NULL)//如果这棵树不是个空树
    {
        ST[l++] = s;
        do{
            s = ST[(h++)%100];
            printf("%c",s->data);
            if(s->lchild!=NULL)
                ST[(l++)%100] = s->lchild;
            if(s->rchild!=NULL)
                ST[(l++)%100] = s->rchild;
        }while(h != l);
    }
}       
/*************************************
 * 函数作用:求树的深度
 * 函数名:BinTreeDepth
 * 参数列表:BinTree bt
 * 返回类型:int
*************************************/
int BinTreeDepth(BinTree bt)
{
    int LDepth = 0,RDepth = 0;
    if(bt!=NULL)
    {
        if(bt->lchild!=NULL)
            LDepth = BinTreeDepth(bt->lchild);
        if(bt->rchild!=NULL)
            RDepth = BinTreeDepth(bt->rchild);
        return LDepth>RDepth?++LDepth:++RDepth;
    }
    else
    {
        return 0;
    }
}
/*************************************
 * 函数作用:在树中查找某元素
 * 函数名:FindBT
 * 参数列表:BinTree bt,DataType x
 * 返回类型:BinTree 
*************************************/
BinTree  FindBT(BinTree bt,char x)
{
    if(bt!=NULL)
    {
        BinTree l,r;
        l = r = NULL;
        if(bt->data == x)
            return bt;
        l = FindBT(bt->lchild,x);
        r = FindBT(bt->rchild,x);
        return l>r?l:r;
    }
    else
    {
        return NULL;
    }
}
/*************************************
    // if(test!=NULL)
    //     printf("%d",Level(h,test));
 * 函数作用:在树中查找某节点所在层次
 * 函数名:Level
 * 参数列表:BinTree bt,BinTNode *p
 * 返回类型:int
*************************************/
int Level(BinTree bt,BinTNode *p)
{
   if(bt!=NULL)
    {
        if(bt == p)
            return 1;
        int l,r;
        l = r = 0;
        l = Level(bt->lchild,p);
        r = Level(bt->rchild,p);
        if(l == -1&& r == -1)
            return -1;
        else
            return (l>r?l:r)+1;
    }
    return -1;
}
int main(int argc, char const *argv[])
{
    //char a[] = "a(b,c(d(e,f),g))";
    //BinTree h;
    //h = CreateTree(a);
    // h = CreateBinTree(h);
    // Preorder(h);
    // Inorder(h);
    // Postorder(h);
    // Inorder1(h);
    // Preorder1(h);
    // Postorder1(h);
    // TransLevel(h);
    // printf("%d",BinTreeDepth(h));
    // BinTree test = FindBT(h,'k');
    // if(test!=NULL)
    //     printf("%c",test->data);
    // BinTree test = FindBT(h,'a');
    // if(test!=NULL)
    //     printf("%d",Level(h,test));
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值