Есть ли эффективные способы создания сбалансированной древовидной структуры

У меня есть сбалансированная бинарная древовидная структура:

Узел 0 на глубине 0 является корнем. Левый дочерний элемент корня - это 1, правый дочерний элемент - это 2, и так далее.

См. Изображение: Есть ли эффективные способы создания сбалансированной древовидной структуры

Общая глубина дерева определяется как N. Этот N - единственный параметр проблемы. Узлы на уровне N обозначаются как конечные узлы.

Я сохраняю это дерево, используя следующую структуру узлов.

struct node_s{
    int n, depth, parent;//n is node number
    int nodescendents;//number of descendents of the current node
    std::vector<int> descendents;//Descendents in ascending order
    int lchild, rchild;//Immediate left child and right child
    std::vector<int> lchildleaves;//leaf nodes that descend from the immediate 
                                                      //left child
    std::vector<int> rchildleaves;//leaf nodes that descend from the immediate 
                                                      //right child
};

Я собираюсь хранить само дерево как:

std::vector<node_s> tree;

Есть ли способ численно эффективно заполнить вектор tree, используя простую алгебру примерно так:

//Creating the nth node, beginning from 0th node, then 1st node and so on
nodes_s node;
//populate all data structures of the nth node
//precisely, here, there are loops, algebraic calculations, etc., that can help 
//populate all of the node_s data members.
tree.push_back(node);

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

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

Damien 17.11.2018 10:25

Я согласен, что будет повторение. Пространство вряд ли пока будет ограничением.

Tryer 17.11.2018 10:27

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

Damien 17.11.2018 11:09
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
140
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Для узла k его ранг r [k] равен floor (log2 (k + 1)), а его позиция в ранге равна p [k] = k - 2 ^ r [k] + 1.

Тогда k располагается парой (r [k], p [k])

Наоборот, k = 2 ^ r [k] + p [k] - 1.

Его родительский элемент затем расположен по (r [k] -1, floor (p [k] / 2)) -> node index = 2 ^ r + p - 1

k - левый потомок, если k% 2 == 1

Думаю, остальное довольно легко

то есть ранг (k) = потолок (бревенчатое основание 2 из (k + 1))? Тогда, возможно, несколько узлов будут сопоставлены с одним и тем же рангом. Ранг - это то же самое, что и глубина?

Tryer 17.11.2018 11:59

@Tryer Вы правы в том, что я назвал рангом, он соответствует глубине дерева. Я использовал эту терминологию целую вечность, и ее трудно изменить. Что касается расчета, я предположил неявное преобразование в целое число rank. Узлы одного ранга (глубины) различаются положением pk в ранге. Это способ просто найти родительскую позицию, но могут быть и другие

Damien 17.11.2018 12:09

Я думаю, вы можете отредактировать свой ответ как r [k] = floor (log base 2 [k + 1]). Тогда его позиция будет p [k] = k - 2 ^ r [k] + 1. Тогда родитель будет (r [k] -1, floor (p [k] / 2)).

Tryer 17.11.2018 12:20

@Tryer Спасибо за исправление в вычислении "k". Я предполагал, что пол (.) Был неявным, но добавить его не проблема. Редактировать готово

Damien 17.11.2018 12:36

@Tryer log2(.) - это C++!

Damien 17.11.2018 12:44

Другие вопросы по теме