Może to być O (1), jeśli lista przechowuje flagę, która umożliwia zamianę znaczenia wskaźników „ prev
” i „ next
” każdego węzła. Jeśli odwrócenie listy byłoby częstą operacją, takie dodanie może być w rzeczywistości przydatne i nie znam żadnego powodu, dla którego wdrożenie byłoby zabronione przez obecny standard. Posiadanie takiej flagi spowodowałoby jednak, że zwykłe przejście na listę byłoby droższe (choćby o stały czynnik), ponieważ zamiast
current = current->next;
w operator++
iteratorze listy, dostaniesz
if (reversed)
current = current->prev;
else
current = current->next;
co nie jest łatwe do dodania. Biorąc pod uwagę, że listy są zwykle przeszukiwane znacznie częściej niż są odwrócone, normalne byłoby wymuszanie tej techniki. Dlatego operacja odwrotna może mieć złożoność liniową. Należy jednak pamiętać, że t ∈ O (1) ⇒ t ∈ O ( n ), więc, jak wspomniano wcześniej, technicznie możliwe byłoby wdrożenie „optymalizacji”.
Jeśli pochodzisz z języka Java lub podobnego, możesz zastanawiać się, dlaczego iterator musi za każdym razem sprawdzać flagę. Czy nie moglibyśmy zamiast tego mieć dwa różne typy iteratorów, oba wywodzące się ze wspólnego typu podstawowego, i mieć std::list::begin
i std::list::rbegin
zwracać polimorficznie odpowiedni iterator? Chociaż jest to możliwe, pogorszyłoby to wszystko, ponieważ przyspieszenie iteratora byłoby teraz wywołaniem funkcji pośredniej (trudnej do wstawienia). W Javie i tak płacisz tę cenę rutynowo, ale z drugiej strony jest to jeden z powodów, dla których wiele osób korzysta z C ++, gdy wydajność jest krytyczna.
Jak zauważył Benjamin Lindley w komentarzach, ponieważ reverse
nie wolno unieważniać iteratorów, jedynym podejściem dozwolonym przez standard wydaje się być przechowywanie wskaźnika z powrotem do listy wewnątrz iteratora, co powoduje podwójnie pośredni dostęp do pamięci.