数据结构课程设计~二叉树的应用(二叉树)

/*
    二叉树的应用(二叉树)
    
    [问题描述]
        编程实现二叉树的建立,先序、中序、后序(递归和非递归方法)、层序遍历,二叉树的高度、繁茂度,
    交换左右子树,统计叶子节点的数目,判断是否为完全二叉树,按树的形态在屏幕上打印输出。
    [基本要求]
        (1) 从文件中读入建树信息,树的节点数目不小于20个,树的高度不小于4。
        (2) 建树信息采用两行英文字符表示,每个英文字符代表一个结点,第1行为树的中序遍历结果,
    第2行为树的后序遍历结果。
    [名词注释]
        二叉树的繁茂度:为各层结点数的最大值与树的高度的乘积
        完全二叉树:
                a:所有节点只可能出现在最大的两层上
                b:对于任何节点,若其右子树的层高为k,则其左子树可能为k或者是k+1

     注意:该程序是在vc++6.0中运行成功,同时需要安装easyx插件才能正常运行,实现图形界面

     测试数据:ABD##EF###C#GHJ#K###I##

            
*/
#include <stdio.h>
#include <malloc.h>
#include <graphics.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>

#define  TRUE  1
#define  FALSE 0

//树型结构体
typedef struct Node
{
    char data;
    struct Node *Lchild;
    struct Node *Rchild;
}BiTNode,*BiTree;

//栈元素结构体
typedef struct node
{
    BiTree tree;
    struct node *next;
}seqstack,*stack;

//队列元素结构体
typedef struct node1
{
    BiTree tree;
    struct node1 *next;
 } Qnode;

//队列的队头和队尾元素指针
 typedef struct
 {
     Qnode *front;
     Qnode *rear;
 }LQnode;

//用于统计每一层叶子节点个数
typedef struct
{
    int countleaf[10];
    int countpoint[10];
    int depth;
}countPoint;
/*typedef struct
{
    char mid[100];
    char post[100];
}tree; */
countPoint point;
//用于统计节点数的全局变量
int count1=0,count2=0;
//用于寻根函数
BiTree tree[100];
int i=0;
//tree list;//定义存储树序列的全局变量


stack init_seq();//初始化空栈,创建站顶元素,返回栈顶指针
int isempty(stack sq);//置栈空
void push(stack sq,BiTree tr);//进栈
void pop(stack sq,BiTree *p);//出栈
BiTree top(stack sq);//取栈顶数据

LQnode *init_LQnode();
int isempty_L(LQnode *q);
void in_LQnode(LQnode *q,BiTree tr);
void out_LQnode(LQnode *q,BiTree *tr);

void creat_Btree(BiTree *root,FILE *fp);//创建树
void pre_visit(BiTree root);//非递归先序遍历
void re_pro_visit(BiTree root);//递归先序遍历
void mid_visit(BiTree root);//非递归中序遍历
void re_mid_visit(BiTree root);//递归中序遍历
void post_visit(BiTree root);//非递归先后序遍历
void re_post_visit(BiTree root);//递归先后序遍历
void leval_visit(BiTree root);//层次遍历
BiTree parent (BiTree root,BiTree leaf);//搜索双亲函数
void print_path(BiTree root);//打印路径函数
void swap_tree(BiTree root);//交换左右子树
void post_visit_point(BiTree root);//递归统计有两个孩子节点和至少有一个孩子的节点,间接统计只有一个孩子的节点
int mid_visit_leaf(BiTree root);//输出叶子节点个数和叶子节点
void pro_visit_leaf(BiTree root);//先序统计叶子节点
int postTreeDepth(BiTree root);//求树的深度
void printTree(BiTree root,int h);//打印树
int * count_leaf_Level(BiTree root,int k);//某一层k的叶子结点个数(待修改)
void print_count_leaf(BiTree root); //统计每一层的叶子节点个数
int Lush_degree(BiTree root);//二叉树的繁茂度
int  IsComBinTree(BiTree root);//判定是否为完全二叉树

FILE * file();
 
void visit(char ch);


int main ()
{
    system("title 树操作系统 ");
    int leaf,depth;//叶子节点数和树的深度
    FILE *fp;
    BiTree root;
    fp=FILE * file();
    creat_Btree(&root,fp);//创建树
    return 0;
}

/**********************界面操作*********************/
void main_menu()
{
    int choice,choice1;
    printf("\n\n\n\n");
    printf("\n\t\t************欢迎进入树操作系统***********\n");
    printf("\t\t                                          \n");
    printf("\t\t\t 1、遍历树\n");
    printf("\t\t\t 2、交换左右子树\n");
    printf("\t\t\t 3、输出叶子节点个数和叶子节点\n");
    printf("\t\t\t 4、树的深度 \n");
    printf("\t\t\t 5、统计每一层的叶子节点个数 \n");
    printf("\t\t\t 6、判定是否为完全二叉树 \n");
    printf("\t\t\t 7、二叉树的繁茂度 \n");
    printf("\n\t\t************谢谢使用树操作系统***********\n");
    InputBox(ch, 100, "请输入您的选择" );
    sscanf(ch,"%d",&choice);
    
    switch(choice)
    {
        case 1:{
                system(cls);
                printf("\n\n\n\n");
                printf("\n\t\t************欢迎进入树操作系统***********\n");
                printf("\t\t                                          \n");
                printf("\t\t\t 1、层次遍历\n");
                printf("\t\t\t 2、非递归先序遍历\n");
                printf("\t\t\t 3、递归先序遍历\n");
                printf("\t\t\t 4、非递归中序遍历 \n");
                printf("\t\t\t 5、递归中序遍历 \n");
                printf("\t\t\t 6、非递归后序遍历 \n");
                printf("\t\t\t 7、递归后序遍历 \n");
                printf("\n\t\t************谢谢使用树操作系统***********\n");
                InputBox(ch, 100, "请输入您的选择" );
                sscanf(ch,"%d",&choice1);
                break;
                }
        case 2:{swap_tree(root);break;}
        case 3:{mid_visit_leaf(root);break;}
        case 4:{postTreeDepth(BiTree root);;break;}
            
            
    }
}
/********************栈操作 ***********************/
//初始化空栈,创建站顶元素,返回栈顶指针
stack init_seq()
{
    stack sq;
    sq=(stack)malloc(sizeof(seqstack));
    sq->next=NULL;
    return sq;    
}

//置栈空
int isempty(stack sq)
{
    if(sq->next==NULL)
        return 1;
    return 0;
}

//入栈函数
void push(stack sq,BiTree tr)
{
    stack q;
    q=(stack)malloc(sizeof(seqstack));
    q->tree=tr;
    q->next=sq->next;
    sq->next=q;
//    free(q);    
}

//出栈函数
void pop(stack sq,BiTree *p)
{
//    char *ch;
    stack q;
    q=sq->next;
    sq->next=q->next;
    (*p)=q->tree;
    free(q);
}

//取栈顶元素
BiTree top(stack sq)
{
    BiTree p;
    if(!isempty(sq))
    {
        p=sq->next->tree;
    }
    return p;
}

/**********************队列操作*******************/
//初始化队列
 LQnode *init_LQnode()
 {
     LQnode *q;
     Qnode *p;
     q=(LQnode*)malloc(sizeof(LQnode));
     p=(Qnode*)malloc(sizeof(Qnode));
     p->next=NULL;
     q->front=q->rear=p;
     return q;
 }
 int isempty_L(LQnode *q)
 {
     if(q->front==q->rear)
         return 1;
     else
         return 0;
 }
 //入队
 void in_LQnode(LQnode *q,BiTree tr)
 {
     Qnode *p;
     p=(Qnode*)malloc(sizeof(Qnode));
     p->tree=tr;
     p->next=NULL;
     q->rear->next=p;
     q->rear=p;
 }

//出队
 void out_LQnode(LQnode *q,BiTree *tr)
 {
     if(!isempty_L(q))
     {
         Qnode *p;
         p=(Qnode*)malloc(sizeof(Qnode));
         p=q->front->next;
         q->front->next=p->next;
         *tr=p->tree;
         free(p);
         if(q->front->next==NULL)
             q->rear=q->front;
     }
 }
 /****************文件操作********************/
//打开文件操作
FILE * file()
{
    FILE *fp;
    char filename[]="树.txt";
    fp=fopen(filename,"r");
    if(fp==NULL)
    {
        printf("\n 打开文件失败,%s可能不存在,请先到对应文件夹下建立该文件!\n",filename);
        exit(1);
    }
    return fp;
}
/********************文件操作**********************/
 
/********************二叉树操作**********************/
//扩展先序建立二叉树
//递归一次便给当前节点的数据域赋值,然后利用递归
//一次给该结点的左右子树赋值,实现二叉树的创建
void creat_Btree(BiTree *root,FILE *fp)
{
    char ch;
    ch=fgetc(fp);
    if(ch==EOF)
        return ;
    if(ch=='#')
        (*root)=NULL;
    else{
        (*root)=(BiTree)malloc(sizeof(BiTNode));
        (*root)->data=ch;
        creat_Btree(&((*root)->Lchild),fp);
        creat_Btree(&((*root)->Rchild),fp);
    }     
}
//利用中序后序遍历建立二叉树
void creat_mid_post_tree(BiTree *root)
{
    
}
//非递归先序遍历
/*    首先对根节点和左子树以此访问并且顺序入栈,如果当前访问节点的左子树为空,
    将该节点A退栈,访问该子树的右子树,对该节点的右子树按照上述方法进行遍历访问,访问完之后退回到,
    A节点的双亲节点,将其退栈,同样的方法访问其右子树,以此类推访问完整个二叉树。
*/
void pre_visit(BiTree root)
{
     stack s;
     BiTree p;
     s=init_seq();
     p=root;
     while(p!=NULL||!isempty(s))
     {
         while(p!=NULL)
         {
             visit(p->data);
             push(s,p);
             p=p->Lchild;
         }
         if(!isempty(s))
         {
             pop(s,&p);
             p=p->Rchild;
         }
     }    
}

//递归实现先序遍历
void re_pro_visit(BiTree root)
{
    if(root)
    {
        visit(root->data);
        re_pro_visit(root->Lchild);
        re_pro_visit(root->Rchild);
    }
}

//非递归中序遍历
/*    首先通过循环不断将节点入栈,直到找到左子树的最左侧的节点,从该节点进行遍历,先访问该结点,然后退栈,访问根节点,
    再然后进入该根节点的右子树,同样的方法进行访问,访问完之后,将该根节点的根节点退栈,同样的方法访问他的右子树,一直循环直至
    栈为空且,辅助指针为空,表示二叉树访问完
*/
void mid_visit(BiTree root)
{
    stack s;
    BiTree p;
    s=init_seq();
    p=root;
    while(p!=NULL||!isempty(s))
    {
        while(p!=NULL)
        {
            push(s,p);        
             p=p->Lchild;
         }
         if(!isempty(s))
         {
             pop(s,&p);
            visit(p->data);
             p=p->Rchild;
         }
     }         
}

//递归实现中序遍历
void re_mid_visit(BiTree root)
{
    if(root)
    {
        re_mid_visit(root->Lchild);
        visit(root->data);
        re_mid_visit(root->Rchild);
    }
}

//非递归后序遍历
/*    首先通过循环不断将节点入栈,直到找到左子树的最左侧的节点,然后取栈顶元素,即该结点,及对其右子树进行考察,
    如果其右子树是空或者是已经访问过,则退栈,访问站顶元素,并将其地址赋值给第二辅助标记指针变量,并将第一指
    针变量置为空,便于再退栈,访问下一个节点的数据,否则如果该节点的右子树不为空且未被访问过,则同样的访问该节点的右子树。
*/
void post_visit(BiTree root)
{
    stack s;
    s=init_seq();
    BiTree p,q;
    p=root;q=NULL;
    while(!isempty(s)||p!=NULL)
    {
        while(p!=NULL)
        {
            push(s,p);
            p=p->Lchild;
        }
        if(!isempty(s))
        {
            p=top(s);
            if((p->Rchild==NULL)||(p->Rchild==q))
            {
                pop(s,&p);
                visit(p->data);
                q=p;
                p=NULL;        
            }
            else
                p=p->Rchild;
        }
     }     
 }

//递归实现后序遍历
void re_post_visit(BiTree root)
{
    if(root)
    {
        re_post_visit(root->Lchild);
        re_post_visit(root->Rchild);
        visit(root->data);
    }

}

//层次遍历
void leval_visit(BiTree root)
{
    LQnode *q;
    q=init_LQnode();
    BiTree p;
    in_LQnode(q,root);
    while(!isempty_L(q))
    {
        out_LQnode(q,&p);
        visit(p->data);
        if(p->Lchild!=NULL)
            in_LQnode(q,p->Lchild);
        if(p->Rchild!=NULL)
            in_LQnode(q,p->Rchild);
    }    
}

/*
//主体部分分为查找叶子节点、寻找双亲函数和打印路径三部分
void pro_visit_leaf(BiTree root)
{
    if(root)
    {
        if(root->Lchild==NULL&&root->Rchild==NULL)
        {
            tree[i]=root;
        //    visit(tree[i]->data);
            i++;        
        }
        pro_visit_leaf(root->Lchild);
        pro_visit_leaf(root->Rchild);
    }
}
*/
//搜索某一节点的双亲
BiTree parent (BiTree root,BiTree leaf)
{
    BiTree p;
    if(root==NULL)
        return NULL;
    if(root->Lchild==leaf||root->Rchild==leaf)
        return root;
    p=parent(root->Lchild,leaf);
    if(p!=NULL)
        return p;
    else
        return (parent(root->Rchild,leaf));
}

//打印某一节点到根节点的路径
void print_path(BiTree root)
{    BiTree p;
    char ch[100];
    int k;
    for(int j=0;j<i;j++)
    {
        k=0;
        p=tree[j];
//        printf("%c:",p->data);
        visit(p->data);
        while(p->data!=root->data)
        {
            p=parent (root,p);
            ch[k]=p->data;
            k++;
        }
        while(k>=1)
        {
            visit(ch[k-1]);
            k--;
        }
        printf("\n");
    }
}

//交换左右子树
/*通过递归实现,原理就是将换两个变量的值*/
void swap_tree(BiTree root)
{
    BiTree p;
    p=root->Lchild;
    root->Lchild=root->Rchild;
    root->Rchild=p;
    if(root->Lchild!=NULL)
        swap_tree(root->Lchild);
    if(root->Rchild!=NULL)
        swap_tree(root->Rchild);
}

//递归统计有两个孩子节点和至少有一个孩子的节点,间接统计只有一个孩子的节点
void post_visit_point(BiTree root)
{
    
    if(root)
    {
        if(root->Lchild!=NULL&&root->Rchild!=NULL)
            count2++;//统计有两个孩子的节点个数
        if((root->Lchild!=NULL||root->Rchild!=NULL))
            count1++;//统计至少有一个孩子的节点个数
        post_visit_point(root->Lchild);
        post_visit_point(root->Rchild);
    }

}

//输出叶子节点个数和叶子节点
int mid_visit_leaf(BiTree root)
{
    int leaf1=0,leaf2=0;
    if(root)
    {
        if(root->Lchild==NULL&&root->Rchild==NULL)
        {
            tree[i]=root;
            i++;
            visit(root->data);
            return 1;
        }
        leaf1=mid_visit_leaf(root->Lchild);
        leaf2=mid_visit_leaf(root->Rchild);
    }
    return (leaf1+leaf2);
}

//求树的深度
int postTreeDepth(BiTree root)
{
    int hr,hl,h;
    if(root==NULL)
        return 0;
    else
    {
        hl=postTreeDepth(root->Lchild);
        hr=postTreeDepth(root->Rchild);
        h=((hr>hl)?hr:hl)+1;
        return h;
    }
}
//打印树 (参数分别是树根和树的深度)
void printTree(BiTree root,int h)
{
    if(root==NULL)
        return ;
    printTree(root->Rchild,h+1);
    for(int j=0;j<h+1;j++)
    {
        printf("-");    
    }
    printf("%c\n",root->data);

    printTree(root->Lchild,h+1);
}

//某一层k的叶子结点个数(待修改)
int * count_leaf_Level(BiTree root,int k)
{
    BiTree    QCountPoint[100];
    BiTree bt;
    bt=root;
    int front,rear;
    int point[2]={0,0},last,level;
    front=rear=0;
    if(bt==NULL||k<=1)
        return 0;
    rear++;
    QCountPoint[rear]=bt;
    last=rear;
    level=1;
    while(rear!=front)
    {
        front=front+1;
        bt=QCountPoint[front];
        if(level==k&&bt->Lchild==NULL&&bt->Rchild==NULL)
            point[0]++;
        if(level==k)
            point[1]++;
        if(bt->Lchild!=NULL)
        {
            rear=rear+1;
            QCountPoint[rear]=bt->Lchild;
        }
        if(bt->Rchild!=NULL)
        {
            rear=rear+1;
            QCountPoint[rear]=bt->Rchild;
        }
        if(front==last)
        {
            level++;
            last=rear;
        }
        if(level>k)
            return point;
    }
}

//统计每一层的叶子节点个数
void print_count_leaf(BiTree root)  
{
    int j;
    int *p;
    point.depth=postTreeDepth(root);
    for(j=1;j<point.depth;j++)
    {    
        p=count_leaf_Level(root,j);
        point.countleaf[j]=*p;
        point.countpoint[j]=*(p+1);
     }     
}

//二叉树的繁茂度
int Lush_degree(BiTree root)
{
    int max=0;
    for(int j=1;j<point.depth;j++)
    {
        if(max<point.countpoint[j])
        max=point.countpoint[j];
    }
    return (max*postTreeDepth(root));
}

//判定是否为完全二叉树
int  IsComBinTree(BiTree root)
{
    int depthL,depthR,j;
    depthL=postTreeDepth(root->Lchild)+1;
    depthR=postTreeDepth(root->Rchild)+1;
    if((depthL==depthR)||(depthL-depthR==1))
    {
        for( j=1;j<=point.depth-2;j++)
        {
            if(point.countleaf[j]!=0)
                break;
        }
        if(j==(point.depth-2))
            return TRUE;
        else
            return FALSE;
            
    }
    else
        return FALSE;    
}

/************访问函数*****************/
void visit(char ch)
{
    putchar(ch);
    printf(" ");
}
 


  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值