forward list library (tsz. forward list libraries)
Az std::forward_list
a C++11 óta elérhető, könnyű és hatékony egyelemű (singly-linked) lista-konténer. Elsődleges célja az alacsony memóriahasználat és a folyamatos, előre irányuló bejárás biztosítása. A következőkben részletesen bemutatjuk struktúráját, főbb műveleteit, komplexitását, összehasonlítását más STL-konténerekkel, tipikus felhasználási területeit, valamint néhány gyakorlati példát és jó tanácsot.
std::forward_list
?next
), előzőre nem.std::list
(kétirányú láncolt lista) funkcionalitásának egyszerűsítése, memória- és időhatékonyság növelése.<forward_list>
fejléc, a konténer része a <list>
-hez hasonló láncolt tárolóknak.
Tulajdonság | Részletek |
---|---|
Elempárok száma | Dinamikusan növelhető/csökkenthető |
Iterátorok | ForwardIterator: csak előre mozoghat |
Memoriastratégia | Minden elemhez csak egy pointer (következő elem címe) |
Egyelemű láncolás | Csökkentett memóriaigény a kétirányú listához képest |
Stabilitás | Elemtörlés nem érvényteleníti a többi elemet (kivéve az éppen törölt) |
#include <forward_list>
#include <iostream>
std::forward_list<int> fl1; // üres lista
std::forward_list<int> fl2 = {1, 2, 3, 4}; // inicializálás lista-literalből
std::forward_list<int> fl3(5, 42); // 5 elem, mindegyik 42
auto it = fl2.begin(); ++it;
fl2.insert_after(it, 99); // beszúrás az it utáni pozícióra
fl2.erase_after(fl2.begin()); // törlés az első elem utáni pozícióról
begin()
/ cbefore_begin()
: a lista kezdő előtti (saját) iterátora.before_begin()
: iterator a fejtet előtti falcióra (insert/erase után használjuk).insert_after(pos, value)
, erase_after(pos)
: beszúrás/törlés a megadott elem után.push_front()
, pop_front()
: fej beszúrás/törlés (O(1)).empty()
, size()
: empty()
O(1), size()
nincs konstans időben (egyszerű használatkor iterál).
push_front
, pop_front
: O(1)insert_after
, erase_after
: adott pozíció után O(1)size()
: O(n), mert nincs belső számlálóclear()
: O(n)merge()
, splice_after()
, remove()
, unique()
, reverse()
: mindegyik O(n)Az egyelemű láncolt szerkezet miatt a véletlenszerű hozzáférés (mint pl. operator
) nem támogatott, csak sorozatos (szekvenciális) bejárásra alkalmas.
Konténer | Véletlenszerű hozzáférés | Beszúrás/törlés közepe táján | Memórialábnyom | Iterátor irányok |
---|---|---|---|---|
vector
|
O(1) | O(n) | tömbhöz hasonló | kétirányú |
deque
|
O(1) | O(n) | magasabb, blokkos | kétirányú |
forward_list
|
nem támogatott | O(1) (után) | alacsony | előre irányú |
list
|
nem támogatott | O(1) | duplán láncolt | kétirányú |
array
|
O(1) | nem módosítható hossz | fix méretű | véges |
vector
vagy deque
.list
.forward_list
.
forward_list
ideális, mert csak előre haladunk elemenként.
merge()
Összefűz két rendezett forward_list
-et; in-place, konstans extra memóriaigénnyel.splice_after()
Egy másik listából átmozgat elemeket úgy, hogy csak pointereket kötünk át: O(1) művelet, ha egyetlen elem.remove()
, remove_if()
Adott érték(ek) törlése elsődleges bejárással.unique()
Sorozatos egyező elemek eltávolítása.reverse()
Lista irányának megfordítása; in-place, O(n).sort()
Nem elérhető! Egyelemű listán nincs beépített sort()
. Ha kell, először másold át list
-be, vagy használd külső algoritmust.
#include <forward_list>
#include <iostream>
#include <algorithm>
int main() {
std::forward_list<int> numbers = {1, 3, 5, 7, 9};
// push_front, pop_front
numbers.push_front(0); // {0,1,3,5,7,9}
numbers.pop_front(); // {1,3,5,7,9}
// insert_after & erase_after
auto it = std::find(numbers.begin(), numbers.end(), 5);
if (it != numbers.end()) {
numbers.insert_after(it, 6); // {1,3,5,6,7,9}
numbers.erase_after(it); // {1,3,5,7,9}
}
// remove_if: törli a páros számokat
numbers.remove_if((int x){ return x % 2 == 0; });
// merge: két rendezett lista összefésülése
std::forward_list<int> evens = {2,4,6,8};
numbers.merge(evens);
// kiírás
for (int x : numbers) {
std::cout << x << ' ';
}
// Eredmény: 1 2 3 4 5 6 7 8 9
}
std::list
-et!splice_after
átmozgatja, nem másolja az elemet; ez gyorsabb, de figyelj, ha az eredeti listát még használod.reserve()
; minden beszúrás külön memóriakiosztással jár. Nagy listák esetén mérlegeld az allocator
testreszabását.sort()
-ra, először másold át std::list
-be, vagy más adatstruktúrát használj.
Az std::forward_list
a C++ nyelvben egy könnyű, egyelemű láncolt lista, amely kiválóan alkalmas soros adatfeldolgozásra, memóriaérzékeny alkalmazásokra és egyszerű, előre haladó bejárást igénylő algoritmusokra. Bár kevésbé rugalmas, mint a kétirányú std::list
, alacsonyabb memóriafoglalása és egyszerűbb működése miatt sok helyzetben előnyösebb. Használatakor érdemes tudatosan mérlegelni a konténer erősségeit és korlátait, hogy a legoptimálisabb megoldást választhassuk programunk számára.