example2_custom_iterator_binary_tree.cpp

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <iostream>
#include <stack>
#include <iterator>

template<typename T>
class BinaryTree {
private:
    struct Node {
        T data;
        Node* left;
        Node* right;
        Node(const T& val) : data(val), left(nullptr), right(nullptr) {}
    };

    Node* root;

public:
    BinaryTree() : root(nullptr) {}

    void insert(const T& value) {
        root = insertRec(root, value);
    }

    class Iterator {
    private:
        std::stack<Node*> stack;

        void pushLeft(Node* node) {
            while (node) {
                stack.push(node);
                node = node->left;
            }
        }

    public:
        using iterator_category = std::forward_iterator_tag;
        using value_type = T;
        using difference_type = std::ptrdiff_t;
        using pointer = T*;
        using reference = T&;

        Iterator(Node* root) {
            pushLeft(root);
        }

        Iterator& operator++() {
            Node* node = stack.top();
            stack.pop();
            pushLeft(node->right);
            return *this;
        }

        Iterator operator++(int) {
            Iterator tmp = *this;
            ++(*this);
            return tmp;
        }

        bool operator==(const Iterator& other) const {
            return (stack.empty() && other.stack.empty()) ||
                   (!stack.empty() && !other.stack.empty() && stack.top() == other.stack.top());
        }

        bool operator!=(const Iterator& other) const {
            return !(*this == other);
        }

        T& operator*() {
            return stack.top()->data;
        }
    };

    Iterator begin() {
        return Iterator(root);
    }

    Iterator end() {
        return Iterator(nullptr);
    }

private:
    Node* insertRec(Node* node, const T& value) {
        if (node == nullptr) {
            return new Node(value);
        }
        if (value < node->data) {
            node->left = insertRec(node->left, value);
        } else if (value > node->data) {
            node->right = insertRec(node->right, value);
        }
        return node;
    }
};

int main() {
    BinaryTree<int> tree;
    tree.insert(5);
    tree.insert(3);
    tree.insert(7);
    tree.insert(1);
    tree.insert(9);

    std::cout << "In-order traversal: ";
    for (const auto& value : tree) {
        std::cout << value << " ";
    }
    std::cout << std::endl;

    // Using the iterator with STL algorithms
    auto minElement = std::min_element(tree.begin(), tree.end());
    auto maxElement = std::max_element(tree.begin(), tree.end());

    std::cout << "Min element: " << *minElement << std::endl;
    std::cout << "Max element: " << *maxElement << std::endl;

    return 0;
}
Back to iterators