web-dev-qa-db-fra.com

Liste liée vs vecteur

Au cours des derniers jours, je me suis préparé pour mon tout premier entretien téléphonique pour un travail de développement logiciel. En recherchant des questions, j'ai trouvé cet article.

Tout était super jusqu'à ce que j'arrive à ce passage,

"Quand utiliseriez-vous une liste chaînée par rapport à un vecteur?"

D'après l'expérience et la recherche, il s'agit de deux structures de données très différentes, une liste chaînée étant un tableau dynamique et un vecteur un point 2D dans l'espace. La seule corrélation que je puisse voir entre les deux est que si vous utilisez un vecteur comme liste chaînée, par exemple myVector(my value, pointer to neighbor)

Pensées?

18
Ryan

Le vecteur est un autre nom pour tableaux dynamiques . C'est le nom utilisé pour la structure de données de tableau dynamique en C++ . Si vous avez de l'expérience en Java vous les connaissez peut-être avec le nom ArrayList. (Java a également une ancienne classe de collection appelée Vector qui n'est pas utilisée de nos jours en raison de problèmes de fonctionnement). a été conçu.)

Les vecteurs sont bons pour l'accès en lecture aléatoire et l'insertion et la suppression à l'arrière (prend un temps constant amorti), mais mauvais pour les insertions et les suppressions à l'avant ou toute autre position (temps linéaire, car les éléments doivent être déplacés). Les vecteurs sont généralement disposés de manière contiguë en mémoire, donc la traversée est efficace car le cache de mémoire CPU est utilisé efficacement.

Listes liées d'autre part sont bonnes pour insérer et supprimer des éléments à l'avant ou à l'arrière (temps constant), mais pas particulièrement bon pour beaucoup d'autres choses: Par exemple, supprimer un élément à un index arbitraire au milieu de la liste prend un temps linéaire car vous devez d'abord trouver le nœud. D'un autre côté, une fois que vous avez trouvé un nœud particulier, vous pouvez le supprimer ou insérer un nouvel élément après lui en temps constant, ce que vous ne pouvez pas faire avec un vecteur. Les listes liées sont également très simples à mettre en œuvre, ce qui en fait une structure de données populaire.

43
Joni

Je sais qu'il est un peu tard pour ce questionneur, mais il s'agit d'une vidéo très perspicace de Bjarne Stroustrup (l'inventeur de C++) expliquant pourquoi vous devriez éviter les listes liées avec du matériel moderne. https://www.youtube.com/watch?v=YQs6IC-vgmo Avec l'allocation de mémoire rapide sur les ordinateurs d'aujourd'hui, il est beaucoup plus rapide de créer une copie du vecteur avec les éléments mis à jour.

5
Jonathan Roberts

Je n'aime pas la réponse numéro un ici, alors je me suis dit que je partagerais des recherches réelles à ce sujet menées par Herb Sutter de Microsoft. Les résultats du test concernaient jusqu'à 100 000 éléments dans un conteneur, mais ont également affirmé qu'il continuerait à effectuer une liste chaînée, même pour un demi-million d'entités. Sauf si vous prévoyez que votre conteneur aura des millions d'entités, votre conteneur par défaut pour un conteneur dynamique devrait être le vecteur. J'ai résumé plus ou moins ce qu'il dit, mais je lierai également la référence en bas:

"[Même si] vous pré-allouez les nœuds dans une liste chaînée, cela vous donne la moitié des performances, mais c'est encore pire [qu'un vecteur]. Pourquoi? Tout d'abord, c'est plus d'espace - La surcharge par élément (fait partie de la raison) - les pointeurs avant et arrière impliqués dans une liste chaînée - mais aussi (et plus important encore) l'ordre d'accès. La liste chaînée doit traverser pour trouver un point d'insertion, en faisant tout ce chasse-pointeur, qui est le même chose que le vecteur faisait, mais ce qui se passe réellement, c'est que les pré-récupérateurs sont aussi rapides . Effectuer des traversées linéaires avec des données qui sont mappées efficacement dans la mémoire en utilisant, par exemple, un vecteur de pointeurs défini et disposé), il surclassera les listes liées dans presque tous les scénarios. "

https://youtu.be/TJHgp1ugKGM?t=2948

2
simon

Comme correction sur le temps d'insertion et de suppression de Big O dans une liste liée, si vous avez un pointeur qui contient la position de l'élément en cours et les méthodes utilisées pour le déplacer dans la liste (comme .moveToStart() , .moveToEnd(), .next() etc), vous pouvez supprimer et insérer en temps constant.

1
blackbox66

Utilisez le vecteur sauf si "la taille des données est importante" ou "une garantie de sécurité solide est essentielle".

la taille des données est grande : - l'insertion de vecteurs au milieu prend un temps linéaire (en raison de la nécessité de mélanger les choses), mais d'autres sont des opérations à temps constant (comme traversée vers le nième nœud). Il n'y a donc pas beaucoup de surcharge si la taille des données est petite.

Selon "Livre de normes de codage C++ par Andrei Alexandrescu et Herb Sutter"

"L'utilisation d'un vecteur pour les petites listes est presque toujours supérieure à l'utilisation de la liste. Même si l'insertion au milieu de la séquence est une opération à temps linéaire pour le vecteur et une opération à temps constant pour la liste, le vecteur surpasse généralement la liste lorsque les conteneurs sont relativement petits en raison de son meilleur facteur constant, et l'avantage Big-Oh de la liste ne se déclenche que lorsque la taille des données augmente. "

garantie de sécurité solide La liste fournit une garantie de sécurité solide. http://www.cplusplus.com/reference/list/list/insert/

1
Rahul_cs12