数据结构算法复习2:树相关考点

算法实现方面要求,熟练掌握二叉树的递归和非递归遍历,并能够用之解决实际问题,如:计算树的层数、度,查找满足条件的节点等。

1,假设二叉树采用二叉链存储结构存储,设计一个算法,求先序遍历序列中第k(1≤k≤二叉树中节点个数)个节点的值

递归模型

    f(b,k)=' '                              当b=NULL时返回特殊字符' '
    f(b,k)=b->data                            当k=n
    f(b,k)=((ch=f(b->lchild,k))==' '?f(b->rchild,k):ch)      其他情况

对应的递归算法

    int n=1;                                   //全局变量
    ElemType PreNode(BTNode *b,int k)
    {   ElemType ch;
        if (b==NULL)
            return ' ';
        if (n==k)
            return(b->data);
        n++;
        ch=PreNode(b->lchild,k);            //遍历左子树
        if (ch!=' ')
            return(ch);                       //在左子树中找到后返回
        ch=PreNode(b->rchild,k);           //遍历右子树
        return(ch);                           //返回右子树中的遍历结果
    }

非递归算法,先序遍历对应的算法

ElemType PreNode1(BTNode *b,int k)        //先序遍历的非递归算法
    {   BTNode *St[MaxSize],*p;
        int top=-1,n=0;
        if (b!=NULL)
        {   top++;                            //根节点进栈
            St[top]=b;
            while (top>-1)                 //栈不为空时循环
            {   p=St[top];                    //退栈并访问该节点
                top--;
                n++;
                if (n==k) return(p->data);
                if (p->rchild!=NULL)      //右孩子节点进栈
                {   top++;
                     St[top]=p->rchild;
                }
                if (p->lchild!=NULL)      //左孩子节点进栈
                {   top++;
                    St[top]=p->lchild;
                }
            }
            printf("\n");
        }
        return(' ');
    }

2,假设二叉树采用二叉链存储结构存储,设计一个算法,求中序遍历序列中第k(1≤k≤二叉树中节点个数)个节点的值。

递归算法

    int n=1;            //全局变量
    ElemType InNode(BTNode *b,int k)
    {   ElemType ch;
        if (b==NULL)
            return ' ';
        ch=InNode(b->lchild,k);                //遍历左子树
        if (ch!=' ')                             //在左子树找到了便返回ch
            return ch;
        else
        {   if (n==k) 
                return b->data;
            n++;
            return InNode(b->rchild,k);       //返回在右子树中查找的结果
        }
    }

非递归算法

ElemType InNode1(BTNode *b,int k)          //中序遍历的非递归算法
    {   BTNode *St[MaxSize],*p;
        int top=-1,n=0;
        if (b!=NULL)
         {   p=b;
            while (top>-1 || p!=NULL)
            {   while (p!=NULL)                //扫描*p的所有左节点并进栈
                {   top++;
                    St[top]=p;
                    p=p->lchild;
                }
                if (top>-1)
                {   p=St[top];                //出栈*p节点
                    top--;
                    n++;
                    if (n==k) return(p->data);
                    p=p->rchild;           //扫描*p的右孩子节点
                }
            }
            printf("\n");
        }
        return(' ');
    }

3,假设二叉树采用二叉链存储结构存储,设计一个算法,求后序遍历序列中第k(1≤k≤二叉树中节点个数)个节点的值。

递归算法

int n=1;        //全局变量
 ElemType PostNode(BTNode *b,int k)
    {   ElemType ch;
        if (b==NULL)
            return ' ';
        ch=PostNode(b->lchild,k);        //遍历左子树
        if (ch!=' ')                       //在左子树找到了便返回ch
            return ch;
        else
        {   ch=PostNode(b->rchild,k);   //遍历右子树
            if (ch!=' ')                  //在右子树找到了便返回ch
                return ch;
            if (n==k) 
                return b->data;
            n++;
        }
    }

非递归算法

ElemType PostNode1(BTNode *b,int k)     //后序遍历的非递归算法
    {   BTNode *St[MaxSize];
        BTNode *p;
        int flag,top=-1,n=0;                //栈顶指针置初值
        if (b!=NULL)
        {   do
            {   while (b!=NULL)            //将*b的所有左节点进栈
                {   top++;
                    St[top]=b;
                    b=b->lchild;
                }
                p=NULL;                    //p指向栈顶节点的前一个已访问的节点
                flag=1;                    //设置b的访问标记为已访问过
                while (top!=-1 && flag)
                {   b=St[top];             //取出当前的栈顶元素
                    if (b->rchild==p)   //右孩子不存在或右孩子已被访问,访问之
                    {   n++;
                        if (n==k) return(b->data);
                        top--;
                        p=b;              //p指向则被访问的节点
                    }
                    else
                    {   b=b->rchild;   //b指向右孩子节点
                        flag=0;           //设置未被访问的标记
                    }
                }
            } while (top!=-1);
            printf("\n");
        }
        return(' ');
    }

4,假设二叉树采用二叉链存储结构存储,设计一个算法,求中序遍历序列中第一个节点的值。

ElemType FirstNode(BTNode *b)
    {   if (b==NULL)
            return(' ');
        while (b->lchild!=NULL)
            b=b->lchild;
        return(b->data);
    }

5,假设二叉树采用二叉链存储结构存储,试设计一个算法,计算一棵给定二叉树的所有节点数。

递归算法如下

int Nodes(BTNode *b)
    {   int num1,num2;
        if (b==NULL) 
            return 0;
        else
        {   num1=Nodes(b->lchild);
            num2=Nodes(b->rchild);
            return (num1+num2+1);
        }
    }

6,假设二叉树采用二叉链存储结构存储,设计一个算法计算一棵给定二叉树的所有叶子节点个数。

递归算法如下

int LeafNodes(BTNode *b)
    {   int num1,num2;
        if (b==NULL) 
            return 0;
        else if (b->lchild==NULL && b->rchild==NULL)
            return 1;
        else
        {   num1=LeafNodes(b->lchild);
            num2=LeafNodes(b->rchild);
            return (num1+num2);
        }
    }

7,假设二叉树采用二叉链存储结构存储,设计一个算法求其中最小值的节点值。

递归算法如下

void FindMinNode(BTNode *b,ElemType &min)
    {   if (b->data<min)
            min=b->data;
        FindMinNode(b->lchild,min);        //在左子树中找最小节点值
        FindMinNode(b->rchild,min);        //在右子树中找最小节点值
    }
    void MinNode(BTNode *b)
    {   if (b!=NULL)
        {   ElemType min=b->data;
            FindMinNode(b,min);
            printf("Min=%d\n",min);
        }
    }

8,假设二叉树采用二叉链存储结构存储,设计一个算法求其中节点值为x的节点个数。

对应的递归算法:

int FindCount(BTNode *b,ElemType x)
    {   if (b==NULL)
            return 0;
        else if (b->data==x)
            return(1+FindCount(b->lchild,x)+FindCount(b->rchild,x));
        else
            return(FindCount(b->lchild,x)+FindCount(b->rchild,x));
    }

9,假设二叉树采用链接存储结构进行存储,设计一个算法,求二叉树b的宽度(即具有节点数最多的那一层上的节点个数)并输出各节点的层次。

int BTWidth(BTNode *b)
    {   struct 
        {   int lno;                          //节点的层次编号
            BTNode *p;                        //节点指针
        } Qu[MaxSize];                        //定义非循环队列
        int front,rear;                       //定义队首和队尾指针
        int lnum,max,i,n;
        front=rear=0;                         //置队列为空队
        if (b!=NULL) 
        {   rear++;    
            Qu[rear].p=b;                     //根节点指针进队
            Qu[rear].lno=1;                   //根节点的层次编号为1
            while (rear!=front)               //队列不为空
            {   front++;
                b=Qu[front].p;                //队头出队
                lnum=Qu[front].lno;
                if (b->lchild!=NULL)       //左孩子进队
                {   rear++;
                    Qu[rear].p=b->lchild;
                    Qu[rear].lno=lnum+1;
                }
                if (b->rchild!=NULL)       //右孩子进队
                {   rear++;
                    Qu[rear].p=b->rchild;
                    Qu[rear].lno=lnum+1;
                }
            }
            printf("各节点的层编号:\n");
            for (i=1;i<=rear;i++)
                printf("   %c,%d\n",Qu[i].p->data,Qu[i].lnlno);
            max=0;lnum=1;i=1;
            while (i<=rear)
            {   n=0;
                while (i<=rear && Qu[i].lno==lnum) 
                {   n++;
                    i++;
                }
                lnum=Qu[i].lno;
                if (n>max) max=n;
            }
            return max;
        }
        else

            return 0; 
    }

10,假设二叉树以二叉链存储,设计一个算法,求其指定的某一层k(k>1)的叶子节点个数。

int LeafKLevel(BTNode *b,int k)
    {   BTNode *Qu[MaxSize];           //定义循环队列
        int front,rear;                //定义队首,队尾指针
        int leaf=0;                    //leaf累计叶子节点个数
        int last;                      //定义当前层中最右节点在队列中的位置
        int level;                     //定义当前节点的层号
        front=rear=0;                  //置队列为空队列
        if (b==NULL || k<=1)        //条件错误返回0
            return(0);
            rear++;                        //节点指针进队
        last=rear;level=1;             //第1层的最右节点在队列中的位置为1
        Qu[rear]=b;
        while (rear!=front)            //队列不为空时循环
        {   front=(front+1)%MaxSize;
            b=Qu[front];              //队头出队列
            if (level==k && b->lchild==NULL && b->rchild==NULL)
                leaf++;
            if (b->lchild!=NULL)   //左孩子进队
            {   rear=(rear+1)%MaxSize;
                Qu[rear]=b->lchild;
            }
            if (b->rchild!=NULL)   //右孩子进队
            {   rear=(rear+1)%MaxSize;
                Qu[rear]=b->rchild;
            }
            if (front==last)         //同层的最右节点处理完毕,层数增1
            {   level++;
                last=rear;           //让last指向下一层的最右节点在队列中的位置
            }
            if (level>k)          //当层号大于k时返回leaf,不再继续
                return(leaf);
        }
    }

猜你喜欢

转载自blog.csdn.net/weixin_40165004/article/details/121185587