二叉树

二叉树代码

二叉树:
//先序遍历
void PreOrder(BTNode *t)
{
    if(!t) return;
    printf("%d ", t->element);
    PreOrder(t->lChild);
    PreOrder(t->rChild);
}

void PreOrderTree(BinaryTree *tree)
{
    if(!tree) return;
    PreOrder(tree->root);
}


//求二叉树的高度
int Height(BTNode *t)
{
    if(!t)  return 0;

    int l=Height(t->lChild);
    int r=Height(t->rChild);
    if(l>r)  return l+1;
    else return r+1;
}






//求二叉树中所有节点的数量
void CountNodes(BTNode *t,int *count)
{
    if(!t)  return;
    *count++;
    CountNodes(t->lChild, count);
    CountNodes(t->rChild, count);
}
int CountN(BinaryTree *tree)
{
    if(!tree) return 0;
    int count=0;
    CountNodes(tree->root, &count);
    return count;
}

//求二叉树中的最大值
void MaxNode(BTNode *t,int *max)
{
    if(!t)  return;
    if(t->element > *max)
        *max=t->element;
    MaxNode(t->lChild, max);
    MaxNode(t->rChild, max);
}
int MaxTree(BinaryTree *tree)
{
    if(!tree) return -1;
    int max=-1;
    
    MaxNode(tree->root, &max);
    return max;
}
//求二叉树中叶子节点的数量
void CountLeaf(BTNode *t,int *count)
{
    if(!t)  return;
    if(!t->lChild && !t->rChild)
        *count++;
    CountLeaf(t->lChild, count);
    CountLeaf(t->rChild, count);
}
int CountL(BinaryTree *tree)
{
    if(!tree) return 0;
    int count=0;
    CountLeaf(tree->root, &count);
    return count;
}

//交换二叉树中每个节点的左右子树
void Exchange(BTNode *t)
{
    BTNode *tmp;
    if(!t)  return;

    tmp=t->lChild;
    t->lChild=t->rChild;
    t->rChild=tmp;

    Exchange(t->lChild);
    Exchange(t->rChild);
}
void ExchangeTree(BinaryTree *tree)
{
    if(!tree) return;
    
    Exchange(tree->root);
}

//拷贝一颗二叉树,将q拷贝一份放到p中
void Copy(BTNode *p, BTNode *q)
{

    if(!q)  return;
    p=(BTNode *)malloc(sizeof(BTNode));
    p->element=q->element;

    Copy(p->lChild, q->lChild);
    Copy(p->rChild, q->rChild);
}
void CopyTree(BinaryTree *oldtree, BinaryTree *newtree)
{
    if(!oldtree) return;
    Copy(newtree->root, oldtree->root);
}

//按先序方法删除一颗二叉树
void Delete(BTNode *t)
{
    BTNode *l,*r;
    if(!t) return;
    l=t->lChild;
    r=t->rChild;
    free(t);
    Delete(l);
    Delete(r);

}
// 宽度优先遍历
void  BFS(BinaryTree *tree)
{
    if(!tree || tree->root) return;

    Queue Q; //用于存储结点指针的队列
    BTNode *p;

    EnQueue(Q, tree->root);
    while(!IsEmpty(Q)){
        Front(Q, &p);  
        DeQueue(Q);

        printf("%d ", p->element);

        if(p->lChild)  
            EnQueue(Q, p->lChild);
        if(p->rChild)  
            EnQueue(Q, p->rChild);
    }
}

//1 利用宽度优先遍历计算度为1的结点的数量
int  BFS_Degree1(BinaryTree *tree)
{
    if(!tree || tree->root) return 0;

    Queue Q; //用于存储结点指针的队列
    BTNode *p;
    int count=0;
    EnQueue(Q, tree->root);

    while(!IsEmpty(Q)){
        Front(Q, &p);  
        DeQueue(Q);

        if((p->lChild && !p->rChild) || (!p->lChild && p->rChild))
            count++;
        if(p->lChild)  
            EnQueue(Q, p->lChild);
        if(p->rChild)  
            EnQueue(Q, p->rChild);
    }
    return count;
}

//2 求二叉树中大于x的节点的数量
void LargeThanX(BTNode *t,int *count, int x)
{
    if(!t)  return;

    if(t->element > x)
        *count++;

    LargeThanX(t->lChild, count, x);
    LargeThanX(t->rChild, count, x);
}

int LTX(BinaryTree *tree, x)
{
    if(!tree) return 0;

    int count=0;
    LargeThanX(tree->root, &count, x);
    return count;
}

// 求二叉树的平均值
void Avgerage(BTNode *t,int *total, int *count)
{
    if(!t)  return;

    *total=*total+t->element;
    *count++;

    Avgerage(t->lChild, total, count);
    Avgerage(t->rChild, total, count);
}

double AvgTree(BinaryTree *tree)
{
    if(!tree) return 0;

    int count=0;
    int total=0;
    Average(tree->root, &total, &count);
    if(count!=0)  return total/count;
    else return 0;
}










//求二叉树中比x大的最小数据
void MinLTX(BTNode *t,int *min, int x)
{
    if(!t)  return;
    if(t->element > x && t->element < *min)
        *min=t->element;
    MinLTX(t->lChild, min, x);
    MinLTX(t->rChild, min, x);
}
int MLTX(BinaryTree *tree, int x)
{
    if(!tree) return -1;
    int min=99999999;

    MinLTX(tree->root, &min, x);

    return min;
}

//扩展:求二叉搜索树中的最小数据(要求算法时间复杂度不高于log2(n))
int MinBST(BSTree *tree)
{
    BSTNode *p;
    if(!tree || tree->root)  return -1;
    p=tree->root;
    while(p->lChild){
        p=p->lChild;
    }
    return p->element;
}

//判断以p和q为根的二叉树是否相似
BOOL IsSimilar(BTNode *p, BTNode *q)
{
    if(!p&&q || p&&!q)
        return FALSE:
    if(!p&&!q)  
        return TRUE;
    return IsSimilar(p->lChild, q->lChild)&&IsSimilar(p->rChild, q->rChild);
}
//计算两棵二叉树的相似度(相似度是指具有相同位置的结点的数量
//与包含结点最多的二叉树的结点数量的比例)
void CountSimilarNodes(BTNode *p, BTNode *q, int *count){
    if(!p&&q || p&&!q)        return :
    if(!p&&!q)      return ;
    *count++;
    CountSimilarNodes(p->lChild, q->lChild, count);
    CountSimilarNodes(p->rChild, q->rChild, count);
}
void CountNodes(BTNode *t,int *count){
    if(!t)  return;
    *count++;
    CountNodes(t->lChild, count);
    CountNodes(t->rChild, count);
}
double Similarity(BinaryTree *tree1, BinaryTree *tree2){
    if(!tree1||!tree2)  return 0;
    int count1=0, count2=0,c=0;
    CountNodes(tree1->root, &count1);
    CountNodes(tree2->root, &count2);
    if(count1==0 && count2==0)  return 1.0;
    CountSimilarNodes(tree1->root, tree2->root, &c);
    if(count1>count2)  return c/count1;
    else return c/count2;
}
设计一个算法求二叉树的内路径长度和外路径长度。
算法思想:
ipath和outpath分别为二又树的内路径长度和外路径长度变量,h用于记录当前考察节点t的路径长度,初始传入时为0,1初始传入为树根节点,ipath 和epath初始均为0,递归程序如下:
(1) 若t为空,则返回:
(2)若t为叶子节点,则根据h计算t的外
路径长度,并加入outpath;否则,根据h计算t的内路径长度,并加入inpath:
(3) 以t的左子树的根节点指针,inpath,
outpath和h+1为参数,递归计算整个二叉树的内路径和外路径长度:
(4) 以t的右子树的根节点指针,inpath,epath和h+1为参数,递归计算整个二叉树的内路径和外路径长度。
//level为当前深度
void PL(BTNode *t, int *inpath, int *outpath, int level)
{
    if(!t)  return;//边界条件
    if(!t->lChild && !t->rChild)//叶子结点,计入外路径长度
        *outpath = *outpath + level;
    else//非叶结点,计入内路径长度
        *inpath = *inpath + level;
    PL(t->lChild, inpath, outpath, level+1);//递归计算左子树
    PL(t->rChild, inpath, outpath, level+1);//递归计算右子树
}
void GetPL(BinaryTree *tree)
{
    int inpath=0, outpath=0;
    if(!tree || !tree->root) return ;  //如果。。。。
    PL(tree->root, &inpath, &outpath, 0);
    printf("内路径和外路径长度分别为%d和%d",inpath,outpath);
}
//求二叉树中第i层中的结点的数量
void  LevelCount(BTNode *t, int i, int level, int *count)
{
    if(!t) return;

    if(level==i) 
        *count++;
    else if(level>i)
        return;
    else{
        LevelCount(t->lChild, i, level+1, count);
        LevelCount(t->rChild, i, level+1, count);
    }
}
int LCT(BinaryTree *tree, int i)
{
    if(!tree || !tree->root) return 0;
    int count=0;
    LevelCount(tree->root, i, 1, &count);
    return count;
}

//求二叉树中以元素值为x的节点为根的子树的高度
算法思想:1 采用递归遍历思想,查找值为x的节点p,找到则返回
             2 计算以p为根的二叉树的高度,并返回
int Height(BTNode *t){
    if(!t) return 0;
    int l=Height(t->lChild);
    int r=Height(t->rChild);
    if(l>r) return l+1;
    else    return r+1;
}
int HeightX(BTNode *t, int x)
{
    int m, n;
    if(!t) return 0;
    if(t->element==x)
        return Height(t);
    else{
        m=HeightX(t->lChild, x);
        if(m>0) return m;
        n=HeightX(t->rChild, x);
        if(n>0) return n;
    }
    return 0;
}

void FindNode(BTNode *t, int x, BTNode **p){
    if(!t) return;
    if(t->element == x){  *p=t; return; }
    FindNode(t->lChild, x, p);
    FindNode(t->rChild, x, p);
}
int HeightX(BianryTree *tree, int x){
    if(!tree || !tree->root) return -1;  //如果。。。。
    BTNode *p=NULL;
    FindNode(tree->root, x, &p);
    if(!p) return 0;  //
    return Height(p);

}

补充题:求与值为x的节点在二叉树的同一层的节点的数量(包含值为x的节点)
void LevelX(BTNode *t, int x,int *level, int h){
    if(!t)  return;
    if(t->element==x){ *level=h; return;}
    LevelX(t->lChild, x, level, h+1);
    LevelX(t->rChild, x, level, h+1);
}
void CountLevel(BTNode *t, int level, int *count, int h){
    if(!t) return;
    if(level==h) *count++;
    else{    //说明else的原因
        CountLevel(t->lChild, level,count, h+1);
        CountLevel(t->rChild, level,count, h+1);
    }
}
int CountLX(BinaryTree *tree, int x){
    if(!tree || !tree->root) return -1;  //如果。。。。
    int count=0, level=0;
    LevelX(tree->root, x, &level, 1);
    if(level==0) return 0;   //
    CountLevel(tree->root, level, &count, 1);
    return count;
}

//求二叉树的宽度

//计算高度
int Height(BTNode *t)
{
    if(!t)  return 0;
    int l=Height(t->lChild);
    int r=Height(t->rChild);
    if(l>r)  return l+1;
    else return r+1;
}
//递归计算每层的宽度
void Weight(BTNode *t, int w[], int level)
{
    if(!t) return;
    w[level]++;//该层宽度加一
    Weight(t->lChild, w, level+1);
    Weight(t->rChild, w, level+1);
}
//基于递归的实现方法(深度优先)
int WeightOfTree(BinaryTree *tree)
{
                if(!tree)  return 0;
    int i,max=-1, h = Height(tree-root);
    int *w=(int*)malloc(sizeof(int)*(h+1));
    for(i=0;i<h+1;i++) w[i]=0;
    Weight(tree->root, w, 1);
    for(i=1;i<h+1;i++)
        if(w[i]>max)  max=w[i];
    return max;
}

//求指定结点p在给定二叉排序树中的层次
int level(BSTNode *t, BSTNode *p)
{
    int count=0;
    BSTNode *q;
    if(!t)  return -1;
    q=t;
    while(q){
        count++;
        if(q->element==p->element)
            return count;
        else if(q->element>p->element)
            q=q->lChild;
        else
            q=q->rChild;
    }
    return -1;
}
//扩展:求二叉树中值为x的节点的层号
void LevelX(BTNode *t, int x,int *level, int h){
    if(!t)  return;
    if(t->element==x){ *level=h; return;}
    LevelX(t->lChild, x, level, h+1);
    LevelX(t->rChild, x, level, h+1);
}

//判定给定二叉树是否为二叉排序树
BOOL IsLarger(int x, BTNode *t){
    if(!t) return TRUE;
    return x>t->element && IsLarger(x, t->lChild)
                        && IsLarger(x, t->rChild);
}
BOOL IsSmaller(int x, BTNode *t){
    if(!t) return TRUE;
    return x<t->element && IsSmaller(x, t->lChild)
                        && IsSmaller(x, t->rChild);
}
BOOL IsBSTree(BTNode *t)
{
    if(!t)  TRUE;
    int temp=t->element;
    if(IsLarger(temp, t->lChild) && IsSmaller(temp, t->rChild))
        return IsBSTree(t->lChild)&&IsBSTree(t->rChild);
    else
        return FALSE;
}


//判断一棵二叉树是否是满二叉树
int Height(BTNode *t){
    if(!t)  return 0;
    int l=Height(t->lChild);
    int r=Height(t->rChild);
    if(l>r)  return l+1;
    else return r+1;
}
void CountNodes(BTNode *t,int *count){
    if(!t)  return;
    *count++;
    CountNodes(t->lChild, count);
    CountNodes(t->rChild, count);
}
BOOL IsFullTree(BinaryTree *tree){
    if(!tree->root) return TRUE;
    int h=Height(tree->root);
    int total=0;
    CountNodes(tree->root, &total);
    int x=1, i;
    for(i=0;i<h;i++) x=x*2;
    x=x-1;
    if(x==total) return TRUE;
    else return FALSE;
}

//判断一棵二叉树是否是完全二叉树
int Height(BTNode *t){
    if(!t)  return 0;
    int l=Height(t->lChild);
    int r=Height(t->rChild);
    if(l>r)  return l+1;
    else return r+1;
}
void mapping(BTNode *t, BTNode *arr[], int i){
    if(!t) return;
    arr[i]=t;
    mapping(t->lChild, arr, 2*i+1);
    mapping(t->rChild, arr, 2*i+2);
}
BOOL IsCompleteTree(BinaryTree *tree){
    int h=Height(tree->root);  //h表示。。。。。。
    int max=1, i;  //max表示。。。。。。
    for(i=0;i<h;i++) max=max*2;
    max=max-1;
    BTNode **arr=(BTNode**)malloc(sizeof(BTNode*)*max);
    for(i=0;i<x;i++) arr[i]=NULL;  //初始化
    mapping(tree->root, arr, 0);
    for(i=0;i<max;i++)  if(arr[i]==NULL) break;
    if(i==max) return TRUE; //当i==max时,当前二叉树为满二叉树,则也是完全二叉树
    for(;i<max;i++)  if(arr[i]!=NULL) return FALSE:
    return TRUE;
}
//试计算二叉树的加权路径长度
void WPL(BTNode *t, int *wpl, int level)
{
    if(!t)  return;
    if(!t->lChild && !t->rChild)
        *wpl = *wpl + t->element*level;
    WPL(t->lChild, wpl, level+1);
    WPL(t->rChild, wpl, level+1);
}
int GetWPL(BinaryTree *tree)
{
    if(!tree || !tree->root) return -1;  //如果。。。。
    int wpl=0;
    WPL(tree->root, &wpl, 0);
    return wpl;
}
//利用宽度优先遍历判断完全二叉树

BOOL  IsCompleteTree(BinaryTree *tree)
{
    if(!tree->root) return TRUE;

    Queue Q; //用于存储结点指针的队列
    BTNode *p;
    BOOL  flag=FALSE;  //是否已发生空指针出队的标记,FALSE表示未发生

    EnQueue(Q, tree->root);
    while(!IsEmpty(Q)){
        Front(Q, &p);  
        DeQueue(Q);
        if(!flag && !p)  flag=TRUE;  //当出队元素第一次为空时,设置flag=TRUE
        else if(flag && p)//已有空指针出队的情况下,发现非空结点,则不是完全二叉树 
            return FALSE;  
        else if(!flag && p){ //未有空指针出队的情况下,非空结点出队,此时将该结点
            EnQueue(Q,p->lChild); //的左右孩子(不论是否为空)依次进队
            EnQueue(Q,p->rChild);
        }
        else if(flag && !p)  //已有空指针出队,且当前出队元素为空指针,则继续循环
            continue;        
    }
    return TRUE;
}
//设计一个尽可能快的算法,求出在一颗二叉排序树中关键字大于k的节点数量
int CountGK(BSTNode *bt,int k)
{
     if(!bt)  return 0;
     return Count(bt->root,k);
}
int Count(BSTNode *t,ink)
{
       if(t==NULL)
            return 0;
       if(t->data<=k)  //当前节点的关键字小于等于k时,左子树不必满足条件,无需遍历
                return Count(t->rchild);
       else//当前节点的关键字大于k时,左右子树都要考虑
                return 1+Count(t->lchild)+Count(t->rchild);
}
//判断一个二叉搜索树是否是AVL树
int Height(BTNode *t){
    if(!t)  return 0;
    int l=Height(t->lChild);
    int r=Height(t->rChild);
    if(l>r)  return l+1;
    else return r+1;
}
BOOL IsAVL(BTNode *t)
{
    if(!t) return TRUE;
    int l=Height(t->lChild);  //计算左子树的高度
    int r=Height(t->rCHild);  //计算右子树的高度
    if(l-r>1 || l-r<-1)      //判断当前结点是否符合AVL树的定义
        return FALSE;
    else
        return IsAVL(t->lChild)&&IsAVL(t->rChild);
}
BOOL IsAVLTree(BinaryTree *tree)
{
    return IsAVL(tree->root);
}

//判断一棵二叉树是否是二叉搜索树
BOOL IsLarge(BTNode *t, int x)  //判断x是否大于t中的所有结点
{
    if(!t) 
        return TRUE;
    return x>t->element && IsLarge(t->lChild, x) && IsLarge(t->rChild, x);
}

BOOL IsSmall(BTNode *t, int x)  //判断x是否小于t中的所有结点
{
    if(!t) 
        return TRUE;
    return x<t->element && IsSmall(t->lChild, x) && IsSmall(t->rChild, x);
}
BOOL IsBST(BTNode *t)
{
    if(!t) 
        return TRUE;

    BOOL flag = IsLarge(t->lChild, t->element) && IsSmall(t->rChild, t->element);
    return flag && IsBST(t->lChild) && IsBST(t->rChild);
}
//判断二叉树中节点p和q的祖先后裔关系
BOOL IsInTree(BTNode *t, BTNode *p)
{
    if(!t) return FALSE;
    return t==p || IsInTree(t->lChild, p) || IsInTree(t->rChild, p);
}
void IsAncestor(BTNode *p, BTNode *q)
{
    if(IsInTree(p, q))  printf("p is a ancestor of q!");
    else if(IsInTree(q, p))  printf("q is a ancestor of p!");
}



//判断二叉树中节点p和q的兄弟关系
void IsSibiling(BTNode *t, BTNode *p, BTNode *q, int *flag)
{
    if(!t) return ;
    if((t->lChild==p && t->rChild==q)||(t->lChild==q && t->rChild==p))
        *flag=1;
    IsSibiling(t->lChild, p, q);
    IsSibiling(t->rChild, p, q);
}
BOOL Brothers(BinaryTree *tree, BTNode *p, BTNode *q)
{
    int flag=0;
    if(!tree||!tree->root)  return FALSE;
    IsSibiling(tree->root, p, q, &flag);
    if(flag) return TRUE;
    else  return FALSE;
}


//判断A和B之间是否有祖先后裔关系
void Find(BTNode *t, BTNode **node, int x)
{
    if(!t)  return;
    if(t->element==x){     *node=t; return; }
    Find(t->lChild, node, x);
    Find(t->rChild, node, x);
}
void Level(BTNode *t, int x, int *le, int t_level) //返回x所在层的层号
{
    if(!t) return;
    if(t->element == x){ *le=t_level; return;}
    Level(t->lChild, x, le,t_level+1);
    Level(t->rChild, x, le,t_level+1);
}
BOOL JudgeAncestor(BinaryTree *tree, int A, int B)
{
    BTNode *p==NULL, *q=NULL;
    int A_level=-1, B_level=-1;
    Level(tree->root, A, &A_level, 1);
    Level(tree->root, B, &B_level, 1);
    if(A_level==-1 || B_level==-1) { printf("不存在祖先后裔关系\n");return FALSE;}
    if(A_level<B_level){
        Find(tree->root, &p, A);
        Find(p, &q, B);
        if(!q) {printf("不存在祖先后裔关系\n"); return FALSE};
        else {printf("A是B的祖先\n");return TRUE;}
    }
    else{
        Find(tree->root, &p, B);
        Find(p, &q, A);
        if(!q) { printf("不存在祖先后裔关系\n");return FALSE; }
        else { printf("B是A的祖先\n"); return TRUE; }
    }
}
//p和q分别为二叉树中任意两个结点,试编写算法查找找到p和q的最近公共祖先结点
BOOL IsAncestor(BTNode *t, BTNode *p, Stack *S)//判断t是否是x的祖先,若是则将t进栈
{
    if(!t) return FALSE;
    if(t==p || IsAncestor(t->lChild, p, S) 
            || IsAncestor(t->rChild, p, S)){
        Push(S, t);
        return TRUE;
    }
    return FALSE;
}
BTNode *FindNA(BTNode *t, BTNode *p, BTNode *q)
{
    Stack S1, S2;
    if(!IsAncestor(t, p, S1)) {printf("p节点不存在"); return NULL};
    if(!IsAncestor(t, q, S2)) {printf("q节点不存在"); return NULL};
    BTNode *tp=NULL;
    while(Top(S1)==Top(S2)){
        tp=Top(S1); Pop(S1); Pop(S2);
    }
    return tp;
}






//已知A和B具有祖先后裔关系,求A和B之间的距离(即A和B之间的路径长度)
void Level(BTNode *t, int A, int B, int *la, int *lb, int t_level) 
{
    if(!t) return;
    if(t->element == A)  *la=t_level;
    if(t->element == B)  *lb=t_level;
    if(*la != -1 && *lb != -1)  //用于在完成A和B的层号计算的前提下,提前退出递归
        return;                 //该判断语句块可以不要
    Level(t->lChild, x, le,t_level+1);
    Level(t->rChild, x, le,t_level+1);
}
int Distance(BinaryTree *tree, int A, int B)
{
    if(!tree)  return -1;
    int A_level=-1, B_level=-1;
    Level(tree->root, A, B, &A_level, &B_level, 1);
    if(A_level==-1 || B_level==-1)  return -1;
    if(A_level>B_level)  return A_level-B_level;
    else         return B_level-A_level;
}

//求A和B的最近共同祖先
BOOL IsInTree(BTNode *t, int x)  //判断x是否在t树中
{
    if(!t)  return FALSE;
    if(t->element == x) return TRUE;
    return IsInTree(t->lChild, x) || IsInTree(t->rChild, x);
}
void FindAllAncestors(BTNode *t, int t_level, int x, BTNode *arr[])
{   ////将x的祖先结点从上到下依次存储到数组中
    if(!t) return;
    if(IsInTree(t, x)){  
        arr[t_level]=t;
        FindAllAncestors(t->lChild, t_level+1, x, arr);
        FindAllAncestors(t->rChild, t_level+1, x, arr);
    }
    else return;
}
int Height(BTNode *t){
    if(!t)  return 0;
    int l=Height(t->lChild);
    int r=Height(t->rChild);
    if(l>r)  return l+1;
    else return r+1;
}
BTNode *GetNearestAncestor(BinaryTree *tree, int A, int B)
{
    int h=Height(tree->root);
    int i;
    BTNode **arrA=(BTNode**)malloc(sizeof(BTNode*)*h);
    BTNode **arrB=(BTNode**)malloc(sizeof(BTNode*)*h);
    for(i=0;i<h;i++) arrA[i]=arrB[i]=NULL;
    FindAllAncestors(tree->root, 0, A, &arrA); //将A的祖先结点从上到下依次存储到数组中
    FindAllAncestors(tree->root, 0, B, &arrB); //将B的祖先结点从上到下依次存储到数组中
    for(i=h-1;i>=0;i--)  //从后向前寻找相同且不为空的结点,该结点即为最近的共同祖先
        if(arrA[i]==arrB[i] && arrA[i]!=NULL) 
            return arrA[i];

}

 

posted @ 2019-12-10 17:23  周青春-ZD  阅读(335)  评论(0编辑  收藏  举报