Реализация двоичной кучи методом динамических структур C++
Есть задание по реализации двоичной кучи через динамические структуры (не классы, никакого ООП). Я примерно понимаю алгоритм и код для случая, когда двоичная куча является по сути своей массивом, но никак не могу додуматься до моего случая. В хэдере я создал две структуры:
struct hNode
{
//UPD (22.05.2022 17.35):
int index;
double value;
hNode* parent = nullptr;
hNode* left_child = nullptr;
hNode* right_child = nullptr;
};
struct heap
{
int size = 0;
hNode* root = nullptr;
};
Было решено разделить процесс заполнения кучи значениями и её упорядочивание в две разные функции, но не одну из этих функций я так реализовать и не смог. Самая главная для меня проблема - понять, в какой момент алгоритм должен стать рекурсивным. Все, что я успел наработать, так это:
void addItem(heap* heap, double value, int ind)
{
if (heap->root == nullptr)
{
auto node = new hNode();
node->value = value;
node->index = 0;
heap->root = node;
ind++;
}
else
{
while (ind <= heap->size-1)
{
}
}
}
void heapifyMax(heap* heap)
{
}
Буду благодарен любой помощи: готовому коду, описанию алгоритма, ссылке на любую литературу или похожий тред.
Ответы (1 шт):
Как вариант для добавления элемента в дерево:
- хранить в структуре кучи указатель на последний родительский элемент, у которого заполнены не все потомки
- хранить в структуре кучи количество элементов
- раз уж Вы решили хранить индекс узла, то можете запоминать индекс узла у которого заполнены не все потомки
- хранить номер уровня и номер узла на уровне, у которого заполнены не все потомки. Но это вариация предыдущего пункта, т.к. легко вычисляется
В любом случае, есть формулы, по которым вычисляется индекс потомка, по ним же можно вычислить индекс предка.
Остался один вопрос - зачем??? Ведь весь смысл кучи в том, что в памяти её проще всего хранить в массиве, ведь оно полное, пока не заполнен уровень, элементы на следующий уровень не добавляются. В вашем варианте происходит перерасход памяти на хранение кучи, перерасход процессорного времени на операции с узлами (добавление, поиск, удаление, упорядочивание и т.д.)
Все структуры данных делаются для того, чтобы оптимизировать ресурсы. Например массив - самый оптимальный по расходу памяти, дерево - очень быстрый поиск, список - быстрая вставка элементов в любое место и т.д. Зачем реализовывать хранение кучи в памяти через дерево, если оптимальнее всего хранить её в виде массива?