Rumah >pembangunan bahagian belakang >C++ >Bagaimanakah Saya Boleh Mencipta Iterator Meratakan dalam C untuk Memudahkan Lelaran Ke Atas Bekas Bersarang?

Bagaimanakah Saya Boleh Mencipta Iterator Meratakan dalam C untuk Memudahkan Lelaran Ke Atas Bekas Bersarang?

Patricia Arquette
Patricia Arquetteasal
2024-11-27 19:22:09254semak imbas

How Can I Create a Flattening Iterator in C   to Simplify Iteration Over Nested Containers?

Pelatar Meratakan dalam C

Pelajar konvensional menavigasi unsur-unsur bekas tunggal, tetapi kadangkala kita menemui bekas bersarang, di mana setiap elemen dalam bekas luar mewakili satu yang berasingan koleksi. Untuk merentasi semua elemen secara berurutan, kita memerlukan mekanisme untuk "meratakan" struktur bersarang.

Di sinilah iterator meratakan memainkan peranan. Ia menggabungkan berbilang peringkat bekas dengan lancar, mempersembahkannya sebagai urutan padu tunggal. Seseorang boleh mengulangi elemen yang diratakan menggunakan gelung berasaskan julat standard, seolah-olah semuanya terkandung dalam bekas tunggal.

Pelaksanaan

Walaupun tiada pelaksanaan terbina dalam dalam perpustakaan C utama, satu contoh pelaksanaan boleh dibuat:

#include <iterator>

template <typename OuterIterator>
class flattening_iterator {
public:
    using outer_iterator = OuterIterator;
    using inner_iterator = typename OuterIterator::value_type::iterator;

    using iterator_category = std::forward_iterator_tag;
    using value_type = typename inner_iterator::value_type;

    flattening_iterator() {}
    flattening_iterator(outer_iterator it) : outer_it_(it), outer_end_(it) {}
    flattening_iterator(outer_iterator it, outer_iterator end)
        : outer_it_(it), outer_end_(end) {
        if (outer_it_ == outer_end_) return;
        inner_it_ = outer_it_->begin();
        advance_past_empty_inner_containers();
    }

    reference operator*() const { return *inner_it_; }
    pointer operator->() const { return &*inner_it_; }

    flattening_iterator& operator++() {
        ++inner_it_;
        if (inner_it_ == outer_it_->end()) advance_past_empty_inner_containers();
        return *this;
    }

    flattening_iterator operator++(int) {
        flattening_iterator it(*this);
        ++*this;
        return it;
    }

    friend bool operator==(const flattening_iterator& a, const flattening_iterator& b) {
        if (a.outer_it_ != b.outer_it_) return false;
        if (a.outer_it_ != a.outer_end_ && b.outer_it_ != b.outer_end_ &&
            a.inner_it_ != b.inner_it_)
            return false;
        return true;
    }

    friend bool operator!=(const flattening_iterator& a, const flattening_iterator& b) {
        return !(a == b);
    }

private:
    void advance_past_empty_inner_containers() {
        while (outer_it_ != outer_end_ && inner_it_ == outer_it_->end()) {
            ++outer_it_;
            if (outer_it_ != outer_end_) inner_it_ = outer_it_->begin();
        }
    }

    outer_iterator outer_it_;
    outer_iterator outer_end_;
    inner_iterator inner_it_;
};

Untuk menggunakan lelaran merata ini, kita boleh memanfaatkan kaedah meratakan templat fungsi:

template <typename Iterator>
flattening_iterator<Iterator> flatten(Iterator it) {
    return flattening_iterator<Iterator>(it, it);
}

template <typename Iterator>
flattening_iterator<Iterator> flatten(Iterator first, Iterator last) {
    return flattening_iterator<Iterator>(first, last);
}

Contoh Penggunaan

Pertimbangkan bekas bersarang ini:

std::unordered_set<std::vector<int>> s;
s.insert(std::vector<int>());
s.insert({ 1, 2, 3, 4, 5 });
s.insert({ 6, 7, 8 });
s.insert({ 9, 10, 11, 12 });

Dengan menggunakan lelaran merata, kami boleh mengulangi semua nombor dengan lancar:

for (auto it(flatten(s.begin(), s.end())); it != s.end(); ++it) {
    std::cout << *it << endl;  // prints 1, 2, 3, ..., 12
}

Kesimpulan

Meratakan iterator menyediakan kaedah yang cekap dan elegan untuk melintasi bekas bersarang secara linear. Pendekatan ini menghapuskan keperluan untuk gelung bersarang yang kompleks atau pengurusan indeks manual. Walaupun bukan sebahagian daripada pustaka standard, pelaksanaan ini boleh dengan mudah dimasukkan ke dalam pangkalan kod anda untuk meningkatkan fleksibiliti dan meningkatkan kebolehbacaan.

Atas ialah kandungan terperinci Bagaimanakah Saya Boleh Mencipta Iterator Meratakan dalam C untuk Memudahkan Lelaran Ke Atas Bekas Bersarang?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn