【王道数据结构编程题】- 二叉树算法题

目录

1.已知一颗二叉树按顺序存储结构进行存储,设计一个算法,求编号分别为i和j的两个节点的最近的公共祖先节点的值。

2.编写后序遍历的二叉树的非递归算法

3.试给出二叉树的自下而上,从右到左的层次遍历算法。

4.假设二叉树采用二叉链表存储结构,设计一个非递归算法求二叉树的高度。

 5.设一颗二叉树中各个节点的值互不相同,其先序遍历序列和中序遍历序列分别存于两个一维数组A[1...n]和B[1...n]中,试编写算法建立该二叉树的二叉链表。

6.二叉树按二叉链表形式存储,写一个判别给定二叉树是否是完全二叉树的算法。

7.假设二叉树采用二叉链表存储结构存储,试着设计一个算法,计算一颗给定二叉树的所有双分支节点的个数。

8.设树B是一颗采用链式结构存储的二叉树,编写一个把树B中所有节点的左,右子树进行交换的函数。


1.已知一颗二叉树按顺序存储结构进行存储,设计一个算法,求编号分别为i和j的两个节点的最近的公共祖先节点的值。

#include <stdio.h>
#include <malloc.h>
#define MaxSize 13

typedef struct TNode
{
    char data;
    TNode* lchild;
    TNode* rchild;
}TNode;

int find_public(TNode T[],int i,int j)//注意这里不是TNode* &T
{
    if(T[i].data!='#'&&T[j].data!='#')//还要判断结点是否存在
    {
        while(i!=j)
        {
            if(i>j)
                i=i/2;
            else
                j=j/2;
        }
        return i;
    }
    else
        return 0;

}

int main()
{
    TNode T[MaxSize];
    for(int i=1;i<MaxSize;i++)//从数组下标1开始存储
    {
        char c;
        scanf("%c",&c);
        T[i].data=c;
    }
    int k=find_public(T,4,10);
    printf("%c\n",T[k].data);//测试数据:ABCDE####F#,输出data:B
    return 0;
}
/*
      A
	B   C
  D   E  
     F 
*/

2.编写后序遍历的二叉树的非递归算法

//非递归的一个后序遍历二叉树
#include<iostream>
using namespace std;
typedef struct TreeNode{
    char data;
    struct TreeNode *lchild,*rchild;
    int tag;
}TreeNode,*Tree;
void creattree(Tree &t)
{
    char ch;
    ch=getchar();
    if(ch=='#') t=NULL;
    else
    {
        t=(TreeNode *)malloc(sizeof(TreeNode));
        t->data=ch;
        t->tag=0;
        t->lchild=NULL;
        t->rchild=NULL;
        creattree(t->lchild);
        creattree(t->rchild);
    }
}
void back(Tree t)
{
    struct TreeNode *stack[100];
    int top=-1;
    TreeNode *p=t;
    TreeNode *x;
    while(p||top!=-1)
    {
        if(p)
        {
            top++;
            stack[top]=p;
            p=p->lchild;
        }
        else
        {
            p=stack[top];
            if(p->rchild&&p->rchild->tag==0)
                p=p->rchild;
            else
            {
                p=stack[top];
                top--;
                cout<<p->data<<" ";
                p->tag=1;
                p=NULL;
            }
        }
    }
}
int main()
{
    Tree t;
    creattree(t);
    back(t);
    return 0;
}
//ABDEC
//测试:ABD##E##C##

3.试给出二叉树的自下而上,从右到左的层次遍历算法。

#include<iostream>
using namespace std;
#define Max 10
typedef struct treenode{
    char data;
    struct treenode *lchild,*rchild;
}treenode,*tree;
void buildtree(tree &t)
{
    char ch;
    ch=getchar();
    if(ch=='#') t=NULL;
    else
    {
        t=(treenode *)malloc(sizeof(treenode));
        t->data=ch;
        t->lchild=NULL;
        t->rchild=NULL;
        buildtree(t->lchild);
        buildtree(t->rchild);
    }
}
typedef struct stack1{
    struct treenode *data[Max];
    int top;
}stack1;
bool isempty(stack1 s)
{
    if(s.top==-1) return true;
    return false;
}
bool isfull(stack1 s)
{
    if(s.top==Max-1)    return true;
    return false;
}
bool enters(stack1 &s,treenode *p)
{
    if(isfull(s))
    {
        cout<<"栈满"<<endl;
        return false;
    }
    s.data[++s.top]=p;
    return true;
}
bool outs(stack1 &s,treenode *&p)
{
    if(isempty(s))
    {
        cout<<"栈空"<<endl;
        return false;
    }
    p=s.data[s.top--];
    return true;
}
struct squeue1{
    struct treenode *data[Max];
    int f,r,tag;
};
bool entersqueue(squeue1 &s,treenode *x)
{
    if(s.f==s.r&&s.tag==1)
    {
        cout<<"队满"<<endl;
        return false;
    }
    s.data[s.r]=x;
    s.r=(s.r+1)%Max;
    s.tag=1;
    return true;
}
int outsqueue(squeue1 &s,treenode *&x)
{
    if(s.f==s.r&&s.tag==0)
    {
        cout<<"队空"<<endl;
        return 0;
    }
    x=s.data[s.f];
    s.f=(s.f+1)%Max;
    s.tag=0;
    return 1;
}
void solve(tree t)
{
    stack1 s;
    squeue1 q;
    treenode *p;
    if(t)
    {
        s.top=-1;
        q.f=q.r=q.tag=0;
        entersqueue(q,t);
        while(!(q.f==q.r&&q.tag==0))
        {
            outsqueue(q,p);
            enters(s,p);
            if(p->lchild) entersqueue(q,p->lchild);
            if(p->rchild) entersqueue(q,p->rchild);
        }
        while(!isempty(s))
        {
            outs(s,p);
            cout<<p->data<<" ";
        }
    }
}
int main()
{
    tree t;
    buildtree(t);
    solve(t);
    return 0;
}
//测试数据:ABD##E##CF##G## 

4.假设二叉树采用二叉链表存储结构,设计一个非递归算法求二叉树的高度。

//非递归计算二叉树的高度
#include<iostream>
using namespace std;
typedef struct treenode{
    char data;
    struct treenode *lchild,*rchild;
}treenode,*tree;
void buildtree(tree &t)
{
    char ch;
    ch=getchar();
    if(ch=='#') t=NULL;
    else
    {
        t=(treenode *)malloc(sizeof(treenode));
        t->data=ch;
        t->lchild=NULL;
        t->rchild=NULL;
        buildtree(t->lchild);
        buildtree(t->rchild);
    }
}
int dept(tree t)
{
    if(!t) return 0;
    tree q[10];
    int f=-1,r=-1;
    int L=0,ans=0;
    q[++r]=t;
    tree p;
    while(f<r)
    {
        p=q[++f];
        if(p->lchild) q[++r]=p->lchild;
        if(p->rchild) q[++r]=p->rchild;
        if(f==L)
        {
            ans++;
            L=r;
        }
    }
    return ans;
}
int main()
{
    tree t;
    buildtree(t);
    cout<<"树的高度为:"<<dept(t)<<endl;
    return 0;
}
//测试数据:ABD##E##CF###

 5.设一颗二叉树中各个节点的值互不相同,其先序遍历序列和中序遍历序列分别存于两个一维数组A[1...n]和B[1...n]中,试编写算法建立该二叉树的二叉链表。

//中序先序构造二叉树
#include<iostream>
using namespace std;
typedef struct treenode{
    char data;
    struct treenode *lchild,*rchild;
}treenode,*tree;
int pos=0;
tree build(char a[],char b[],int s,int e)
{
    if(s<=e)
    {
        treenode *root=(treenode *)malloc(sizeof(treenode));
        root->data=a[pos];
        int i;
        for(i=s;i<=e;i++) if(b[i]==root->data) break;
        pos++;
        root->lchild=build(a,b,s,i-1);
        root->rchild=build(a,b,i+1,e);
        return root;
    }
    return NULL;
}
void disp(tree t)
{
    if(t)
    {
        disp(t->lchild);
        disp(t->rchild);
        cout<<t->data<<" ";
    }
}
int main() {
    char a[]={'A','B','D','E','C','F'};//先序序列
    char b[]={'D','B','E','A','F','C'};//中序序列
    tree root=build(a,b,0,5);
    cout<<"后序序列为:"<<endl;
    disp(root);
	return 0;
}
/*        A
       /    \
      B      C
     / \    /
    D   E  F
*/

6.二叉树按二叉链表形式存储,写一个判别给定二叉树是否是完全二叉树的算法。

//判断是否是完全二叉树
#include<iostream>
using namespace std;
#define Max 15
typedef struct treenode{
    char data;
    struct treenode *lchild,*rchild;
}treenode,*tree;
void buildtree(tree &t)
{
    char ch;
    ch=getchar();
    if(ch=='#') t=NULL;
    else
    {
        t=(treenode *)malloc(sizeof(treenode));
        t->data=ch;
        t->lchild=NULL;
        t->rchild=NULL;
        buildtree(t->lchild);
        buildtree(t->rchild);
    }
}
struct squeue{
    struct treenode *data[Max];
    int f,r,tag;
};
bool isempty(squeue s)
{
    if(s.f==s.r&&s.tag==0) return true;
    return false;
}
bool isfull(squeue s)
{
    if(s.f==s.r&&s.tag==1) return true;
    return false;
}
bool enters(squeue &s,treenode *p)
{
    if(isfull(s)) return false;
    s.data[s.r]=p;
    s.r=(s.r+1)%Max;
    s.tag=1;
    return true;
}
bool outs(squeue &s,treenode *&p)
{
    if(s.f==s.r&&s.tag==0) return false;
    p=s.data[s.f];
    s.f=(s.f+1)%Max;
    s.tag=0;
    return true;
}
bool isok(tree t)
{
    squeue s;
    s.f=s.r=s.tag=0;
    bool flag=true,ans=true;
    if(t==NULL) ans=true;
    if(!t->lchild&&!t->rchild) ans=true;
    enters(s,t);
    treenode *p;
    while(!isempty(s))
    {
        outs(s,p);
        if(!p->lchild)
        {
            flag=false;
            if(p->rchild) ans=false;
        }
        else//有左孩子
        {
            if(flag)//之前不存在缺孩子的节点
            {
                enters(s,p->lchild);
                if(p->rchild) enters(s,p->rchild);
                else flag=false;
            }
            else//之前存在缺孩子的节点
                ans=false;
        }
    }
    if(ans) return true;
    return false;
}
int main()
{

   tree t;
   buildtree(t);
   if(isok(t)) cout<<"yes"<<endl;
   else cout<<"no"<<endl;
    return 0;
}
//ABD##E##CF##G##  完全
//ABD###CE##F##  非完全

7.假设二叉树采用二叉链表存储结构存储,试着设计一个算法,计算一颗给定二叉树的所有双分支节点的个数。

//计算二叉树中双分支结点的个数
#include<iostream>
using namespace std;
typedef struct treenode{
    char data;
    struct treenode *lchild,*rchild;
}treenode,*tree;
void buildtree(tree &t)
{
    char ch;
    ch=getchar();
    if(ch=='#') t=NULL;
    else
    {
        t=(treenode *)malloc(sizeof(treenode));
        t->data=ch;
        t->lchild=NULL;
        t->rchild=NULL;
        buildtree(t->lchild);
        buildtree(t->rchild);
    }
}
int num(tree t)
{
    if(!t) return 0;
    else if(t->lchild&&t->rchild) return num(t->lchild)+num(t->rchild)+1;
    else return num(t->lchild)+num(t->rchild);
}
int main()
{
    tree t;
    buildtree(t);
    cout<<"该二叉树中双分结点有 "<<num(t)<<" 个"<<endl;
    return 0;
}
/*
       A
     /  \
    B    C
  /\     /  \
 D E    F   G
 */
//前序序列:ABD##E##CF##G##

8.设树B是一颗采用链式结构存储的二叉树,编写一个把树B中所有节点的左,右子树进行交换的函数。

//交换左右子树
#include<iostream>
using namespace std;
typedef struct treenode{
    char data;
    struct treenode *lchild,*rchild;
}treenode,*tree;
void buildtree(tree &t)
{
    char ch;
    ch=getchar();
    if(ch=='#') t=NULL;
    else
    {
        t=(treenode *)malloc(sizeof(treenode));
        t->data=ch;
        t->lchild=NULL;
        t->rchild=NULL;
        buildtree(t->lchild);
        buildtree(t->rchild);
    }
}
void swap(tree &t)
{
    treenode *p;
    if(t)
    {
        swap(t->lchild);
        swap(t->rchild);
        p=t->lchild;
        t->lchild=t->rchild;
        t->rchild=p;
    }
}
void disp(tree t)
{
    if(t)
    {
        cout<<t->data<<" ";
        disp(t->lchild);
        disp(t->rchild);
    }
}
int main()
{
    tree t;
    buildtree(t);
    cout<<"交换过后的二叉树为(前序序列):"<<endl;
    swap(t);
    disp(t);
    return 0;
}
/*

             A                            A
          B    C                       C     B
        D  E  F  G                   G   F   E  D  

ABD##E##CF##G##                   ACGFBED 

*/

猜你喜欢

转载自blog.csdn.net/m0_56051805/article/details/125415110