- 对于一个有N个结点、K条边的森林,不能确定它共有几棵树。
False
每多一棵树,结点数就会比边数多一,所有N-K就是树的棵数。
- 树的后根序遍历序列等同于它所对应二叉树的中序遍历序列。
True
树的后根序遍历序列等同于它所对应二叉树的中序遍历序列,树的先根序遍历序列等同于它所对应二叉树的先序遍历序列;
- 高度为h(h>0)的完全二叉树对应的森林所含的树的个数一定是h。
False
二叉树转换成森林中树的个数, 与该树根节点一直往右遍历, 到叶子节点的节点数相同。h高的完全二叉树, 最右可能有h或者h-1个节点,但是对于h高的满二叉树,最有一定是h个节点,所以对应的森林一定有h棵树。
- 任何最小堆中从根结点到任一叶结点路径上的所有结点是有序的(从小到大)。
True
- 在有N个元素的最大堆中,随机访问任意键值的操作可以在O(logN)时间完成。
False
堆排序最坏 nlog2(n),堆的左右孩子没有固定的顺序,无法像平衡二叉树那样顺着找下去。
- 最大堆(大顶堆、max-heap)的前序遍历结果是从大到小排列的。
False
和二叉搜索树区分开
- For binary heaps with N elements, the BuildHeap function (which adjust an array of elements into a heap in linear time) does at most N−log(N+1) comparisons between elements.
False
- 将森林转换为对应的二叉树,若在二叉树中,结点u是结点v的父结点的父结点,则在原来的森林中,u和v可能具有的关系是:
1.父子关系; 2. 兄弟关系; 3. u的父结点与v的父结点是兄弟关系
A.只有2
B.1和2
C.1和3
D.1、2和3
选B 画图即可
- 设森林F中有三棵树,第一、第二、第三棵树的结点个数分别为M1,M2和M3。则与森林F对应的二叉树根结点的右子树上的结点个数是:
A.M1
B.M1+M2
C.M2+M3
D.M3
选C 除了第一棵树,其余的树(所有的结点)都在二叉树根结点的右子树上
- 已知森林 F 及与之对应的二叉树 T,若 F 的先根遍历序列是 a, b, c, d, e, f,后根遍历序列是 b, a, d, f, e, c,则 T 的后序遍历序列是:
A.b, a, d, f, e, c
B.b, d, f, e, c, a
C.b, f, e, d, c, a
D.f, e, d, c, b, a
选C 先根遍历序列为T的先序遍历序列,后根遍历序列为T的中序遍历序列。根据这两个序列即可画出树,从而求出后序遍历序列。
- 堆的形状是一棵:
A.二叉搜索树
B.满二叉树
C.非二叉树
D.完全二叉树
选D
- 将10、12、1、14、6、5、8、15、3、9、7逐个按顺序插入到初始为空的最小堆(小根堆)中,然后连续执行两次删除最小元素操作(DeleteMin),此后堆顶的元素是什么?
A.5
B.6
C.7
D.9
选A 最小堆的堆顶元素一定是最小值,两次删除最小元素将1、3删除后,5就是最小元素
- 将d叉树堆存储在数组中。则对任意下标为i的单元,其父结点、第一个孩子结点、最后一个孩子结点的下标为:
A.⌈(i+d−2)/d⌉、(i−2)d+2、(i−1)d+1
B.⌈(i+d−1)/d⌉、(i−2)d+1、(i−1)d
C.⌊(i+d−2)/d⌋、(i−1)d+2、i * d+1
D.⌊(i+d−1)/d⌋、(i−1)d+1、i * d
选C 这里的除是取整的
- 设最小堆(小根堆)的层序遍历结果为{5, 18, 15, 28, 22, 42, 40}。用线性时间复杂度的算法将该堆调整为最大堆(大根堆),则该树的中序遍历结果为:
A.18, 28, 22, 15, 40, 5, 42
B.18, 28, 22, 42, 15, 40, 5
C.5, 22, 18, 42, 15, 40, 28
D.22, 5, 18, 42, 40, 15, 28
选B 从倒数第二层开始,逐层调整
- 在有n(>1)个元素的最大堆(大根堆)中,最小元的数组下标可以是:
A.1
B.⌊n/2⌋−1
C.⌊n/2⌋+2
D.⌊n/2⌋
选D “可以是”,画图验证即可
- 在一个有2333个元素的最小堆中,下列哪个下标不可能是最大元的位置?
A.1116
B.1167
C.2047
D.2232
选A 最小堆的最大元或者最大堆的最小元都只能出现在叶子结点上,且考虑到堆是一个完全二叉树的结构特性,故2333个元素,最后一层有2333-1024-1023=286个叶子结点,这286个叶子结点来自于上一层的前143个父结点,即从倒数第二层的第144个(堆的1167个)结点开始的结点都是叶子结点,也就是说最大元可能出现在1167~2333的任一结点上。
- 下列关于大根堆(至少含 2 个元素)的叙述中,正确的是:
(I). 可以将堆看成一棵完全二叉树
(II). 可以采用顺序存储方式保存堆
(III). 可以将堆看成一棵二叉排序树
(IV). 堆中的次大值一定在根的下一层
A.仅 I、II
B.仅 II、III
C.仅 I、II、IV
D.仅 I、III、IV
选C
(编程题)
- Percolate Up and Down
Write the routines to do a “percolate up” and a “percolate down” in a binary min-heap.
Format of functions:
void PercolateUp( int p, PriorityQueue H );
void PercolateDown( int p, PriorityQueue H );
where int p is the position of the element, and PriorityQueue is defined as the following:
typedef struct HeapStruct *PriorityQueue;
struct HeapStruct {
ElementType *Elements;
int Capacity;
int Size;
};
Sample program of judge:
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
#define MinData -1
typedef struct HeapStruct *PriorityQueue;
struct HeapStruct {
ElementType *Elements;
int Capacity;
int Size;
};
PriorityQueue Initialize( int MaxElements ); /* details omitted */
void PercolateUp( int p, PriorityQueue H );
void PercolateDown( int p, PriorityQueue H );
void Insert( ElementType X, PriorityQueue H )
{
int p = ++H->Size;
H->Elements[p] = X;
PercolateUp( p, H );
}
ElementType DeleteMin( PriorityQueue H )
{
ElementType MinElement;
MinElement = H->Elements[1];
H->Elements[1] = H->Elements[H->Size--];
PercolateDown( 1, H );
return MinElement;
}
int main()
{
int n, i, op, X;
PriorityQueue H;
scanf("%d", &n);
H = Initialize(n);
for ( i=0; i<n; i++ ) {
scanf("%d", &op);
switch( op ) {
case 1:
scanf("%d", &X);
Insert(X, H);
break;
case 0:
printf("%d ", DeleteMin(H));
break;
}
}
printf("\nInside H:");
for ( i=1; i<=H->Size; i++ )
printf(" %d", H->Elements[i]);
return 0;
}
/* Your function will be put here */
Sample Input:
9
1 10
1 5
1 2
0
1 9
1 1
1 4
0
0
Sample Output:
2 1 4
Inside H: 5 10 9
AC代码
void PercolateUp( int p, PriorityQueue H ){
ElementType element = H->Elements[p];
while (H->Elements[p / 2] > MinData) {
if (element < H->Elements[p / 2]) {
H->Elements[p] = H->Elements[p / 2];
p = p / 2;
}
else {
break;
}
}
H->Elements[p] = element;
}
void PercolateDown( int p, PriorityQueue H ){
ElementType element = H->Elements[p];
while (p * 2 <= H->Size) {
if (H->Elements[p * 2] < element) {
H->Elements[p] = H->Elements[p * 2];
p = p * 2;
}
else {
break;
}
}
H->Elements[p] = element;
}
- 小字辈
本题给定一个庞大家族的家谱,要请你给出最小一辈的名单。
输入格式:
输入在第一行给出家族人口总数 N(不超过 100 000 的正整数) —— 简单起见,我们把家族成员从 1 到 N 编号。随后第二行给出 N 个编号,其中第 i 个编号对应第 i 位成员的父/母。家谱中辈分最高的老祖宗对应的父/母编号为 -1。一行中的数字间以空格分隔。
输出格式:
首先输出最小的辈分(老祖宗的辈分为 1,以下逐级递增)。然后在第二行按递增顺序输出辈分最小的成员的编号。编号间以一个空格分隔,行首尾不得有多余空格。
输入样例:
9
2 6 5 5 -1 5 6 4 7
输出样例:
4
1 9
AC代码
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<string.h>
using namespace std;
int f[100005];
int a[100005];
int find(int x)
{
if(a[x])return a[x];
if(f[x]==-1)return a[x]=1;
else return a[x]=find(f[x])+1;
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
f[i]=i;
for(int i=1;i<=n;i++)
{
cin>>f[i];
}
int max=0;
for(int i=1;i<=n;i++)
{
int temp;
temp=find(i);
if(temp>max)max=temp;
}
cout<<max<<endl;
int flag=1;
for(int i=1;i<=n;i++)
if(a[i]==max)
{
if(flag)
{
cout<<i;
flag=0;
}
else cout<<" "<<i;
}
cout<<endl;
return 0;
}