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
Lepaskan: 2024-11-27 19:22:09
asal
331 orang telah melayarinya

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_;
};
Salin selepas log masuk

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);
}
Salin selepas log masuk

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 });
Salin selepas log masuk

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
}
Salin selepas log masuk

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!

sumber:php.cn
Kenyataan Laman Web ini
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
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan