数据结构之王道二叉树大题

notes:
1.global存了一些结构体,定义见后边
2.使用了队列,队列的操作的实现,见其他文章
3.使用了数学库,编译命令类似于 gcc -g tree.c -o tree -lm

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//global存了一些结构体
#include "Global.h"
//使用了队列
#include "LinkQueue.c"
//使用了数学库,编译命令类似于 gcc -g tree.c -o tree -lm
#include <math.h>
Tree InitTree(int data)
{
    Tree head= (Tree)malloc(sizeof(TreeNode));
    head->data=data;
    head->lchild=NULL;
    head->rchild=NULL;
    return head;
}
Tree LeftInsertTree(Tree head,int data)
{
    Tree temp=malloc(sizeof(TreeNode));
    if (temp==NULL) return NULL;
    temp->data=data;
    temp->lchild=NULL;
    temp->rchild=NULL;
    head->lchild=temp;
    return temp;
}
Tree RightInsertTree(Tree head,int data)
{
    Tree temp=malloc(sizeof(TreeNode));
    if (temp==NULL) return NULL;
    temp->data=data;
    temp->lchild=NULL;
    temp->rchild=NULL;
    head->rchild=temp;
    return temp;
}
int InsertLeftAndRight(Tree head,Tree left,Tree right,int ldata,int rdata)
{
    Tree lt=malloc(sizeof(TreeNode));
    Tree rt=malloc(sizeof(TreeNode));
    if(lt==NULL||rt==NULL) return -1;
    lt->data=ldata;
    lt->lchild=NULL;
    lt->rchild=NULL;
    rt->data=rdata;
    rt->lchild=NULL;
    rt->rchild=NULL;
    head->lchild=lt;
    head->rchild=rt;
    left=lt;
    right=rt;
    return 1;
}
void Visit(Tree head)
{
    
    printf(" %c ",head->data);
}
void PreOrder(Tree head)
{
    if(head!=NULL)
    {
        Visit(head);
        PreOrder(head->lchild);
        PreOrder(head->rchild);
    }
}
void InOrder(Tree head)
{
    if (head!=NULL)
    {
        InOrder(head->lchild);
        Visit(head);
        InOrder(head->rchild);
    }
    
}

void LevelOrder(Tree root)
{
    LinkQueue queue;
    Tree p;
    InitLinkQueue(&queue);
    EnQueue(&queue,root);
    while(!IsEmpty(&queue))
    {
        DeQueue(&queue,&p);
        Visit(p);
        if (p->lchild!=NULL)
        {
            EnQueue(&queue,p->lchild);
        }
        if (p->rchild!=NULL)
        {
            EnQueue(&queue,p->rchild);
        }
    }

}

int GetTreeHight(Tree root)
{
    if(root==NULL) return 0;
    int front=-1,rear=-1;
    int last=0,level=0;
    Tree Q[MaxSize];
    Q[++rear]=root;
    Tree p;
    //队列非空
    while(front<rear)
    {
        p=Q[++front];
        if (p->lchild!=NULL)
        {
            Q[++rear]=p->lchild;
        }
        if (p->rchild!=NULL)
        {
            Q[++rear]=p->rchild;
        }
        //到了一层的层尾
        if (front==last)
        {
            level++;
            //此时下一层已经全部如队,此层已经全部出对
            last=rear;
        }
    }
    return level;
}

int GetTreeWight(Tree root)
{
    if (root==NULL)
    {
        return 0;
    }
    Tree Q[MaxSize];
    int rear=-1,front=-1;
    int level=0,last=0;
    int count=0;
    Tree p;
    //注意越界,但是我不会写动态分配的代码,emmm
    int wights[10]={0,0};
    Q[++rear]=root;
    while(front<rear)
    {
        p=Q[++front];
        count++;
        if (p->lchild!=NULL)
        {
            Q[++rear]=p->lchild;
        }
        if (p->rchild!=NULL)
        {
            Q[++rear]=p->rchild;
        }
        if (last==front)
        {
            wights[level]=count;
            count=0;
            level++;
            last=rear;
        }
    }
    int i=0,max=0;
    for (int i = 0; i < 10; i++)
    {
        if (wights[i]>max) max=wights[i];
    }
    return max;
}


//根据先序遍历序列和中序遍历序列建立一个二叉树
//先序:ABCDEFGHI
//中序:BCAEDGHFI
//l1 0 l2=8 l2 0 h2 8
//i=2  h2-i=6 l2=2
Tree PreInCreat(char PreQueen[],char InQueen[],int l1,int h1,int l2,int h2)
{
    //l1 l2指向先序和中序的第一个元素
    //h1 h2指向先序和中序的最后一个元素
   //首先根据先序序列找到根节点
    Tree root=InitTree(PreQueen[l1]);
    //根据中序序列找到左子数的元素,和右子树的元素
    int i=0,llen=0,rlen=0;
    for (i = l2; root->data!=InQueen[i]; i++);
    llen=i-l2;
    rlen=h2-i;
    //注意,在递归建立时注意不要改变值,也就是如果表达i往后移动一位,不能是i++而是i+1
    //尽量不使用i表达
    if (llen!=0)
        root->lchild=PreInCreat(PreQueen,InQueen,l1+1,l1+llen,l2,l2+llen-1);
    else
        root->lchild=NULL;
    if (rlen!=0)
        root->rchild=PreInCreat(PreQueen,InQueen,h1-rlen+1,h1,h2-rlen+1,h2);
    else
        root->rchild=NULL;
    return root;
}

//利用层次遍历的思想 判断是不是完全二叉树 垃圾版
//贼垃圾,不要看
int Low_IsFullTree(Tree root)
{
    if (root==NULL) return -1;
    int last=0,level=0;
    int count=0;
    int front=-1,rear=-1;
    int heigth=GetTreeHight(root);
    Tree Q[MaxSize];
    Tree p;
    //入队
    Q[++rear]=root;
    while (front<rear)
    {
        //出队
        p=Q[++front];
        //每次如队列一个就加一可以统计每层的个数
        count++;
        if (p->lchild!=NULL)
        {
            Q[++rear]=p->lchild;
        }
        if (p->rchild!=NULL)
        {
            Q[++rear]=p->rchild;
        }
        //如果队列的前指针指向了last
        //说明这一层遍历完了
        if (last==front&&level!=heigth-2)
        {
            level++;
            //刚遍历完时,rear指向这一层的尾节点
            last=rear;
            //看看这一层是不是满的
            //不是满的有两种情况,第一种不是完全二叉树
            //第二种,最后一层
            //如果不进if说明是满二叉树
            if (pow(2,level-1)!=count)
            {
                return 0;
            }
            //这层完了,下一层重新计数
            count=0;
        }
        //刚进倒数第二层,遍历每一个节点
        if(level==heigth-2)
        {
            int flag_1=1,flag_2=0;
            int t_front=front,t_rear=rear;
            int i=0;
            while(t_front-t_rear!=1)
            {
                if (Q[t_front]->lchild==NULL || Q[t_front]->rchild==NULL)
                {
                   if (flag_1==1) flag_2++;
                }
                else
                {
                    if(flag_1==0) flag_2++;
                }
                if(flag_2==2||flag_2>2) return 0; 
                t_front++;
            }
        }
    }
    return 1;
}

//升级版 是不是完全二叉树
int IsFullTree_Pro(Tree root)
{
    int front=-1,rear=-1;
    Tree Q[MaxSize];
    Q[++rear]=root;
    Tree p;
    while(front==rear)
    {
        p=Q[++front];
        if (p!=NULL)
        {
            Q[++rear]=p->lchild;
            Q[++rear]=p->rchild;
        }
        else
        {
            Q[++rear]=NULL;
        }
    }
    int i=0;
    while(i!=rear)
    {
        if (Q[i]==NULL)
        {
            int j=i+1;
            while(j!=rear)
            {
                if (Q[j]!=NULL)
                {
                    return 0;
                }
            }
        }
        i++;
    }

}

//计算所以双分支节点个数,层次遍历写法
int DoubelChildCount(Tree root)
{
    if (root==NULL) return 0;
    LinkQueue *queue;
    InitLinkQueue(queue);
    EnQueue(queue,root);
    Tree p;
    int count=0;
    while(!IsEmpty(queue))
    {
        DeQueue(queue,p);
        if (p->lchild!=NULL&&p->rchild!=NULL)
        {
            count++;
        }
        if (p->lchild!=NULL)
        {
            EnQueue(queue,p->lchild);
        }
        if (p->rchild!=NULL)
        {
            EnQueue(queue,p->rchild);
        }
    }
}

//递归写法,计算所有双分支节点的个数
int DoubelChildCount_digui(Tree root)
{
    if (root==NULL)
    {
        return 0;
    }
    else if (root->lchild!=NULL&&root->rchild!=NULL)
    {
        return DoubelChildCount_digui(root->lchild)+DoubelChildCount_digui(root->rchild)+1;
    }
    else
    {
        return DoubelChildCount_digui(root->lchild)+DoubelChildCount_digui(root->rchild);
    }  
}

//层次遍历交换左右节点
int ChangeLeftAndRight(Tree root)
{
    if (root==NULL) return 0;
    LinkQueue *queue;
    InitLinkQueue(queue);
    EnQueue(queue,root);
    Tree p,temp;
    int count=0;
    while(!IsEmpty(queue))
    {
        DeQueue(queue,p);
        //交换节点
        temp=p->rchild;
        p->rchild=p->lchild;
        p->lchild=temp;
        //此时左右分支还没有进入队列
        if (p->lchild!=NULL)
        {
            EnQueue(queue,p->lchild);
        }
        if (p->rchild!=NULL)
        {
            EnQueue(queue,p->rchild);
        }
    }
}
//递归交换左右节点
void ChangeLeftAndRight_digui(Tree root)
{
    if (root==NULL)
    {
        return ;
    }
    else
    {
        Tree temp;
        temp=root->lchild;
        root->lchild=root->rchild;
        root->rchild=temp;
        ChangeLeftAndRight_digui(root->lchild);
        ChangeLeftAndRight_digui(root->rchild);
    }
    
}
//根据根节点删除一棵树
void Delete(Tree root)
{
    if (root!=NULL)
    {
        Delete(root->lchild);
        Delete(root->rchild);
        //左右节点都被删除完了,此节点必然左右为空
        free(root);
    }
    return ;
}
//删除节点是x的的节点,并删除以x为根节点的树
void DeleteX(Tree root,char x)
{
    if (root!=NULL)
    {
        //检查该节点是不是x
        if (root->data==x)
        {
            Delete(root);
        }
        //递归访问左右节点
        DeleteX(root->lchild,x);
        DeleteX(root->rchild,x);
    } 
    return ;
}
//打印值为x的节点的所有祖先
int PrintXParents(Tree root,char x)
{
    if (root!=NULL)
    {
        if (root->data==x)
        {
            printf(" %c",root->data);
            return 1;
        }
        int flag_1= PrintXParents(root->lchild,x);
        if (flag_1==1)
        {
            printf(" %c",root->data);
            return 1;
        }
        int flag_2= PrintXParents(root->rchild,x);
        if (flag_2==1)
        {
            printf(" %c",root->data);
            return 1;
        }
    }
    return 0;
}


//根据先序建立满二叉树,递归吧,递归好写阿红红火火
Tree FullQueueCreatTree(char queue[],int begin,int end)
{
    //别着急,先检查以下序列,如果是满二叉树的序列应该个数上有限制
    int i=0,len=end-begin+1,child_len=(end-begin)/2;
    while(1)
    {
        //正好等比求和是他
        if ((pow(2,i)-1)==len) break;
        //i只会越来越大,不可能再次相等
        if (pow(2,i)>len) return NULL;
        i++;
    }
    Tree root=malloc(sizeof(TreeNode));
    //头节点已经建好,递归建立左右子树
    root->data=queue[begin];
    if (begin==end)
    {
        return root;
    }
    root->lchild=FullQueueCreatTree(queue,begin+1,begin+child_len);
    root->rchild=FullQueueCreatTree(queue,begin+child_len+1,end);
    return root;
}


int main()
{
    char PreQueen[]="ABCDEFGHI";
    char InQueen[]="BCAEDGHFI";
    printf("%s,%s",PreQueen,InQueen);
    Tree head=PreInCreat(PreQueen,InQueen,0,8,0,8);
    PreOrder(head);
    InOrder(head);
    LevelOrder(head);
    printf("%d\n",GetTreeHight(head));
    printf("-------find x parents--------\n");
    PrintXParents(head,'E');
    printf("\n-------get root wights--------\n");
    printf("%d\n",GetTreeWight(head));
    printf("\ncreat tree\n");
    Tree root=FullQueueCreatTree("ABDECFG",0,6);
    PreOrder(root);
}

//2014年 真题
// typedef struct WPL_Tree
// {
//     struct WPL_Tree *left,*right;
//     int weight;
// } *WTree;
// int PreOrderWPL(WTree root,int deep)
// {
//     int wpl=0;
//     if (root->right==NULL&&root->left==NULL)
//     {
//         return deep*root->weight;
//     }
//     if (root->left!=NULL)
//     {
//         wpl+=PreOrderWPL(root->left,deep+1);    
//     }
//     if (root->right!=NULL)
//     {
//         wpl+=PreOrderWPL(root->right,deep+1);
//     }
//     return wpl;
// }

//2017年真题
// typedef struct node
// {
//     char data[10];
//     struct node *left,*right;
// } BTree;
// char* GetExpress(BTree *root,int deep)
// {
//     char * ex=NULL;
//     if (root!=NULL)
//     {
//         char op=root->data;
//         if (deep==1)
//         {
//             char *a= GetExpress(root->left,deep+1);
//             char *b= GetExpress(root->right,deep+1);
//             ex=*a+op+*b;        
//         }
//         if (root->left==NULL&&root->right==NULL)
//         {
//             return root->data;
//         }
//         char *a= GetExpress(root->left,deep+1);
//         char *b= GetExpress(root->right,deep+1);
//         ex='('+*a+')'+op+'('+*b+')';
//     }
//     return ex;
// }

#ifndef __GLOBAL_H__
#define MaxSize 255
typedef struct TreeNode
{
    char data;
    struct TreeNode *lchild,*rchild;
} TreeNode,*Tree;
//数据类型定义
typedef struct LinkNode
{
    Tree data;
    struct LinkNode *next;    
} LinkNode;
typedef struct
{
    LinkNode *front,*rear;
} LinkQueue;
void InitLinkQueue(LinkQueue *queue);
void EnQueue(LinkQueue *queue,Tree data);
int DeQueue(LinkQueue *queue, Tree *data);

#define __GLOBAL_H__
#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
(1)非递归定义 树(tree)是由n(n≥0)个结点组成的有限集合。n=0的树称为空树;n>0的树T: ① 有且仅有一个结点n0,它没有前驱结点,只有后继结点。n0称作树的根(root)结点。 ② 除结点外n0 , 其余的每一个结点都有且仅有一个直接前驱结点;有零个或多个直接后继结点。 (2)递归定义 一颗大树分成几个大的分枝,每个大分枝再分成几个小分枝,小分枝再分成更小的分枝,… ,每个分枝也都是一颗树,由此我们可以给出树的递归定义。 树(tree)是由n(n≥0)个结点组成的有限集合。n=0的树称为空树;n>0的树T: ① 有且仅有一个结点n0,它没有前驱结点,只有后继结点。n0称作树的根(root)结点。 ② 除根结点之外的其他结点分为m(m≥0)个互不相交的集合T0,T1,…,Tm-1,其中每个集合Ti(0&le;i<m)本身又是一棵树,称为根的子树(subtree)。 2、掌握树的各种术语: (1) 父母、孩子与兄弟结点 (2) 度 (3) 结点层次、树的高度 (4) 边、路径 (5) 无序树、有序树 (6) 森林 3、二叉树的定义 二叉树(binary tree)是由n(n≥0)个结点组成的有限集合,此集合或者为空,或者由一个根结点加上两棵分别称为左、右子树的,互不相交的二叉树组成。 二叉树可以为空集,因此根可以有空的左子树或者右子树,亦或者左、右子树皆为空。 4、掌握二叉树的五个性质 5、二叉树的二叉链表存储。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值