NeuDs 数据结构月考2

本文涉及数据结构中的二叉树知识,包括二叉树的转换、遍历方式(前序、中序、后序)、完全二叉树和满二叉树的区别、二叉排序树的性质、哈夫曼编码以及查找效率等。文章还包含了多项判断题和选择题,用于检验对这些概念的理解,并提供了二叉树相关问题的解决方案,如先序遍历输出叶节点、度为1的节点,以及求解二叉树高度等编程题。
摘要由CSDN通过智能技术生成

NeuDs 数据结构月考2:树+前/中/后序遍历


一.判断题


将一棵树转成二叉树,根结点没有左子树。F ---应该是没有右子树


一棵有9层结点的完全二叉树(层次从1开始计数),至少有512。F

完全二叉树并不是,满二叉树,所以第九层可能只有一个,但是要求第八层是满的;所以总节点数至少有2^{8}-1=255个结点,所以此题为F


补充知识:

知识点来源:数据结构第二版 P107

(1)一个二叉树第 i 层的最大结点数位 2^{i-1},i>=1;

(2)深度为k的二叉树有最大结点总数  2^{k}-1,k>=1


一棵树中,某结点位置上方各层中的所有结点都是该结点的祖先。F


如果完全二叉树从根结点开始按层次遍历的输入序列为1,2,3,4,5,6,7,则该完全二叉树是二叉排序树。F


哈夫曼编码是一种最优的前缀码。对一个给定的字符集及其字符频率,其哈夫曼编码不一定是唯一的,但是每个字符的哈夫曼码的长度一定是唯一的。F

长度也不唯一,若每个字符的字符频率都一样,那长度也不唯一


在二叉树的顺序存储结构中(根的下标为1),下标为130的结点一定处于左子树中。T

对于顺序二叉树存储来说(根的下标为1)

1.第n个元素的左子结点为 2*n

2.第n个元素的右子结点为 2*n+1

3.第n个元素的父结点为 n/2


非空二叉树的形态

一棵非空二叉树,若后序遍历与中序遍历的序列相同,则该二叉树所有结点均无左孩子。F

没有右孩子


中根遍历二叉查找树所得序列一定是有序序列。T


任何最小堆中从根结点到任一叶结点路径上的所有结点是有序的(从小到大)。T


任何二叉搜索树中同一层的结点从左到右是有序的(从小到大)。T


给定一棵树,可以找到唯一的一棵二叉树与之对应。 T


 一棵有124个结点的完全二叉树,其叶结点个数是确定的。T


二叉排序树的查找效率和二叉排序树的髙度有关。T


若一个结点是某二叉树的中序遍历序列的最后一个结点,则它必是该树的前序遍历序列中的最后一个结点。F 


在一棵二叉搜索树上查找63,序列39、101、25、80、70、59、63是一种可能的查找时的结点值比较序列。F

解析:根结点39,63大,往右子树找,但是右子树中有25比39小,二叉搜索树右子树的结点一定比根结点大,所以错


 


二.单选题


1.设最小堆(小根堆)的层序遍历结果为{1, 3, 2, 5, 4, 7, 6}。用线性时间复杂度的算法将该堆调整为最大堆(大根堆),则该树的中序遍历结果为:

A.1, 4, 3, 7, 2, 6, 5

B.3, 5, 4, 7, 2, 6, 1

C.4, 1, 3, 7, 6, 2, 5

D.3, 5, 4, 2, 6, 1, 7


2.关于二叉排序树的描述不正确的是____。

A.在最坏情况下,利用插入操作构造一颗二叉排序树花费的代价为O(log2​n)。

B.在含有n个结点的平衡二叉排序树中,查找失败时最多花费代价为O(log2​n)。

C.从二叉排序树中删去一个结点后再重新插入,一定是作为叶子结点插入的。

D.二叉排序树的查找效率取决于树的。

最差类似于的数组类似于单链表,为O(n)


3.一棵二叉树,度为2结点数为94,度为1结点数为124,则叶子结点数为( ).

A.93

B.123

C.95

D.125

注:此公式只在二叉树中才能使用

总数 N = n0 + n1 +n2

n0 = n2 +1 

n0 =  94 +1 =95


4.具有20个结点的二叉树使用二叉链表进行存储,其中空指针的数目是( ).

A.19

B.40

C.21

D.190


5.已知一二叉树的后序和中序遍历的结果分别是FDEBGCA 和FDBEACG,那么该二叉树的前序遍历结果是什么?

A.ABDEFCG

B.ABCDEFG

C.ABDFECG

D.ABDFEGC


6.一棵有101个结点的树一定有______条边。

A.200

B.101

C.99

D.100

一颗N个节点的树有 N - 1条边


7.若以{4,5,6,3,8}作为叶子节点的权值构造哈夫曼树,则带权路径长度是()。

A.59

B.28

C.55

D.68


8.对于二叉树,如果其中序遍历结果与前序遍历结果一样,那么可以断定该二叉树:

A.所有结点都没有左儿子

B.是完全二叉树

C.所有结点都没有右儿子

D.这样的树不存在


9.若一棵二叉树的前序遍历序列是{ 4, 2, 1, 3, 6, 5, 7 },中序遍历序列是{ 1, 2, 3, 4, 5, 6, 7 },则下列哪句是错的?

A.6是3的父结点

B.所有的奇数都在叶子结点上

C.这是一棵完全二叉树

D.这是一棵二叉搜索树


10.完全二叉树的第6层有10个节点,该完全二叉树总计有多少个节点( ).

A.74

B.42

C.41

D.73

前5层总数为2^{5}-1=31,加上第六层 ;31+10=41


11.有17个叶子的哈夫曼树的结点总数为 ( ).

A.288

B.35

C.33

D.34

n个叶子的哈夫曼树的结点总数为2n-1

有n个叶子的哈夫曼树的结点总数为( )。__牛客网 (nowcoder.com)


12.给二叉树的结点编号

对一棵二叉树的结点从 1 开始顺序编号。要求每个结点的编号大于其左、右孩子的编号,且左孩子的编号小于右孩子的编号。可采用 ▁▁▁▁▁ 实现编号。

A.层次遍历

B.中序遍历

C.先序遍历

D.后序遍历

先左,后右,在父结点,则为后序遍历


13.若二叉搜索树是有N个结点的完全二叉树,则不正确的说法是:

A.最小值一定在叶结点上

B.最大值一定在叶结点上

C.所有结点的平均查找效率是O(logN)

D.中位值结点在根结点或根的左子树上

最大值在右子树上,但不一定是叶子结点


14.在下述结论中,正确的是:

① 只有2个结点的树的度为1;

② 二叉树的度为2;

③ 二叉树的左右子树可任意交换;

④ 在最大堆(大顶堆)中,从根到任意其它结点的路径上的键值一定是按非递增有序排列的。

A.①④

B.②④

C.②③④

D.①②③

空二叉树的度为0,二叉树的左右子树不能随意交换


15.完全二叉树顺序存储,结点X的编号为21,则其右孩子结点的编号是( )

A.22

B.20

C.43

D.42

当根结点从1,开始存储,第n号结点的左孩子为2n;右孩子为2n+1;

当根节点从0,开始村粗,第n号节点的左孩子为2n+1,右孩子为2n+2;


16.关于二叉排序树的描述不正确的是____。

A.二叉排序树的查找效率取决于树的高度。

B.在含有n个结点的平衡二叉排序树中,查找失败时最多花费代价为O(log2​n)。

C.在最坏情况下,利用插入操作构造一颗二叉排序树花费的代价为O(log2​n)。

D.从二叉排序树中删去一个结点后再重新插入,一定是作为叶子结点插入的。

二叉查找树的查询速度取决于树的深度/高度,相同结点数深度/高度最小的是平衡二叉树。


对于平衡二叉树时,因为其高度是最小的,所以为在查找时效率最高;查找失败也为O(log2n)


对于插入操作就不一样了,最坏的情况会变成单链表的插入,时间花费为O(n)


三.函数题


R6-1 先序输出叶结点

本题要求按照先序遍历的顺序输出给定二叉树的叶结点。

函数接口定义:

void PreorderPrintLeaves( BinTree BT );

其中BinTree结构定义如下:

typedef struct TNode *Position; typedef Position BinTree; struct TNode{ ElementType Data; BinTree Left; BinTree Right; };

函数PreorderPrintLeaves应按照先序遍历的顺序输出给定二叉树BT的叶结点,格式为一个空格跟着一个字符。

裁判测试程序样例:

#include <stdio.h> #include <stdlib.h> typedef char ElementType; typedef struct TNode *Position; typedef Position BinTree; struct TNode{ ElementType Data; BinTree Left; BinTree Right; }; BinTree CreatBinTree(); /* 实现细节忽略 */ void PreorderPrintLeaves( BinTree BT ); int main() { BinTree BT = CreatBinTree(); printf("Leaf nodes are:"); PreorderPrintLeaves(BT); printf("\n"); return 0; } /* 你的代码将被嵌在这里 */

输出样例(对于图中给出的树):

Leaf nodes are: D E H I
void PreorderPrintLeaves( BinTree BT)
{
    if(BT!=NULL)//若结点不空
    {
        if(BT->Left==NULL&&BT->Right==NULL)//判断是否为叶节点
        {
            printf(" %c",BT->Data);
            return ;
        }else{
            PreorderPrintLeaves(BT->Left);//递归遍历左节点
            PreorderPrintLeaves(BT->Right);//递归遍历右节点
        }
    }


    
}

R6-1 先序输出度为1的结点

本题要求实现一个函数,按照先序遍历的顺序输出给定二叉树中度为1的结点。

函数接口定义:

void PreorderPrintNodes( BiTree T);

T是二叉树树根指针,PreorderPrintNodes按照先序遍历的顺序输出给定二叉树T中度为1的结点,格式为一个空格跟着一个字符。

其中BiTree结构定义如下:

typedef struct BiTNode
{
    ElemType data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;

裁判测试程序样例:

#include <stdio.h> #include <stdlib.h> typedef char ElemType; typedef struct BiTNode { ElemType data; struct BiTNode *lchild,*rchild; }BiTNode,*BiTree; BiTree Create();/* 细节在此不表 */ void PreorderPrintNodes( BiTree T); int main() { BiTree T = Create(); printf("Nodes are:"); PreorderPrintNodes(T); return 0; } /* 你的代码将被嵌在这里 */

输入样例:

输入为由字母和'#'组成的字符串,代表二叉树的扩展先序序列。例如对于如下二叉树,输入数据:

ACG#H###BEF###D##

输出样例(对于图中给出的树):


Nodes are: C G E
void PreorderPrintNodes(BiTree T){
    if(T != NULL){
        if((T->lchild == NULL && T->rchild != NULL) || (T->lchild != NULL && T->rchild == NULL)){
            printf(" %c", T->data);
        }
        PreorderPrintNodes(T->lchild);
        PreorderPrintNodes(T->rchild);
    }
}


R6-2 求二叉树高度

本题要求给定二叉树的高度。

函数接口定义:

int GetHeight( BinTree BT );

其中BinTree结构定义如下:

typedef struct TNode *Position; typedef Position BinTree; struct TNode{ ElementType Data; BinTree Left; BinTree Right; };

要求函数返回给定二叉树BT的高度值。

裁判测试程序样例:

#include <stdio.h> #include <stdlib.h> typedef char ElementType; typedef struct TNode *Position; typedef Position BinTree; struct TNode{ ElementType Data; BinTree Left; BinTree Right; }; BinTree CreatBinTree(); /* 实现细节忽略 */ int GetHeight( BinTree BT ); int main() { BinTree BT = CreatBinTree(); printf("%d\n", GetHeight(BT)); return 0; } /* 你的代码将被嵌在这里 */

输出样例(对于图中给出的树):

4

在此函数中,首先判断输入的二叉树指针是否为空,若是则直接返回0。否则,如果输入的二叉树只有一个根结点,那么高度为1,直接返回即可。对于其他情况,则递归计算左右子树的高度,并取两者高度的较大值再加上1即可得到整棵二叉树的高度。 

int GetHeight(BinTree BT)
{
    if (!BT) // 空树高度为0
        return 0;
    else if (!BT->Left && !BT->Right) // 只有一个根结点,高度为1
        return 1;
    else
    {
        int left_height = GetHeight(BT->Left); // 计算左子树的高度
        int right_height = GetHeight(BT->Right); // 计算右子树的高度
        if(left_height>right_height)return left_height+1;
        else return right_height+1;
    }
}

R6-2 二叉树的遍历

本题要求给定二叉树的4种遍历。

函数接口定义:

void InorderTraversal( BinTree BT ); void PreorderTraversal( BinTree BT ); void PostorderTraversal( BinTree BT ); void LevelorderTraversal( BinTree BT );

其中BinTree结构定义如下:

typedef struct TNode *Position; typedef Position BinTree; struct TNode{ ElementType Data; BinTree Left; BinTree Right; };

要求4个函数分别按照访问顺序打印出结点的内容,格式为一个空格跟着一个字符。

裁判测试程序样例:

#include <stdio.h> #include <stdlib.h> typedef char ElementType; typedef struct TNode *Position; typedef Position BinTree; struct TNode{ ElementType Data; BinTree Left; BinTree Right; }; BinTree CreatBinTree(); /* 实现细节忽略 */ void InorderTraversal( BinTree BT ); void PreorderTraversal( BinTree BT ); void PostorderTraversal( BinTree BT ); void LevelorderTraversal( BinTree BT ); int main() { BinTree BT = CreatBinTree(); printf("Inorder:"); InorderTraversal(BT); printf("\n"); printf("Preorder:"); PreorderTraversal(BT); printf("\n"); printf("Postorder:"); PostorderTraversal(BT); printf("\n"); printf("Levelorder:"); LevelorderTraversal(BT); printf("\n"); return 0; } /* 你的代码将被嵌在这里 */

输出样例(对于图中给出的树):

Inorder: D B E F A G H C I
Preorder: A B D F E C G H I
Postorder: D E F B H G I C A
Levelorder: A B C D F G I E H
void InorderTraversal( BinTree BT )
{
    if(BT)
    {
        InorderTraversal(BT->Left);
        printf(" %c",BT->Data);
        InorderTraversal(BT->Right);
    }
}

void PreorderTraversal( BinTree BT )
{
    if(BT)
    {
        printf(" %c",BT->Data);
        PreorderTraversal(BT->Left);
        PreorderTraversal(BT->Right);
    }
}

void PostorderTraversal( BinTree BT )
{
    if(BT)
    {
        PostorderTraversal(BT->Left);
        PostorderTraversal(BT->Right);
        printf(" %c",BT->Data);
    }
}
void LevelorderTraversal( BinTree p )
{
    int i=0,j=0;//利用一个很长的数组来模拟队列操作
    BinTree ptr[100]={NULL},ptr1=NULL;
    if(p!=NULL)
    {
        ptr[i++]=p;
        while(i>j)
        {
            ptr1=ptr[j++];
            printf(" %c",ptr1->Data);
            if(ptr1->Left!=NULL)ptr[i++]=ptr1->Left;
            if(ptr1->Right!=NULL)ptr[i++]=ptr1->Right;
        }
    }
}


 四.编程题


R7-1 完全二叉树的权值

给定一棵包含 N 个节点的完全二叉树,树上每个节点都有一个权值,按从上到下、从左到右的顺序为A1​,A2​,A3​⋅⋅⋅AN​

现在小明要把相同深度的节点的权值加在一起,他想知道哪个深度的节点权值之和最大?如果有多个深度的权值和同为最大,请你输出其中最小的深度。

注:根的深度是 1。

输入格式:

第一行包含一个整数N(1 ≤ N ≤ 100000)

第二行包含 N个整数,A1​,A2​,A3​⋅⋅⋅AN​(-100000 ≤ Ai​ ≤ 100000)

输出格式:

输出一个整数代表答案,结尾无空格换行。

输入样例:

在这里给出一组输入。例如:

7
1 6 5 4 3 2 1

输出样例:

在这里给出相应的输出。例如:

2

题目来源:蓝桥杯省赛真题

这道题可基于,二叉树的数组存储来+数学函数来实现每一深度的结点权值相加,并不需要构造二叉树 ;以下是手画的图例

#include<bits/stdc++.h>
#include<math.h>
using namespace std;

int main()
{
    int n;
    cin>>n;
    int *a = new int[n+1];
    int *b = new int[n+1];

    for(int i=0;i<n+1;i++)
    {
        a[i]=b[i]=0;
    }
    
    for(int i=1;i<n+1;i++)
    {
        cin>>a[i];
    }
    
    for(int i=1;i<=log2(n+1);i++)
    {
        int sum=0;
        for(int k=pow(2,i-1);k<=pow(2,i)-1;k++)
        {
            sum+=a[k];
        }
        b[i]=sum;
    }

    int maxid=1;
    for(int i=1;i<n+1;i++)
    {
        if(b[i]>b[maxid])maxid=i;
    }
    cout<<maxid;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

H._

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值