16.考研-数据结构-二叉树的相关算法01

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Suyebiubiu/article/details/81323272

中序遍历对二叉树线索化的递归算法

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;
    }
}

猜你喜欢

转载自blog.csdn.net/Suyebiubiu/article/details/81323272