10821. Создание двоичного дерева поиска
Бинарное
дерево поиска является эффективной структурой данных для быстрого поиска. Все
элементы левого поддерева меньше значения корня, а элементы правого поддерева –
больше корня.
Ниже показаны деревья бинарного
поиска с 4 вершинами, которые получены в результате вставки элементов порядке,
приведенном под деревьями.
В задаче необходимо найти такой
порядок вставки чисел от 1 до n в бинарное дерево поиска, чтобы получилось дерево высоты не более h. Высота дерева
определяется рекурсивно:
1. Высота пустого дерева равна 0.
2. Высота дерева равна максимуму
высот его поддеревьев плюс 1.
Полученный порядок должен быть
лексикографически наименьшим. Например, для n = 4, h = 3 следует вывести 1 3 2 4, а не 2 1
4 3 или 3 2 1 4.
Вход. Каждая
строка содержит два натуральных числа n и h (1 £ n £ 10000, 1 £ h £ 30). Последняя строка содержит n = h
= 0 и не
обрабатывается. Выходные данные содержат не более
30 тестов.
Выход. Для каждого теста вывести его
номер и порядок вершин, в котором они будут вставляться в бинарное дерево
поиска высоты не более h. Если такого дерева не существует, то вывести сообщение ‘Impossible.’.
4 3
4 1
6 3
0 0
Case 1: 1 3 2 4
Case 2:
Impossible.
Case 3: 3 1 2 5 4
6
рекурсия
Полное
бинарное дерево высоты h содержит 1 + 2 + 4 + … +
2h-1 = 2h - 1 вершин. Если n ³ 2h, то искомого дерева не
существует. Иначе будем строить такое дерево, в котором будет по максимуму
заполняться правое поддерево.
Пусть следует расположить в
дереве поиска высоты не более h числа от a
до b. Тогда в правом поддереве высоты
h – 1 следует расположить 2h-1
– 1 элементов, а число d
= b – 2h-1
+ 1 следует расположить в корне. Числа от a до d – 1 располагаем в левом поддереве. Если d < a,
то в левом поддереве
чисел не будет и в таком случае положим d = a.
Пример.
Рассмотрим второй пример, где n = 6, h
= 3. Дерево высоты 3
может содержать до 23 – 1 = 7
вершин. В корне дерева расположим число d = 6 – (22 – 1) = 3. Рекурсивно вставляем числа от 1 до 2 в левое поддерево и
числа от 4 до 6 в правое. Получим последовательность 3
1 2 5 4 6.
void find(int
a, int b, int
h)
{
int d = b -
(1 << (h-1)) + 1;
if (a > b)
return;
if (d < a)
d = a;
printf(" %d",d);
find(a,d-1,h-1);
find(d+1,b,h-1);
}
Последовательно читаем входные значения n и h, печатаем номер
теста. Проверяем, существует ли искомое дерево: выводим ‘Impossible.’, если n
³ 2h. Иначе выводим искомую последовательность вершин,
вызвав функцию find(1, n, h).
while(scanf("%d %d",&n,&h), n+h)
{
printf("Case
%d:",cs++);
if (n >=
1 << h) printf(" Impossible.");
else
find(1,n,h);
printf("\n");
}