天天看點

非線性表-BiTree(二叉樹練習題-沒事多看看)

1:判斷是否為平衡二叉樹

非線性表-BiTree(二叉樹練習題-沒事多看看)
非線性表-BiTree(二叉樹練習題-沒事多看看)
int depth(bitTree T)
{
    if(!T)
        return 0;
    else
        return max(depth(T->lchild),depth(T->rchild))+1;
        //這有個缺點,空樹會傳回深度1
}
//判斷平衡二叉樹
int balance(bitTree t)
{
    int left,right;
    int cha;
    if(t!=NULL)
    {
        left=depth(t.lchild);
        right=depth(t.rchild);
        cha=left-right;
        if(cha>1||cha<-1)
        {
            return false;
        }
        return  balance(t.lchild)&&balance((t.rchild));
    }

}      

View Code

2:判斷是否為完全二叉樹

非線性表-BiTree(二叉樹練習題-沒事多看看)
非線性表-BiTree(二叉樹練習題-沒事多看看)
/**層次周遊,根入隊入隊
1: 若隊列目前節點左右節點均存在 存入隊列
2:若隊列目前節點的左節點存在,右節點不存在 設定bj=0 其之後的節點不能有左右節點
3:若隊列目前節點不存在左節點,存在右節點,設定cm=1
4:若目前節點不存在左右節點,設定bj=0,之後節點不能存在左右節點
*/
int wanquan(bitTree t)
{
    if(t==NULL)return 0;
    QueuePtr q;
    InitQue(q);
    bitTree p=t;
    int cm=1;
    //用cm變量值表示迄今為止二叉樹為完全二叉樹
    //(其初值為1,一旦發現不滿足上述條件之一,則置cm為0
    //結束後傳回cm的值
    int bj=1;
    //bj變量值表示迄今為止所有節點均有左右孩子(其初值為1),
    //一旦發現一個節點沒有左孩子或沒有右孩子時置bj為0
    if(!p->lchild&&p->rchild)return 0;//如果根隻有右子樹,沒有左子樹,肯定就不是
    EnQue(q,p);
    /**
         1
       2   3
     4  5 6  7

   目前隊列:    7
   出隊元素:1 2 3 4 5 6
       cm:1 1 1 1 1 1 1 1
       bj:1 1 1 1 0 0 0 0

         1
       2   3
     4    5

   目前隊列:   5
   出隊元素:1 2 3 4 5
       cm:1 1 1 0 0 0
       bj:1 1 0 0 0 0
         1
       2   3
     4

   目前隊列:
   出隊元素:1 2 3 4
       cm:1 1 1 1 1
       bj:1 1 0 0 0

         1
       2   3
     4  5 6

   目前隊列:
   出隊元素:1 2 3 4 5 6
       cm:1 1 1 1 1 1 1
       bj:1 1 1 0 0 0 0
     */
    while(DeQue(q,p)&&cm)
    {
        if(p->lchild&&p->rchild)//左右節點存在
        {
            if(bj==0)cm=0;break;//bj為0說明上一顆樹沒有右孩子或者說兩個孩子都沒,是以這棵樹不能有孩子
            EnQue(q,p->lchild);
            EnQue(q,p->rchild);
        }
        if(p->lchild&&!p->rchild)//左節點存在,右節點不存在
        {
            if(bj==0)cm==0;break;//bj為0說明上一顆樹沒有右孩子或者說兩個孩子都沒,是以這棵樹不能有孩子
            EnQue(q,p->lchild);
            bj=0;
        }
        if(!p->lchild&&p->rchild) //左節點不存在,右節點存在,沒有左孩子直接判死刑
        {
            cm=0,
        }
        if(!p->lchild&&!p->rchild)//兩個孩子都沒有,則隊列中的下一個元素不能有孩子
        {
            bj=0;
        }

    }
     return cm;
}      

View Code

3:求雙節點個數

非線性表-BiTree(二叉樹練習題-沒事多看看)
非線性表-BiTree(二叉樹練習題-沒事多看看)
int sum=0;
int twoSon(bitTree t)
{
    if(!t)return 0;
    if(t->lchild!=NULL&&t->rchild!=NULL)
    {
        sum++;
        twoSon(t->lchild);
        twoSon(t->rchild);

    }
    else
    {
        twoSon(t->lchild);
        twoSon(t->rchild);

    }
    return sum;
}      

View Code

4:将左右節點交換

第一種(書上):

非線性表-BiTree(二叉樹練習題-沒事多看看)
非線性表-BiTree(二叉樹練習題-沒事多看看)
void swap(bitTree b)
{
    if(b)
    {
        swab(b->lchild);
        swap(b->rchild);
        temp=b->lchild;
        b->lchild=b->rchild;
        b->rchild=temp;
    }
}      

View Code

第二種:

非線性表-BiTree(二叉樹練習題-沒事多看看)
非線性表-BiTree(二叉樹練習題-沒事多看看)
int changeson(bitTree t)
{
    if(!t)return 0;
    LinkQueue q;
    InitQue(q);
    EnQue(&q,t);
    bitTree p;
    bitTree temp;
    while(QueEmpty(q))//隊列不為空
    {
        DeQue(&q,&p);//出隊
        if(p->lchild!=NULL&&p->rchild!=NULL)//左右節點存在,交換
        {
            temp=p->lchild;
            p->lchild=p->rchild;
            p->rchild=temp;
            EnQue(&q,p->lchild);
            EnQue(&q,p->rchild);

        }
        if(p->lchild!=NULL&&p->rchild==NULL)//左節點存在右節點不存在 左節點變成右節點
        {
            p->rchild=p->lchild;
            EnQue(&q,p->lchild);

        }
        if(p->lchild!=NULL&&p->rchild==NULL)//左節點不存在右節點存在 由節點變成左節點
        {
            p->lchild=p->rchild;
            EnQue(&q,p->rchild);

        }
    }
    return 1;
}      

View Code

5:root指向根節點,p,q指向二叉樹任意兩個節點的指針,找到p,q公共祖先節點

第一種:

非線性表-BiTree(二叉樹練習題-沒事多看看)
非線性表-BiTree(二叉樹練習題-沒事多看看)
//輔助函數 T若為空傳回,否則若等于要找得數傳回真,
//或者有孩子節點等于要找得數傳回真,且t為e
status Search(bitTree T,bitTree e)
{
    if(!T)
        return FALSE;
    if(T==e||Search(T->lchild,e)==TRUE||Search(T->rchild,e)==TRUE)
        return TRUE;
    else
        return FALSE;
}
//若e是T中某個非根結點,則傳回它的雙親,否則傳回NULL,前提T存在
bitTree Parent(bitTree T,bitTree e)
{
    if(T==e)//沒有雙親
        return NULL;

    if(T->lchild==e||T->rchild==e)//根節點是雙親
        return T;
    else if(Search(T->lchild,e)==TRUE)//根節點的左子樹有要找得數 執行完search t指向e這個值的雙親,t->lchild指向e
        return Parent(T->lchild,e);//傳回父母節點
    else if(Search(T->rchild,e)==TRUE)//根節點的右子樹有要找得數t指向e這個值的雙親,t->lchild指向e
        return Parent(T->rchild,e);//傳回父母節點
    else

    return NULL;
}
void searchParent(bitTree root,bitTree p,bitTree q,bitTree r)
{
    if(!root||!p||!q)return 0;
    bitTree pp;
    pp=p;
    while(pp!=NULL)
    {
        //以pp為根節點,第一次以p為根節點,在子樹找q,找到說明pp是公共祖先節點
        if(Search(pp,q)==TRUE){
            r=pp;
            break;
        }
        pp=Parent(root,pp);//在樹中找到pp的雙親,傳回雙親節點

    }

}      

View Code

第二種(書上):

非線性表-BiTree(二叉樹練習題-沒事多看看)
非線性表-BiTree(二叉樹練習題-沒事多看看)
stack s[],s1[];
bitTree ancestor(bitTree root,bitNode *p,bitNode *q)
{
    top=0;bt=root;
    while(bt!=NULL||top>0)
    {
        while(bt!=NULL)
        {
            s[++top].t=bt;
            s[top].tag=0;
            bt=bt->lchild;//沿左分支向下
        }
        while(top!=0&&s[top].tag==1)
        {
            //假設p在q的左側,遇到p棧中元素均為p祖先
            if(s[top].t==p)
            {
                for(i=1;i<=top;i++)
                {
                    s1[i]=s[i];
                    top1=top;
                }
            }
            if(s[top].t==q)
            {
                for(i=top;i>0;i--)//将棧中元素的樹節點到s1中去比對
                {
                    for(j=top1;j>0;j--)
                    {
                        if(s1[j].t==s[i].t)return s[i].t;//p和q的最近公共祖先已找到
                    }
                }
                top--;
            }
        }
        if(top!=0)
        {
            s[top].tag=1;
            bt=s[top].t->rchild;
        }
    }
    return NULL:

}      

View Code

6:二叉樹的帶權路徑長度WPL所有葉節點的帶權路徑之和

非線性表-BiTree(二叉樹練習題-沒事多看看)
非線性表-BiTree(二叉樹練習題-沒事多看看)
/**
     1
   2   3
 4  5 6  7
基于先序周遊,用一個靜态變量儲存WPL把每個節點的深度作為參數傳遞
若為葉子結點,WPL=該節點深度*權值,若非葉子節點則遞歸調用
*/
int wpl=0;
void preOrderRoad(bitTree t,int dept)
{
    if(t==NULL)
    {
        return 0;
    }
    if(t->lchild==NULL&&t->rchild==NULL)
    {
        wpl=wpl+t->data*dept;
        return;
    }
    else
    {
        preOrderRoad(t->lchild,dept+1);
        preOrderRoad(t->rchild,dept+1);
    }

}      

View Code

7:對樹中每個元素值為X的節點,删去以他為根的子樹,并釋放相應空間

第一種(書上):

非線性表-BiTree(二叉樹練習題-沒事多看看)
非線性表-BiTree(二叉樹練習題-沒事多看看)
void deleteXtree(bitTree &bt)
{
    if(bt)
    {
        deleteXtree(bt->lchild);
        deleteXtree(bt->rchild);
        free(bt);
    }
}
void search(bitTree bt,int x)
{
    bitTree Q[];//存放二叉樹隊列節點指針
    if(bt)
    {
        if(bt->data==x)
        {
            deleteXtree(bt);
            exit(0);
        }
        InitQueue(Q);
        EnQueue(Q,bt);
        while(!isEmpty(Q))
        {
            DeQueue(Q,p);
            if(p->lchild)
            {
                if(p->lchild->data==x)
                {
                    deleteXtree(p->lchild);
                    p->lchild=NULL;
                }
                else EnQueue(Q,p->lchild);
            }
            if(p->rchild)
            {
                if(p->rchild->data==x)
                {
                   deleteXtree(p->rchild);
                    p->rchild=NULL;
                }
                else EnQueue(Q,p->rchild);
            }
        }

    }
}      

View Code

第二種:

非線性表-BiTree(二叉樹練習題-沒事多看看)
非線性表-BiTree(二叉樹練習題-沒事多看看)
//層次周遊找到元素值為x的節點,遞歸删除子樹,釋放空間
int delectX(bitTree &t,int x)
{
    if(!t)return 0;
    QueuePtr q;
    InitQue(q);
    EnQue(&q,t);
    bitTree bnode;
    while(DeQue(&q,bnode))
    {
        if(bnode->data==k)
        {
            if(t->rchild!=NULL)del(t->rchild);
            if(t->lchild!=NULL)del(t->lchild);
            continue;
        }
        if(bnode->rchild!=NULL)
        {
            EnQue(&q,*(bnode->rchild));
        }
        if(bnode->lchild!=NULL)
        {
            EnQue(&q,*(bnode->lchild));
        }
    }

}
int del(bitTree t)
{
    if(!t)return 0;
    if(t->rchild==NULL&&t->lchild==NULL)
    {
        free(t);
    }
    if(t->rchild!=NULL)del(t->rchild);
    if(t->lchild!=NULL)del(t->lchild);
}      

View Code

8:求先序周遊第k個節點的值

第一種:

非線性表-BiTree(二叉樹練習題-沒事多看看)
非線性表-BiTree(二叉樹練習題-沒事多看看)
//非遞歸先序周遊計數,每周遊一個數加一到k,輸出目前值的結果
int searchK(bitTree *t,int k)
{
    Stack st;
    if(!st)return 0;
    if(!t)return 0;
    push(st,*t);
    bitTree tno;
    int i=0
    while(pop(st,tno))
    {
        i++;
        if(i==k)
        {
            printf("%d",tno->data);
            break;
        }
        if(tno.rchild!=NULL)
        {
            push(st,*(tno.rchild));
        }
        if(tno.lchild!=NULL)
        {
            push(st,*(tno.lchild));
        }
    }

}      

View Code

第二種(書上):

非線性表-BiTree(二叉樹練習題-沒事多看看)
非線性表-BiTree(二叉樹練習題-沒事多看看)
int i=1;
int preNode(bitTree b,int k)
{
    if(b==NULL)return '#';
    if(i==k)return b->data;
    i++;
    ch=preNode(b->lchild,k);
    if(ch!='#')return ch;
    ch=preNode(b->rchild,k);return ch;
}      

View Code

9:二叉樹各節點值互不相同,先序周遊A[1...n]和中序周遊B[1...n] 編寫算法建立二叉連結清單

非線性表-BiTree(二叉樹練習題-沒事多看看)
非線性表-BiTree(二叉樹練習題-沒事多看看)
/**
         1
       2   3
     4  5 6  7
先序周遊: 1 2 4 5 3 6 7
中序周遊: 4 2 5 1 6 3 7

*/
bitTree preINCreat(int a[],int b[],int l1,int h1,int l2,int h2)
{
    //l1,h1為先序的第一和最後一個節點下标,l2,h2位中序的第一和最後一個下标
    l1=l2=1,h1=h2=n;
    root=(bitTree)malloc(sizeof(bitTree));
    root->data=a[l1];
    for(i=l2;b[i]!=root->data;i++);
    llen=i-l2;//左子樹長度
    rlen=h2-i;//右子樹長度
    if(llen)
        root->lchild=preINCreat(a,b,l1+1,l1+llen,l2,l2+llen-1);//遞歸建立左子樹
    else
        root->lchild=NULL;//左子樹為空
    if(rlen)
        root->rchild=preINCreat(a,b,h1-rlen+1,h1,h2-rlen+1,h2);//遞歸建立右子樹
    else
        root->rchild=NULL;//右子樹為空
    return root

}      

View Code

10:列印數值為x的節點的祖先

非線性表-BiTree(二叉樹練習題-沒事多看看)
非線性表-BiTree(二叉樹練習題-沒事多看看)
int prPar(bitTree T,int x)
{
    bitTree tnode;
   // tnode=Parent(T,x);
   // if(tnode!=NULL)
   // {
   //     printf("%d",tnode->data);
   // }
   if(T==x)return NULL;
   if(T->lchild==x||T->rchild==x)
   {
       tnode=T;
       return tnode;//找到雙親節點
   }
   else if(Search(T->lchild,x)==TRUE)
   {
       prPar(T->lchild,x);
   }
   else if(Search(T->rchild,x)==TRUE)
   {
       prPar(T->rchild,x);
   }
   else return NULL;

}      

View Code

非線性表-BiTree(二叉樹練習題-沒事多看看)
非線性表-BiTree(二叉樹練習題-沒事多看看)
typedef struct
{
    bitTree t;
    int tag;//0:左子女被通路,1右子女被通路
}stack;
void Search(bitTree bt,int x)
{
    stack s[];
    top=0;
    while(bt!=NULL||top>0)
    {
        while(bt!=NULL&&bt->data!=x)
        {
            a[++top].t=bt;
            s[top].tag=0;
            bt=bt->lchild;//沿左分支向下
        }
        if(bt->data==x)
        {
            printf("所查節點的所有祖先節點的值");
            for(i=1;i<=top;i++)
            {
                printf("%d",s[i].t->data);
            }
            exit(0);
        }
        while(top!=0&&s[top].tag==1)//退棧
        {
            top--;
        }
        if(top!=0)
        {
            s[top].tag=1;
            bt=s[top].t->rchild;//沿着右分支向下周遊
        }

    }
}      

View Code

11:求非空二叉樹寬度

非線性表-BiTree(二叉樹練習題-沒事多看看)
非線性表-BiTree(二叉樹練習題-沒事多看看)
/**
求非空二叉樹寬度
設定寬度初值num0
         1
       2   3
     4  5 6  7
     設計結構為

隊列,順序周遊二叉樹,一層周遊完之後,剩下的都是下一層
第一層 cur=1 cur--直到cur=0,計算目前隊列長指派于cur=2
第二層 cur=2 cur--直到cur=0,計算目前隊列長指派于cur=4
*/
int treeWid(bitTree t)
{
    if(!t)return 0;

    QueuePtr q;
    InitQue(q);
    EnQue(&q,t);

    bitTree bnode;
    int width=1;
    int curwidth=1;
    while(QueEmpty(q))
    {
        while(curwidth!=0)
        {
            DeQue(&q,bnode);
            if(bnode->lchild!=NULL) EnQue(&q,bnode->lchild);
            if(bnode->rchild!=NULL) EnQue(&q,bnode->rchild);
            curwidth--;
        }
        curwidth=QueueLength(q);//求隊列的長度
        width=curwidth>width?curwidth:width;
    }
    return width;
}      

View Code

12:設有滿二叉樹,已知先序周遊,求後序周遊

非線性表-BiTree(二叉樹練習題-沒事多看看)
非線性表-BiTree(二叉樹練習題-沒事多看看)
/**
         1
       2   3
     4  5 6  7
先序周遊:1 2 4 5 3 6 7
後序周遊:4 5 2 6 7 3 1
化分函數(樹先序序列 ){
    if(序列數量大于一個){
        化分函數(左子樹先序序列);
        化分函數(右子樹先序序列);
    }
    輸出根(頭部序列);
}
*/
void preTopostAction(char a[],int begin,int end)
{
    char root=a[begin];//暫存根,子樹周遊完後最後輸出
    if(begin+1<=end)
    {
        begin=begin+1;//左端+1(把根節點獨立出來)
        //此時左子樹從begin+1位開始,到(begin+end)/2)結束
        preToPost(a, begin,((begin+end)/2)); //左子樹

        //此時右子樹從((begin+end)/2) + 1)位開始,到end結束
        preToPost(a, (((begin+end)/2) + 1), end); //右子樹

    }
    printf("%c",root);

}
void preTopost(char a[],int len)//先序周遊數組和數組長度
{
    preTopostAction(a,0,len-1);

}      

View Code

13:将二叉樹葉節點從左到右順序連成一個單連結清單,表頭指針head,二叉樹按二叉連結清單方式存儲,連結時用葉節點的右指針來存放單連結清單指針

非線性表-BiTree(二叉樹練習題-沒事多看看)
非線性表-BiTree(二叉樹練習題-沒事多看看)
LinkList head,pre=NULL;
LinkList Inorder(bitTree bt)
{
    if(bt)
    {
        Inorder(bt->lchild);//中序周遊子樹
        if(bt->lchild==NULL&&bt->rchild==NULL)//葉節點
        {
            if(pre==NULL)//處理第一個葉節點
            {
                head=bt;
                pre=bt;

            }
            else
            {
                pre->rchild=bt;
                pre=bt;
            }
            Inorder(bt->rchild);//中序周遊右子樹
        }
        pre->rchild=NULL;//設定連結清單尾

    }
     return head;
}      

View Code

14:判斷兩個二叉樹是否相似

/**
t1,t2都是空的或者隻有一個根節點,t1.t2左右子樹相似
f(t1,t2)=1; t1=t2=NULL
f(t1,t2)=0;t1與t2其中一個為空
f(t1,t2)=f(t1->lchild,t2->lchild)&&f(t1->rchild,t2->rchild);t1.t2均不為空
*/
int similar(bitTree t1,bitTree t2)
{
    int lefts,rights;
    if(t1==NULL&&t2==NULL)
    {
        return 1;
    }
    else if((t1==NULL&&t2!=NULL)||(t2==NULL&&t1!=NULL))
    {
        return 0;
    }
    else
    {
        lefts=similar(t1->lchild,t2->lchild);
        rights=similar(t1->rchild,t2->rchild);
        return lefts&&rights;
    }
}      

15:将給定的表達式樹轉換為等價的中綴表達式(通過括号反映操作符計算順序)

/**
     *
   +   *
  a  bc  d
表達式樹的中序序列加上必要的括号即為等價的中綴表達式,基于二叉樹的中序周遊得到所需表達式

除根節點和葉節點之外,周遊到其他節點時在周遊其左子樹之前加上左括号,周遊完右子樹加上右括号
*/
void btreetoE(bitTree *root)
{
    btreetoEXP(root,1);
}
void btreetoEXP(bitTree *root,int deep)
{
    if(root==NULL)return ;
    else if(root->left==NULL&&root->right==NULL)//若為葉節點輸出
    {
        printf("%s",root->data);
    }
    else
    {
        if(deep>1)printf("(");//有子表達式加一層括号
        btreetoEXP(root->left,deep+1);
        printf("%s",root->data);        // (a+b) * (c*d)
        btreetoEXP(root->right,deep+1);
        if(deep>1)printf(")");
    }

}