vecteur vs liste dans la STL
J'ai remarqué dans l'efficacité de la STL qui
vecteur est le type de séquence
doit être utilisé par défaut.
Qu'est ce que ça veut dire? Il semble ignorer que l'efficacité vector
peut rien faire.
Quelqu'un pourrait-il me proposer un scénario où vector
n'est pas une option réalisable mais list
doit être utilisé?
- Si ce n'est pas ce que vous avez demandé, il est intéressant de souligner que la valeur par défaut vecteur signifie également que vous pouvez facilement interagir avec des vieux code, bibliothèques C, ou non-des bibliothèques de modèles, depuis le vecteur est un mince wrapper autour de la "traditionnelle" de la gamme dynamique d'un pointeur et la taille.
- Bjarne Strostrup effectivement fait un test où il nombres aléatoires générés et puis ajoutés à une liste et un vecteur respectivement. Les insertions ont été faites pour que la liste/vecteur a été commandé à tout moment. Même si c'est généralement "liste de domaine" le vecteur a surclassé la liste par une marge importante. La raison étant que la mémoire d'accès est lent et la mise en cache fonctionne mieux pour les données séquentielles. Tout est disponible dans son discours de "GoingNative 2012"
- baptiste-wicht.com/2012/12/cpp-benchmark-vector-list-deque
- Si vous voulez voir la keynote par Bjarne Stroustrup que @échapper mentionné, je l'ai trouvé ici: youtu.être/OB-bdWKwXsU?t=2672
InformationsquelleAutor skydoor | 2010-02-05
Vous devez vous connecter pour publier un commentaire.
Les Situations où vous souhaitez insérer un grand nombre d'éléments dans n'importe où, mais la fin d'une séquence à plusieurs reprises.
Découvrez la complexité des garanties pour chaque type de conteneur:
Ce sont la complexité des garanties de la norme des containers?
list
apush_front
vecteur:
liste:
En général, l'utilisation de vecteur lorsque vous ne vous souciez pas de ce type de conteneur séquentiel que vous utilisez, mais si vous faites beaucoup d'insertions ou des ratures et ce, partout dans le conteneur autre que de la fin, vous allez avoir à utiliser la liste. Ou si vous avez besoin d'un accès aléatoire, alors vous allez vouloir vecteur, pas de liste. Autre que cela, il y a naturellement le cas où vous êtes va avoir besoin de l'un ou l'autre en fonction de votre application, mais en général, ce sont de bonnes lignes directrices.
reserve()
le ramener à O(1). L'ajout de nouveaux éléments à une liste (c'est à dire pas d'épissage de mer) effectue en O(n) libre allocations de magasin.list
libère de la mémoire lors de l'effacement d'éléments, maisvector
ne le fait pas. Unvector
ne pas réduire sa capacité lorsque vous réduisez sa taille, sauf si vous utilisez leswap()
truc.vector
avant-l'allocation: Ce peut consommer beaucoup de mémoire pour les grands vecteurs si vous ne connaissez pas la taille à l'avance et ne sont pas en mesure dereserve
. //vector
re-l'allocation: Cela peut être un cher pour les grands-ish objets (et de grands vecteurs).Si vous n'avez pas besoin d'insérer des éléments souvent alors un vecteur le plus efficace. Il a beaucoup plus de cache du PROCESSEUR, de la localité de une liste. En d'autres termes, l'accès à un élément rend très probable que le prochain élément est présent dans le cache, et peut être récupéré sans avoir à lire lente RAM.
Plus de réponses ici, en oubliez un détail important: pour quoi?
Que voulez-vous garder dans la containter?
Si c'est une collection de
int
s, puisstd::list
perdra dans tous les cas de figure, peu importe si vous pouvez réaffecter, vous ne retirez de l'avant, etc. Les listes sont plus lents à la traverse, chaque insertion frais vous une interaction avec l'allocateur. Il serait extrêmement difficile de préparer un exemple, oùlist<int>
beatsvector<int>
. Et même alors,deque<int>
peut-être mieux ou à proximité, ne pas justyfing l'utilisation de listes, ce qui aura une plus grande surcharge de la mémoire.Toutefois, si vous êtes aux prises avec de gros, laid gouttes de données - et de quelques-uns d'entre eux - vous ne voulez pas overallocate lors de l'insertion, et de la copie en raison de la réallocation de la serait une catastrophe - alors vous pouvez peut-être être mieux avec une
list<UglyBlob>
quevector<UglyBlob>
.Encore, si vous passez à
vector<UglyBlob*>
ou mêmevector<shared_ptr<UglyBlob> >
, nouveau - liste de retard.Donc, motif de l'accès, de la cible de l'élément de comptage etc. affecte encore la comparaison, mais à mon avis, les éléments de la taille - le coût de la copie, etc.
list<T>
est la possibilité desplice
dans O(1). Si vous avez besoin de la constante de temps de l'épissage, la liste peut également être la structure de choix 😉UglyBlob
- même des objets avec juste un peu de chaîne les membres peuvent facilement être d'un coût prohibitif pour copier, de sorte que les réaffectations est coût. Aussi: Ne négligez pas l'espace supplémentaire à la croissance exponentielle d'unevector
tenant des objets de quelques dizaines d'octets la taille peut causer (si vous ne pouvez pasreserve
à l'avance).vector<smart_ptr<Large>>
vslist<Large>
-- je dirais, si vous avez besoin d'un accès aléatoire aux éléments, levector
de sens. Si vous n'avez pas besoin d'un accès aléatoire, lalist
semble plus simple et devrait effectuer aussi.Une capacité de std::list est épissage (liaison ou le déplacement d'une partie ou toute une liste dans une autre liste).
Ou peut-être si votre contenu est très cher à copier. Dans un tel cas, il pourrait être moins cher, par exemple, pour trier la collection avec une liste.
Notez également que si la collection est petite (et le contenu ne sont pas particulièrement cher pour copier), un vecteur peut toujours mieux que une liste, même si vous insérer et effacer n'importe où. Une liste alloue à chaque nœud individuellement, et qui peut être beaucoup plus coûteux que le déménagement quelques objets simples autour.
Je ne pense pas qu'il y a de très dur règles. Cela dépend de ce que la plupart veulent faire avec le conteneur, ainsi que sur la façon dont grand vous attendez le conteneur et le contenu type. Un vecteur en général l'emporte sur une liste, car elle alloue à son contenu comme un seul bloc contigu (il est en fait un tableau alloué dynamiquement, et dans la plupart des cas d'un tableau est le moyen le plus efficace pour contenir un tas de choses).
splice
entre les différentes listes est spécifié comme linéaire de la complexité et desize
est spécifiquement constante. Donc, pour accueillir les novices qui itérer sursize
ou que ce soit, toute une classe d'algorithmes est hors de portée pour la STL, ou "conforme" conteneurs de la période.Bien les élèves de ma classe me semble tout à fait incapable de m'expliquer quand il est plus efficace d'utiliser des vecteurs, mais ils ont l'air tout à fait heureux quand me conseiller d'utiliser des listes.
C'est la façon dont je le comprends
Listes:
Chaque élément contient une adresse à l'autre ou de l'élément précédent, donc, avec cette fonctionnalité, vous pouvez générer aléatoirement des éléments, même si elles ne sont pas triées, l'ordre ne change pas: c'est efficace si vous la mémoire est fragmentée.
Mais il a aussi un autre très gros avantage: vous pouvez facilement insérer/supprimer des éléments, parce que la seule chose que vous devez faire est de changer certaines de pointeurs.
Inconvénient:
Pour lire de façon aléatoire un seul élément, vous devez sauter d'un point à un autre jusqu'à ce que vous trouver la bonne adresse.
Vecteurs:
Lors de l'utilisation de vecteurs, la mémoire est beaucoup plus organisés en rangées régulières: chaque n-ième éléments sont stockées juste après (n-1)ème élément et avant (n+1)ème élément.
Pourquoi est-il mieux que la liste ?
Parce que c'permettre à accès aléatoire rapide.
Voici comment: si vous connaissez la taille d'un élément dans un vecteur, et si elles sont contiguës en mémoire, vous pouvez facilement prédire où la n-ième élément est; vous n'avez pas à parcourir tous les éléments d'une liste à lire celui que vous voulez, avec un vecteur, directement à vous lire, avec une liste vous ne pouvez pas.
D'autre part, de modifier le tableau de vecteurs ou de modifier une valeur est beaucoup plus lente.
Listes sont plus appropriés pour garder la trace des objets qui peuvent être ajoutés/supprimés de la mémoire.
Les vecteurs sont plus appropriés lorsque vous souhaitez accéder à un élément d'une grande quantité d'articles simples.
Je ne sais pas comment sont les listes optimisé, mais vous devez savoir que si vous voulez l'accès en lecture rapide, vous devez utiliser des vecteurs, parce que la qualité de la STL fixer des listes, il n'est pas aussi rapide de l'accès en lecture de vecteur.
vector
causé par la modification de ses taille peut être lent? alors d'accord, mais dans les cas oùreserve()
peut être utilisé, qui évite ces problèmes.Fondamentalement, un vecteur est un tableau avec gestion automatique de la mémoire. Les données sont contigus en mémoire. Essayez d'insérer des données dans le milieu est une opération coûteuse.
Dans une liste les données sont stockées en indépendants des emplacements de mémoire. L'insertion dans le milieu n'est pas de la copie de certaines données pour faire de la place pour la nouvelle.
Pour répondre plus spécifiquement à votre question, je vais vous citer cette page
Tout moment, vous ne pouvez pas avoir les itérateurs invalidé.
deque
suffirait.Quand vous avez beaucoup d'insertion ou délétion dans le milieu de la séquence. par exemple, un gestionnaire de mémoire.
La préservation de la validité des itérateurs est l'une des raisons pour utiliser une liste. L'autre, c'est quand vous ne voulez pas un vecteur de réaffecter lors de la poussée des éléments. Cela peut être géré par une utilisation intelligente de la réserve(), mais dans certains cas, il peut être plus facile ou plus possible d'utiliser une liste.
Lorsque vous souhaitez déplacer des objets entre les conteneurs, vous pouvez utiliser
list::splice
.Par exemple, un graphe de l'algorithme de partitionnement peut avoir un nombre constant d'objets de manière récursive divisé entre un nombre croissant de conteneurs. Les objets doivent être initialisés à la fois et de toujours rester au même endroit dans la mémoire. C'est beaucoup plus rapide pour les réorganiser en réassocier que par la réaffectation des.
Edit: que les bibliothèques se préparer à mettre en œuvre C++0x, le cas général de l'épissage une sous-suite dans une liste est de plus en complexité linéaire avec la longueur de la séquence. C'est parce que
splice
(maintenant) doit effectuer une itération sur la séquence de compter le nombre d'éléments. (Parce que la liste doit enregistrer sa taille.) Un simple comptage et le rétablissement du lien entre la liste est encore plus rapide que toute autre alternative, et l'épissage de l'ensemble d'une liste ou d'un seul élément sont des cas particuliers avec la constante de la complexité. Mais, si vous avez de longues séquences d'épissage, vous pourriez avoir à creuser autour pour une meilleure, à l'ancienne, non conforme conteneur.La seule règle absolue où
list
doit être utilisé est de l'endroit où vous devez distribuer des pointeurs vers des éléments du conteneur.Contrairement à
vector
, vous savez que la mémoire des éléments ne sera pas réattribué. Si elle pouvait être, alors vous pourriez avoir des pointeurs vers la mémoire inutilisée, ce qui est, au mieux, un gros no-no, et au pire, unSEGFAULT
.(Techniquement, un
vector
de*_ptr
également de travailler mais dans ce cas, vous êtes à l'émulationlist
donc, c'est juste de la sémantique.)Autre soft règles ont trait aux problèmes de performance de l'insertion d'éléments dans le milieu d'un conteneur, après quoi
list
serait préférable.Les listes sont un wrapper pour un doublement LinkedList dans la stl, offrant ainsi des fonctionnalités que vous pouvez attendre de la part de d-linklist à savoir O(1) d'insertion et de suppression.
Alors que les vecteurs sont contagieux séquence de données qui fonctionne comme un tableau dynamique.P.S - plus facile à traverser.
Faire simple-
À la fin de la journée quand vous êtes confus de choisir des contenants en C++, l'utilisation de ce diagramme de flux de l'image ( Dis merci pour moi ) :-
entrez la description de l'image ici
Vecteur-
1. vecteur est basé sur contagieux mémoire
2. vecteur est le chemin à parcourir pour petit ensemble de données
3. vecteur d'effectuer plus rapidement tout en se déplaçant sur le jeu de données
4. vecteur d'insertion suppression est lent sur le vaste ensemble de données, mais très rapide
petite
Liste-
1. la liste est basée sur un segment de mémoire
2. liste de chemin à faire pour un très vaste ensemble de données
3. la liste est relativement lent sur la traversée de petits jeux de données, mais rapide à
vaste ensemble de données
4. liste d'insertion suppression est rapide sur vaste ensemble de données, mais lente sur les petits
ceux
Dans le cas d'un vecteur et liste, les principales différences qui se collent à moi sont les suivants:
vecteur
Un vecteur stocke ses éléments dans la mémoire contiguë. Par conséquent, aléatoire
l'accès est possible à l'intérieur d'un vecteur, ce qui signifie que l'accès à un
élément d'un vecteur est très rapide car il suffit de multiplier le
adresse de base avec l'index de l'élément pour accéder à cet élément. En fait, il
ne prend que O(1) ou à temps constant à cet effet.
Depuis un vecteur de coeur encapsule un tableau, chaque fois que vous insérez un
élément dans le vecteur (tableau dynamique), il a pour redimensionner lui-même par
trouver un nouveau bloc contigu de mémoire pour accueillir les nouveaux
les éléments de ce qui est coûteux.
Il ne consomme pas de mémoire supplémentaire pour stocker les pointeurs vers d'autres
éléments à l'intérieur d'elle.
liste
Une liste stocke ses éléments non contigus en mémoire. Par conséquent,
accès aléatoire n'est pas possible à l'intérieur d'une liste, ce qui signifie que le
d'accéder à ses éléments, nous devons utiliser les pointeurs et les traverse
la liste qui est plus lent par rapport à un vecteur. Cela prend un temps O(n) ou un temps linéaire qui est
plus lent que O(1).
Depuis une liste des utilisations non contigu de mémoire, le temps pris pour insérer un
élément à l'intérieur d'une liste est beaucoup plus efficace que dans le cas de son
vecteur homologue parce que la redistribution de la mémoire est à éviter.
Il consomme de la mémoire supplémentaire pour stocker des pointeurs vers l'élément avant et
après un élément particulier.
Donc, en gardant à l'esprit ces différences, nous avons l'habitude de considérer mémoire, fréquentes accès aléatoire et insertion pour décider du vainqueur de vecteur vs liste dans un scénario donné.