1. 程式人生 > >16.考研-資料結構-二叉樹的相關演算法01

16.考研-資料結構-二叉樹的相關演算法01

中序遍歷對二叉樹線索化的遞迴演算法

void InThread(ThreadTree &P,ThreadTree &pre)
{
    if(p!=null)
    {
        InThread(p->lchild,pre);
        if(lchild==null)
        {
            p->lchild=pre;
            p->ltag=1;
        }
        if(pre!=null&&pre->rchild==null)
        {
            pre->rchild=p;
            pre->rtag=1;
        }
        pre=p;
        InThread(p->rchild,pre);
    }
}

void CreatInTread(ThreadTree T)
{
    ThreadTree pre=null;
    if(T!=null)
    {
        InThread(T,pre);
        pre->rchild=null;
        pre->rtag=1;
    }
}

已知一棵二叉樹按順序儲存結構進行儲存,設計一個演算法,求編號i到j的兩個結點的最近的公共祖先結點的值

ElemType Comm_Ancestor(SqTree T,int i,int j)
{
    if(T[i]!='#'&&T[j]!='#')
    {
        while(i!=j)
        {
            if(i>j)
                i=i/2;
            else
                j=j/2;
        }
        return T[i];
    }
}

假設二叉樹採用二叉連結串列儲存結構,設計一個非遞迴演算法求二叉樹高度

int Btdepth(BiTree T)
{
    if(!T)
        return 0;
    int front=-1,rear=-1;
    int last=0,level=0;
    BiTree Q[MaxSize];
    Q[++rear]=T;
    BiTree P;
    while(front<rear)
    {
        p=Q[++front];
        if(p->lchild)
            Q[++rear]=p->lchild;
        if(p->rchild)
            Q[++rear]=p->rchild;
        if(front==last)
        {
            level++;
            last=rear;
        }
        return level;
    }
}

二叉樹按二叉連結串列形式儲存,寫一個判別給定二叉樹是否是完全二叉樹的演算法

解題思想: 
根據完全二叉樹的定義,具有n個結點的完全二叉樹與滿二叉樹中編號1–n的結點一一對應。 
採用層次遍歷的演算法,將所有結點加入佇列(包括空結點),當遇到空結點時,檢視其後是否有非空結點,若有,則二叉樹不是完全二叉樹。

bool IsComplete(BiTree &T)
{
    InitQueue(Q);
    if(!T)                        空樹為滿二叉樹
        return 1;
    EnQueue(Q,T);
    while(!IsEmpty(Q))
    {
        DeQueue(Q,p);
        if(p)                      結點非空,將其左右樹入佇列
        {
            EnQueue(Q,p->lchild);
            EnQueue(Q,p->rchild);
        }
        else                       結點為空,檢查其後是否有非空結點
        {
            while(!IsEmpty(Q))
            {
                DeQueue(Q,p);
                if(p)              結點為空,檢查其後是否有非空結點
                    return 0;
            }
        }
        return 1;
    }
}

假設二叉樹採用二叉連結串列儲存結構儲存,試設計一個演算法,計算給定二叉樹的所有雙分支結點個數

int DsonNodes(BiTree &T)
{
    if(T==null)
        return 0;
    else if(T->lchild!=null&&T->rchild!=null)
        return DsonNodes(T->lchild)+DsonNodes(T->rchild)+1;
    else
        return DsonNodes(T->lchild)+DsonNodes(T->rchild);
}

假設二叉樹採用二叉連結串列儲存結構,設計一個演算法,求先序遍歷序列中第k個結點的值(1≤k≤二叉樹中結點個數)

解題思路: 
設定一個全域性變數i記錄已訪問過的結點序號,其初值是根結點在先序序列中的序號,即為1,。 
當二叉樹為空時返回特殊字元‘#’。 
當i=k時,小時豪到滿足條件的結點。返回b->data; 
當i!=k時,則遞迴地在左子樹中查詢,若找到了則返回該值,否則繼續遞迴地在右子樹中查詢,並返回其結果

int i=1;
ElemType PreNode(BiTree b,int k)
{
    if(b==null)
        return '#';
    if(i==k)
        return b->data;
    ch=PreNode(b->lchild,k);
    if(ch!='#')
        return ch;
    ch=PreNode(b->rchild,k);
        return ch;
}

在二叉樹中查詢值為x的結點,試編寫演算法,列印值為x的結點的所有祖先,假設值為x的結點不多於1個

演算法思想:採用非遞迴後序遍歷,最後訪問根節點,當訪問之為x的結點時,棧中所有元素均為該結點的祖先,依次出棧列印即可

typedef struct
{
    BiTree t;
    int tag;
}stack          tag=0表示左子樹被訪問,tag=1時表示右子女被訪問

void search(BiTree bt,ElemType x)
{
    stack s[];
    top=0;
    while(bt!=null||top>0)
    {
        while(bt!=null&&bt->data!=x)
        {
            s[++top].t=bt;
            s[top].tag=0;
            bt=bt->lchild;
        }
        if(bt->data==x)
        {
            printf("所查結點的所有祖先結點的值為:");
            for(int 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;
        }
    }
}

若一棵二叉樹的結點結構為(LLIKE,INFO,RLINK),ROOT指向該二叉樹根結點的指標,p和q分別指向該二叉樹中任意兩個結點,試比阿尼額演算法,ANCESTOR(ROOT,p,q,r),該演算法找到p和q的最近公共祖先結點

演算法思想: 
採用後續非遞迴遍歷演算法,棧中存放二叉樹結點的指標,當訪問到某結點時,棧中所有元素均為該結點的祖先,後續遍歷必然先遍歷到結點p,棧中元素均為p的忑結點,先將棧複製到另一塊輔助棧中去,繼續遍歷到結點q時,將棧中元素從棧頂開始逐個到輔助棧中去匹配,第一個匹配到的元素即結點p與q的公共最近祖先。

typedef struct
{
    BiTree t;
    int tag;    tag=0左子女被訪問過,tag=1時,右子女被訪問過
}srack;

stack s1[],s2[];
BiTree Ancestor(BiTree ROOT,BiTNode *p,BiTNode *q)
{
    top=0;
    bt=ROOT;
    while(bt!=null&&bt!=p&&bt!=q)
    {
        while(bt!=null)
        {
            s[++top].t=bt;
            s[top].tag=0;
            bt=bt->lchild;
        }
        while(top!=0&&s[top].tag==1)
        {
            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--)
                        for(j=top1;j>0;j--)
                            if(s1[j].t==s[i].t)
                                return s[i].t;
                }
                top--;
            }
            if(top!=0)
            {
                s[top].tag=1;
                bt=s[top].t->rchild;
            }
        }
    }
}

假定二叉樹採用二叉連結串列儲存結構,設計一個演算法,求非空二叉樹b的寬度(即具有結點數最多的那一層的結點個數)

採用層次遍歷,求出所有結點的層次,並將所有結點與對應的層次放在一個佇列中,然後通過掃描佇列求出各層的結點總數即二叉樹的寬度

typedef struct
{
    BiTree data[MaxSize];        結點
    int level[MaxSize];          儲存data中相同下表的結點層
    int front,rear;              
}Qu;

int BTWidth(BiTree b)
{
    BiTree p;
    int i,k,max,n;
    Qu.front=Qu.rear=-1;
    Qu.rear++;
    Qu.data[Qu.rear]=b;
    Qu.level[Qu.rear]=1;
    while(QU.front<Qu.front)
    {
        Qu.rear++;
        p=Qu.data[Qu.front];
        k=Qu.data[Qu.front];
        if(p->lchild!=null)
        {
            Qu.rear++;
            Qu.data[Qu.rear]=p->lchild;
            Qu.level[Qu.rear]=k+1;
        }
        if(p->rchild!=null)
        {
            Qu.rear++;
            Qu.data[Qu.rear]=p->rchild;
            Qu.level[Qu.rear]=k+1;
        }
        max=0;
        i=0;k=1;
        while(i<=Qu.rear)
        {
            n=0;
            while(i<=Qu.rear&&Qu.level[i]==k)
            {
                i++;n++;
            }
            k=Qu.level[i];
            if(n>max)
            max=n;
        }
        return max;
    }
}

設計一個演算法,將二叉樹的葉結點從做導遊的順序連成一個單鏈表,表頭指標為head,二叉樹按二叉連結串列方式儲存,連結時用葉結點的右指標域來存放單鏈表指標

演算法思想: 
通常我們所使用的先序,中序和後續遍歷對於葉結點的訪問都從左到右排序,這裡我們採用中序遍歷遞迴演算法。 
設前驅結點指標pre,初始為空,第一個葉結點由指標head指向,遍歷到葉結點時,就將它的前驅rchild指向它,最後一個葉結點rchild為空

LinkList head,pre=null;
LinkList InOrder(BiTree bt)
{
    if(bt)
    {
        InOrder(br->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;
    }
}

試設計判斷兩課二叉樹是否相似的演算法。所謂二叉樹T1與T2相似,指的是T1與T2都是空的二叉樹或都只有一個根結點;或T1的左子樹與T2的左子樹是相似的且T1的右子樹與T2的右子樹是相似的

int similar(BiTree T1,BiTree T2)
{
    int lefts,rights;
    if(T1==NULL&&t2==NULL)
        return 1;
    else if(T1==NULL||T2==NULL)
        return 0;
    else
    {
        lefts=similar(T1->lchild,T2->lchild)
        rights=similar(T1->rchild,T2->rchild);
        return lefts&&rights;
    }
}