树和森林,堆

  1. 对于一个有N个结点、K条边的森林,不能确定它共有几棵树。
    False
    每多一棵树,结点数就会比边数多一,所有N-K就是树的棵数。

  1. 树的后根序遍历序列等同于它所对应二叉树的中序遍历序列。
    True
    树的后根序遍历序列等同于它所对应二叉树的中序遍历序列,树的先根序遍历序列等同于它所对应二叉树的先序遍历序列

  1. 高度为h(h>0)的完全二叉树对应的森林所含的树的个数一定是h。
    False
    二叉树转换成森林中树的个数, 与该树根节点一直往右遍历, 到叶子节点的节点数相同。h高的完全二叉树, 最右可能有h或者h-1个节点,但是对于h高的满二叉树,最有一定是h个节点,所以对应的森林一定有h棵树。

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

  1. 在有N个元素的最大堆中,随机访问任意键值的操作可以在O(logN)时间完成。
    False
    堆排序最坏 nlog2(n),堆的左右孩子没有固定的顺序,无法像平衡二叉树那样顺着找下去。

  1. 最大堆(大顶堆、max-heap)的前序遍历结果是从大到小排列的。
    False
    和二叉搜索树区分开

  1. 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

  1. 将森林转换为对应的二叉树,若在二叉树中,结点u是结点v的父结点的父结点,则在原来的森林中,u和v可能具有的关系是:
    1.父子关系; 2. 兄弟关系; 3. u的父结点与v的父结点是兄弟关系
    A.只有2
    B.1和2
    C.1和3
    D.1、2和3
    选B 画图即可

  1. 设森林F中有三棵树,第一、第二、第三棵树的结点个数分别为M1,M2和M3。则与森林F对应的二叉树根结点的右子树上的结点个数是:
    A.M1
    ​B.M1+M2
    ​C.M2+M3
    ​D.M3
    选C 除了第一棵树,其余的树(所有的结点)都在二叉树根结点的右子树上

  1. 已知森林 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的中序遍历序列。根据这两个序列即可画出树,从而求出后序遍历序列。

  1. 堆的形状是一棵:
    A.二叉搜索树
    B.满二叉树
    C.非二叉树
    D.完全二叉树
    选D

  1. 将10、12、1、14、6、5、8、15、3、9、7逐个按顺序插入到初始为空的最小堆(小根堆)中,然后连续执行两次删除最小元素操作(DeleteMin),此后堆顶的元素是什么?
    A.5
    B.6
    C.7
    D.9
    选A 最小堆的堆顶元素一定是最小值,两次删除最小元素将1、3删除后,5就是最小元素

  1. 将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 这里的除是取整的

  1. 设最小堆(小根堆)的层序遍历结果为{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 从倒数第二层开始,逐层调整

  1. 在有n(>1)个元素的最大堆(大根堆)中,最小元的数组下标可以是:
    A.1
    B.⌊n/2⌋−1
    C.⌊n/2⌋+2
    D.⌊n/2⌋
    选D “可以是”,画图验证即可

  1. 在一个有2333个元素的最小堆中,下列哪个下标不可能是最大元的位置?
    A.1116
    B.1167
    C.2047
    D.2232
    选A 最小堆的最大元或者最大堆的最小元都只能出现在叶子结点上,且考虑到堆是一个完全二叉树的结构特性,故2333个元素,最后一层有2333-1024-1023=286个叶子结点,这286个叶子结点来自于上一层的前143个父结点,即从倒数第二层的第144个(堆的1167个)结点开始的结点都是叶子结点,也就是说最大元可能出现在1167~2333的任一结点上。

  1. 下列关于大根堆(至少含 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值