NeuDs 数据结构月考2:树+前/中/后序遍历
一.判断题
将一棵树转成二叉树,根结点没有左子树。F ---应该是没有右子树
一棵有9层结点的完全二叉树(层次从1开始计数),至少有512。F
完全二叉树并不是,满二叉树,所以第九层可能只有一个,但是要求第八层是满的;所以总节点数至少有-1=255个结点,所以此题为F
补充知识:
知识点来源:数据结构第二版 P107
(1)一个二叉树第 i 层的最大结点数位 ,i>=1;
(2)深度为k的二叉树有最大结点总数 ,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(log2n)。
B.在含有n个结点的平衡二叉排序树中,查找失败时最多花费代价为O(log2n)。
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层总数为,加上第六层 ;31+10=41
11.有17个叶子的哈夫曼树的结点总数为 ( ).
A.288
B.35
C.33
D.34
n个叶子的哈夫曼树的结点总数为2n-1
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(log2n)。
C.在最坏情况下,利用插入操作构造一颗二叉排序树花费的代价为O(log2n)。
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; }