Как работает итератор в дереве?

319
06 сентября 2018, 18:20

Хочу написать итератор для самописного дерева (авл), но не могу понять как должен вести себя итератор во время инкременирования? Тоесть, в зависимости от положения элеманта, на который указывает итератор (нахождение в правой или левой ветке) он должен поступать по разному. К тому же он должен иметь возможность подниматься вверх по дереву, но узлы указывают только на потомков, а не на родителей. Нужно дописывать в каждый узел указатель на потомка? Как подобная задача решена в stl?

Answer 1

Не знаю как написаны итераторы для стандартных контейнеров, но чтобы выразить свое мнение, написал незаконченный и недоработанный класс дерева со своим итератором:

template <class T>
class Tree {
    struct Node {
        T data;
        Node *parent;
        Node *left;
        Node *right;
        Node(const T& t) :
            data(t), left(0), right(0), parent(0) {}
    };
    Node  *current;
    std::less<int> cmp;
public:
    Tree(const T& t = T()) : current(new Node(t)) {}
    ~Tree();
    Tree(const Tree &);
    Tree& operator =(const Tree&);
    using Itcat = std::bidirectional_iterator_tag;
    void insert(const T&);
   // ищем в ветке, с конкретным корнем, предыдущий  элемент по компаратору
    Node* next_element(Node*);
    // указатель  на следующий элемент  по компаратору
    Node* prev_element(Node*);
    struct iterator : public std::iterator<Itcat,Tree<T>::Node>
    {
        using It = std::iterator<Itcat,Tree<T>::Node>;
        using reference = typename std::iterator_traits<It>::reference;
        Node* cur;
        iterator(Node* p = nullptr) : cur(p) {}
        reference operator *() { return *cur;  }
        // если, допустим вы хотите, чтобы после ++ итератор указывал на
        // следующий элемент по возрастанию, что вполне естественно
        // для копаратора less<T>
        iterator& operator ++() {
            // current должен указывать на предыдущий элемент по компаратору
            //для нашего  копаратора
            if(cur->right)
              cur = next_element(cur->right);
            else {
              cur = next_element(cur->parent);
            }
            return *this;
        }
        iterator& operator --() {
            if(cur->left)
                cur = prev_element(cur->left);
            return *this;
        }
    };
};

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

READ ALSO
Как выделить память для массива функций

Как выделить память для массива функций

Вот так ругается компиляторКак можно реализовать такой динамический массив?

270
Хранение множества продуктов

Хранение множества продуктов

У меня есть база данных и 3 таблицы: ProductEntity, OrderEntity и ProductInOrder

223
Как настроить в .properties log4j путь к логам внутри проекта?

Как настроить в .properties log4j путь к логам внутри проекта?

Друзья, здравствуйте, Подскажите как настроить вproperties log4j путь к логам внутри проекта? То есть что бы после пула с гита путь был всегда октуален

303
Воспроизведение midi в java

Воспроизведение midi в java

Я использую библиотеку JMusic для редактора MIDI (и AU) файлов:http://explodingartcom/jmusic/index

284