文章目录
一、题目
将一系列给定数字顺序插入一个初始为空的小顶堆H[]。随后判断一系列相关命题是否为真。命题分下列几种:
- x is the root:x是根结点;
- x and y are siblings:x和y是兄弟结点;
- x is the parent of y:x是y的父结点;
- x is a child of y:x是y的一个子结点。
输入格式:
每组测试第1行包含2个正整数N(≤ 1000)和M(≤ 20),分别是插入元素的个数、以及需要判断的命题数。下一行给出区间[−10000,10000]内的N个要被插入一个初始为空的小顶堆的整数。之后M行,每行给出一个命题。题目保证命题中的结点键值都是存在的。
输出格式:
对输入的每个命题,如果其为真,则在一行中输出T,否则输出F。
输入样例:
5 4
46 23 26 24 10
24 is the root
26 and 23 are siblings
46 is the parent of 23
23 is a child of 10
输出样例:
F
T
F
T
二、方法1
1、思路
本题考察的是对堆的认识。
(1)知识点
① 完全二叉树
若设二叉树的深度为 h ,除第 h 层外,其它各层 (1 ~ h - 1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
例如:
一棵二叉树至多只有最下面的一层上的结点的度数可以小于2,并且最下层上的结点都集中在该层最左边的若干位置上,而在最后一层上,右边的若干结点缺失的二叉树,则此二叉树成为完全二叉树。
② 小顶堆和大顶堆
堆是一棵完全二叉树,其任何一非叶节点满足性质:
任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。
- 小顶堆:堆顶的关键字是所有关键字中最小的
- 大顶堆:堆顶的关键字是所有关键字中最大的
③ 堆的简单性质
堆的最大特点就是可以用数组来表示,不需要用指针来建立二叉树。
用数组来表示堆,只需要弄清楚三个问题:
- 给定一个父亲的下标 x,能知道其左右孩子的下标;
- 给定一个左孩子的下标 x,能知道其父亲和右兄弟的下标;
- 给定一个右孩子的下标 x,能知道其左兄弟和父亲的下标。
通过数学证明,得出一个优美的论断:
- 已知孩子的下标 x,其父亲的下标为 ( x - 1)// 2;
- 已知父亲的下标 x,其左右孩子的下标分别为
( x + 1)* 2 - 1 ,( x + 1)* 2;
④ 创建堆
void creat(int x)
{
heap[++cnt] = x;
int t = cnt;
while (t > 1 && heap[t] < heap[t / 2])
{
heap[t] = heap[t / 2];
heap[t / 2] = x;