Ce pourrait être O (1) si la liste stockait un drapeau qui permet d'échanger la signification des pointeurs « prev
» et « next
» de chaque nœud. Si l'inversion de la liste était une opération fréquente, un tel ajout pourrait en fait être utile et je ne connais aucune raison pour laquelle sa mise en œuvre serait interdite par la norme actuelle. Cependant, avoir un tel drapeau rendrait la traversée ordinaire de la liste plus coûteuse (ne serait-ce que par un facteur constant) car au lieu de
current = current->next;
dans l' operator++
itérateur de la liste, vous obtiendrez
if (reversed)
current = current->prev;
else
current = current->next;
ce qui n'est pas quelque chose que vous décidez d'ajouter facilement. Étant donné que les listes sont généralement parcourues beaucoup plus souvent qu'elles ne sont inversées, il serait très imprudent pour la norme d' imposer cette technique. Par conséquent, l'opération inverse peut avoir une complexité linéaire. Notez cependant que t ∈ O (1) ⇒ t ∈ O ( n ) donc, comme mentionné précédemment, implémenter techniquement votre «optimisation» serait autorisé.
Si vous venez d'un environnement Java ou similaire, vous vous demandez peut-être pourquoi l'itérateur doit vérifier l'indicateur à chaque fois. Ne pourrions-nous pas avoir à la place deux types d'itérateurs distincts, tous deux dérivés d'un type de base commun, et avoir std::list::begin
et std::list::rbegin
renvoyer de manière polymorphe l'itérateur approprié? Bien que possible, cela rendrait le tout encore pire car l'avancement de l'itérateur serait un appel de fonction indirect (difficile à intégrer) maintenant. En Java, vous payez ce prix régulièrement de toute façon, mais là encore, c'est l'une des raisons pour lesquelles de nombreuses personnes optent pour le C ++ lorsque les performances sont critiques.
Comme le souligne Benjamin Lindley dans les commentaires, puisqu'il reverse
n'est pas permis d'invalider les itérateurs, la seule approche permise par le standard semble être de stocker un pointeur vers la liste à l'intérieur de l'itérateur ce qui provoque un double accès mémoire indirect.