Search
Write a publication
Pull to refresh

Comments 26

Один только вопрос к тегам b-tree != Binary tree. Бинарное дерево это когда у любого элемента строго не более 2х дочерних, а семейство B деревьев сильно ветвистые. Ну и сверху ещё много отличий

Сократил так, binary в b. Не сильно в терминологию углублялся, исправлю.

контейнер с нужными свойствами есть например в GNU PBDS
gcc.gnu.org/onlinedocs/libstdc++/ext/pb_ds

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

Это делалось не под конкретную задачу, а от нечего делать. За последние лет 8 я только один раз стэк писал для работы)

У вас получилось что-то очень похожее на «Декартово дерево по неявному ключу».
С чем-то подобным я публиковал сообщение 25.05.2015 на
www.cyberforum.ru/ms-access/thread60797-page3.html
У Вас это «вес», у меня «уровень». Конечно сейчас я уже пользуюсь схемой без связи по
уровню, но главная проблема — это когда данные меняются, и необходимо вставлять
в элемент разветвленного дерева, которой ближе к корню, элемент большего веса. Увеличивать вес этого элемента и всех родителей-не выход, потому как может оказаться,
что предлагают заглотить «папу».
это когда данные меняются, и необходимо вставлять
в элемент разветвленного дерева, которой ближе к корню, элемент большего веса

Не очень понял, что здесь имеется ввиду. Вставка поддерева?
Я имею ввиду, что структуру данных по некой заданной теме должен определять не программист, а пользователь. Поэтому делим данные на 2 типа: Элементы(вес 0) и Сборки (вес > 0). Типа: страница (Элемент вес 0) — Книга (Сборка вес 1), а книги на полках и т.д.Но если некий роман написан в 3х томах (вес романа=2), нужно следить чтобы Польз. не поместил книжную полку, где размещается этот роман ( ее вес=3) в качестве еще главы упомянутого романа. Т.е. в некоторой степени база должна быть готова к решению еще не возникших задач (автор еще и не думает писать 2ю главу). Да, вставка поддерева.

Ни разу не похоже на декартово дерево

Я не смотрел как именно автор делает балансировку, и не утверждаю что это декартово дерево. Но прелдагаю вам почитать про структуру данных полное имя которой я привел.
Декартово дерево по неявному ключу
Идея как раз в том, чтобы хранить вспомогательную величину, которую автор называет «вес», и на ее основе получать порядковый номер элемента. Использовать декартово дерево оказывается удобно для балансировки и поддержания инварианта весов.
Заметим, что фактически в данном случае ключ для какой-то вершины — это количество вершин, меньших неё.

Красивая формулировка, как раз так вот и сделал.

Ясно, как теперь быстро вычислять для текущей вершины её неявный ключ. Поскольку во всех операциях мы приходим в какую-либо вершину, спускаясь по дереву, мы можем просто накапливать эту сумму, передавая её функции. Если мы идём в левое поддерево — накапливаемая сумма не меняется, а если идём в правое — увеличивается на cnt(t->l)+1.

Все умное до меня уже было написано )
А зачем в функции bntree::balance сделан обмен данными между узлами, при помощи копирования через this->tmb_data? В дереве не должно быть таких операций.
Помню что по быстрому накидал как самый простой вариант. На тот момент в указателях что ли запутался, и ссылку на родителя не хранил еще. Надо переделать.

У меня какое-то дежавю.
https://habr.com/ru/post/479142/
Повторю свой комментарий оттуда — чем ваша идея отличается от дерева порядковой статистики, которое давным-давно описано в Кормене?

Почитал Кормена. Идея ни чем, но мое дерево не красно-черное.


От соседнего поста отличается реализацией. У меня нет доп. поля:


  • Для всех вершин, которые на одну правее вышеупомянутых, увеличить add на 1

Когда искал как такое реализовать, не нашел подходящей структуры. И это статьи то же не было.

Если у вас не сбалансированное ДДП, то тогда и сложности операций у вас будут в худшем случае линейные (в среднем все равно логарифмические).

При удалении тоже надо балансировать, иначе можно поудалять листья таким образом, что дерево будет иметь линейную высоту.
Кроме того, попробуйте вставить в ваше дерево последовательно числа от 1 до 1000 — если я правильно понял ваш код, то высота в вашем дереве будет в районе 250 вместо ожидаемой 10-20

Ок, если сервер с виртуалками на работе на НГ не выключили, то гляну.

Проверил, балансирует как надо.


При удалении тоже надо балансировать

Я бы поспорил, на счет необходимости. Список мы конечно можем получить таким образом (если заполним дерево и будем только удалять), но при 1-ой же вставке дерево отбалансируется.

Насчет проверки моего примера — согласен, я ошибся, и думал, что балансируется по весу, а не по высоте на его основе. Меня не покидало ощущение, что что-то не так: вроде у вас похожее с АВЛ-деревом условие (высоты левого и правого деревьев отличаются не более чем на единицу), но при этом у вас только 1 поворот на операцию, а в АВЛ их может быть два.
Вот пример: {8, 4, 30, 2, 6, 10, 36, 9, 12,38, 13, 14, 15 };
https://ideone.com/recc7a
При его последовательной вставке в ваше дерево получится справа высота два, слева — 5. Явно нарушается ваш предполагаемый инвариант про баланс высот. Хотелось бы иметь формальное доказательство, что у вас там действительно логарифмическая высота — не факт, что найденый мой пример делает самый худший дизбаланс, наверняка можно похуже найти.


Насчет удаления — не согласен. У вас же после 1 поворота идет выход из цикла, значит при вставке отбалансируется только самый нижний кусочек.

получится справа высота два, слева — 5

Да. Переделал, на полный проход балансировки после вставки:


p = child;
//break;

Попозже почитаю как в 2-ва поворота на балансировке делать.

Такая структура хорошо подходит для хранения и обновления рейтингов по какому-либо параметру.

А чем вам не понравился std::map?

Уже есть insert()

Если нужен доступ по номеру, то «std::map::begin() + k»

А имея итератор на позиции уже можно применить erase() или extract()

Везде все тот же log(N). Зачем заново изобретать велосипед?
Sign up to leave a comment.

Articles