Timus 2002 by Tolia

Для решения использовалось AVL-дерево выложенное тут.

Алгоритм решения задачи с соответствием с условием задачи.

 

Ссылка на решение.

Частотный словарь

Определение понятия «частотный словарь» можно посмотреть в Википедии.

Реализовывалось на своем АВЛ-дереве.

Сначала надо распарсить строку на слова, которые удовлетворяют условию задачи 1. Потому, надо с помощью структуры данных как map реализовать дерево, поддерживающее ключ -> значение структуру. АВЛ-дерево в каком-то роде схоже с map, так что можно использовать его. Правда оно не имплемирует ни одного интерфейса, которые имплемирует map. Разбив текст на слова и добавив их в дерево с количеством их вхождений мы можем вывести частоту каждого из них. Для хранения общего количества слов используется переменная внутри словаря. Библиотека имеет один метод для получения результата — это по заданному слову выдать частоту его вхождения. Если необходимо вывести все слова в словаре, то тогда можно расширить класс АВЛ-дерева.

#include <iostream>
using namespace std;int main() {for( int i = 0; i < 10; i++ )
{
if( i % 2 == 0 )
{
cout << “Even” << endl;
}
else
{
cout << “Odd” << endl;
}
}
return 0;
}%EOF%

 

0 3 0.1111111111111111
10 1 0.037037037037037035
2 1 0.037037037037037035
Even 1 0.037037037037037035
Odd 1 0.037037037037037035
cout 2 0.07407407407407407
else 1 0.037037037037037035
endl 2 0.07407407407407407
for 1 0.037037037037037035
i 4 0.14814814814814814
if 1 0.037037037037037035
include 1 0.037037037037037035
int 2 0.07407407407407407
iostream 1 0.037037037037037035
main 1 0.037037037037037035
namespace 1 0.037037037037037035
return 1 0.037037037037037035
std 1 0.037037037037037035
using 1 0.037037037037037035
aaa for bbb aaa for if
%EOF%
aaa 2 0.3333333333333333
bbb 1 0.16666666666666666
for 2 0.3333333333333333
if 1 0.16666666666666666

 

Ссылка на ideone.

Обратная польская запись

Что такое обратная польская запись можно прочитать в Википедии.

Использовался свой стек, выложенный ранее тут.

Поскольку не было необходимости реализовывать дополнительные функции, то то я обошелся для хранения переменных одним стеком и одной строкой, в отличии от реализации моей коллеги.

Лексемы по сути те же самые, только нет ни слова про функции. Для вычисления строки была сложность в нахождении «числовых значений». Для это бралась подстрока данной строки от начала числа до пробела после него.

 

 

Ссылка на ideone.

Стек v.Java

        Stack test = new Stack(4);
        System.out.println(test.isEmpty());
        test.push(12);
        System.out.println(test.isEmpty());
        System.out.println(test.peek());
        test.push(13);
        test.push(14);
        test.push(15);
        test.push(16);
        test.push(17);
        test.push(‘(‘);
        System.out.println(test.size());
        System.out.println(test.peek().equals(‘(‘));
        test.pop();
        System.out.println(test.peek());
        test.pop();
        System.out.println(test.peek());
        test.pop();
        System.out.println(test.peek());
        test.pop();
        System.out.println(test.peek());
        test.pop();
        System.out.println(test.peek());
        System.out.println(test.isEmpty());
        test.pop();
        System.out.println(test.peek());
        test.pop();
        System.out.println(test.isEmpty());
true

false

12

7

true

17

16

15

14

13

false

12

true

Что такое стек прекрасно расскажет Википедия.

Реализация динамического стека. Есть приватная функция resize, которая меняет размер массива, выделяемого под стек. Массив копируется в новый с помощью Java’вского копирования массивов.

Есть тестовый вывод, для проверки корректности всех методов.

Ссылка на ideone.

АВЛ-дерево

Описание АВЛ-дерева вы можете прочитать в Википедии.

Здесь представлен код реализации рекурсивного АВЛ-дерева. Отличается от обычно бинарного дерева тем, что у узлов есть высота и показатель балансировки. Балансировка может меняться при добавлении или удалении, и восстанавливается с помощью малого левого(правого), или большого левого(правого) поворотов. Как это выглядит можно увидеть в той же Википедии.

Показатель балансировки подсчитывается специальной функцией, как и показатель высоты.

Для возможности бегать по узлам дерева, есть приватные функция getHigherNode, getLowerNode. К которым есть доступ у узлов. К примеру мы в самой левой вершине дерева, либо мы лист, либо у нас есть правое поддерево. Если мы лист, то надо вернуть просто нашего предка. Если же есть правое поддерево. То надо вывести следующую вершину справа. Мы попали в эту вершину. Мы снова либо лист, либо есть правое поддерево, либо есть левое поддерево, либо сразу оба. Если мы лист, то нам надо подняться вверх по дереву, пока мы являемся правым сыном нашего предка, как только мы попадем в наш первоначальный самый маленький узел, мы перестаем быть правым сыном, значит нам пора остановиться, и вернуть отца самого маленького узла. Если же есть только правое поддерево(вернулись к моменту, где мы правый узел от самого маленького), то спускаемся снова вправо и имеем те же ситуации. Если же есть только левое поддерево, то заходим в него и действуем по тем же правилам. Если есть оба, то сначала пойдем в левое поддерево, после того, как мы там побываем и вернемся к узлу, нам надо будет продолжить обходить правое поддерево.

Попробуйте данный алгоритм действия, для этого дерева.

  • Определите следующий элемент для узла 0001.
  • Определите следующий элемент для узла 0003.
  • Определите следующий элемент для узла 0004.
  • Определите следующий элемент для узла 0005.
  • Определите следующий элемент для узла 0007, зная, что предок корня — это null.

Дерево

В коде присутствует поэтапный вывод дерева. Чтобы убедиться в корректности методов. Сначала вводятся так данные, чтобы сделать малый левый поворот. Потом так, чтобы сделать большой левый поворот и малый правый. После этого удаляются элементы так же, как и в бинарном дереве, только после удаление надо проверить показатель балансировки каждого из узлов, и если надо, то сбалансировать.

 

 

Ссылка на ideone.

BigSegmentedArray by Tolia

Мне предоставили реализовать класс, который наследует SegmentedArray и характеризуется следующим:

  • принимает большой массив
  • частые запросы get(), min();

Поскольку команда set задает значение на интервале, я решил сделать «дерево отрезков». Которое устроено как бинарное дерево относительно индекса (в задании большое количество запросов get(), следовательно будет быстрее искать элемент по индексу), имея в себе левый и правые концы интервала, а также значение на этом интервале.

Основная операция в данной структуре — set(). И она самая сложная по своей схеме. Когда приходить запрос на установление значения на интервале, надо проверить, возможно узел пуст, следовательно такого интервала еще не задавали, и тогда можно его создать. Если же узел не пуст, то надо проверить, в данном узле ли задается наш интервал, или же надо перейти к другому. Если же в данном узле надо задать интервал, то у нас вырисовывается три ситуации: когда задаваемый интервал не превосходит интервала узла, когда заданный интервал превосходить  интервал узла и когда одна точка заданного интервала лежит внутри интервала узла, а другая, вне его. В первом случаем, просто разбиваем внутренний интервал на три подинтервала: левая часть внутреннего интервала, заданный интервал и правая часть внутреннего интервала. Во-втором, необходимо увеличить границы внутреннего интервала до задаваемого, и удалить все интервалы(в левом и правом узлах), которые данный новый интервал перекрыл. В третьем необходимо разбить интервал узла на подинтервал до внутренней точки задаваемого интервала, и на то, что осталось. Потом удалить все интервала, которые мы перекрыли.

Untitled

Метод поиска значение по индексу осуществляется как и в бинарном дереве, пока не попадем на нужный нам интервал, или значение данного индекса еще не было установлено.

Метод нахождения минимума на подинтервала спускается по дереву, пока не попадет на нужный интервал, и потом проверяет значения на каждом из интервалов и выбирает минимальный.

Поскольку у нас дерево отсортировано по индексу, то искать индекс элемента по значению сложнее, необходимо пройти все интервалы от индекса, который нам дали в начале, пока не встретим искомое значение, или же выведем, что его нет.

Теоретическая оценка сложности методов:

  • get(i): O(log(count(set)));
  • set(x, y, val): O(log(count(set)));
  • indexof(val, index): O(count(set() — interval(index)));
  • min(x, y) : O(count(set()))
Ссылка на ideone.

 

Binary Tree Search

Код реализация Бинарного дерева на Java для задания из Word of Week. Саму идею дерева и теоретический алгоритм можно почитать в Википедии. Отличается от реализации на C++ тем, что в Java мы не обращаемся к адресам узлам явно, сравнение происходит через компаратор и сам класс при создании имеет свои особенности от C++. Для работы самого класса, в нем присутствуют приватные методы, которые работают рекурсивно, и geter’ы, позволяющие получать значение от работы приватных методов.

В тестовом выводе можно пронаблюдать(если вы запустите данный код) как выглядит дерево после добавления данных, потом как оно выглядит после удаления одного из узлов и далее убедиться в правильности дополнительных функций.

Ссылка на ideone.