Как сделать дерево на C++?

Как создать древовидную структуру данных на C++, в которой используются итераторы вместо указателей? Я не нашел в STL ничего, что могло бы это сделать. Я бы хотел иметь возможность создавать деревья и управлять ими следующим образом:

#include <iostream>
#include <tree>
using namespace std;

int main()
{
    tree<int> myTree;

    tree<int>::iterator i = myTree.root();
    *i = 42;

    tree<int>::iterator j = i.add_child();
    *j = 777;
    j = j.parent();

    if (i == myTree.root() && i == j) cout << "i and j are both pointing to the root\n";

    return 0;
}

Спасибо, tree.hh кажется именно тем, что я искал.

If this is for gaining the benefit of a data-structure holding arbitrary index types, optimized for searching and good at insertion then consider using a map.

A map is an associative container that has performance guarantees identical to those of a tree: logarithmic searching, logarithmic insertion, logarithmic deletion, linear space. Internally they are often implemented as red-black trees, although that is not a guarantee. Still, as an STL user all you should care about is the performance guarantees of the STL algorithms and data-structures. Whether they're implemented as trees or little green men shouldn't matter to you.

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

Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
6
0
16 760
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Карта - это ассоциативный контейнер, который имеет гарантии производительности, идентичные таковым у дерева: логарифмический поиск, логарифмическая вставка, логарифмическое удаление, линейное пространство. Внутри они часто реализуются как красно-черные деревья, хотя это не гарантия. Тем не менее, как пользователь STL, все, о чем вы должны заботиться, - это гарантии производительности алгоритмов STL и структур данных. Неважно, реализованы ли они в виде деревьев или маленьких зеленых человечков.

Кстати, не существует такой вещи, как функция root (). Все контейнеры STL имеют функцию begin (), реализующую концептуальное начало контейнера. Тип итератора, возвращаемого этой функцией, зависит от характеристик контейнера.

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

Вот tree.hh, который немного близок к тому, что вы хотите сделать, хотя и немного разные.

Вот фрагмент кода, извлеченный с его веб-сайта.

int main(int, char **)
   {
   tree<string> tr;
   tree<string>::iterator top, one, two, loc, banana;

   top=tr.begin();
   one=tr.insert(top, "one");
   two=tr.append_child(one, "two");
   tr.append_child(two, "apple");
   banana=tr.append_child(two, "banana");
   tr.append_child(banana,"cherry");
   tr.append_child(two, "peach");
   tr.append_child(one,"three");

   loc=find(tr.begin(), tr.end(), "two");
   if (loc!=tr.end()) {
      tree<string>::sibling_iterator sib=tr.begin(loc);
      while(sib!=tr.end(loc)) {
         cout << (*sib) << endl;
         ++sib;
         }
      cout << endl;
      tree<string>::iterator sib2=tr.begin(loc);
      tree<string>::iterator end2=tr.end(loc);
      while(sib2!=end2) {
         for(int i=0; i<tr.depth(sib2)-2; ++i) 
            cout << " ";
         cout << (*sib2) << endl;
         ++sib2;
         }
      }
   }

Что изменилось? Ваша реализация проще, когда дело доходит до добавить узел к дереву. Хотя ваша версия indiscutably проще, Дев из этой библиотеки, вероятно, хотел бы иметь некоторую информацию, доступную без просмотра дерева, таких как размер дерева, например.

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

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