web-dev-qa-db-fra.com

Quel est l'avantage de la liste chaînée par rapport à un tableau et inversement?

Veuillez expliquer quel est l'avantage de la liste chaînée par rapport à un tableau. Et aussi y at-il un avantage à utiliser tableau par rapport à la liste chaînée.

Cordialement, Shoaib

20
Shoaib Akhtar

Les deux stockent une séquence d'éléments, mais en utilisant des techniques différentes.

Un tableau stocke les éléments dans un ordre successif en mémoire, c'est-à-dire qu'il se présente comme suit:

--------------------------------------------------------------------------------------
|  item 1  |  item 2  |  item 3  |  ...  ...  |  item x  | //here comes other stuff
--------------------------------------------------------------------------------------

Cela signifie que les éléments sont l'un après l'autre consécutifs en mémoire.

A ((doublement) lié) liste, en revanche, stocke les éléments de la manière suivante: Il crée un propre "élément de liste" pour chaque élément; cet "élément de liste" contient l'élément actuel et un pointeur/référence/indice/etc vers le "prochain élément de liste". S'il est doublement lié, il contient également un pointeur/référence/indice/etc vers le précédent "élément de liste":

                                  ------------
------------        ----------    |  item 4  |
|  item 1  |        | item 2 |    |  next ---+----...
|  next ---+------->| next   |    ------------
------------        ---+------      ^
                       |            |
                       |            |
                       v            |
                       ----------   |
                       | item 3 |   |
                       | next --+---+
                       ----------

Cela signifie que les éléments peuvent être répartis sur toute la mémoire et ne sont pas stockés à des emplacements de mémoire spécifiques.

Maintenant que nous savons cela, nous pouvons comparer certaines opérations habituelles sur des séquences d'éléments:

  • Accès à un élément à un index spécifique: À l'aide d'un tableau, nous calculons simplement le offset pour cet index et avons l'élément à l'index. 

    C'est très bon marché. Par contre avec liste, nous ne savons pas a priori où est stocké l'élément à l'index (car tous les éléments peuvent être n'importe où en mémoire), nous devons donc parcourir l'élément de liste par élément jusqu'à trouver l'élément à l'index. C'est une opération coûteuse.

  • Ajout d'un nouvel élément à la fin de la séquence: L'utilisation d'un tableau peut conduire au problème suivant: Les tableaux ont généralement une taille fixe, donc si nous avons la situation, notre tableau est déjà complètement rempli (voir //here comes other stuff), nous ne pourrons probablement pas y insérer le nouvel élément car il pourrait déjà y avoir autre chose. Donc, il faut peut-être copier tout le tableau. Cependant, si le tableau n'est pas rempli, nous pouvons simplement y placer l'élément.

    En utilisant un list, nous devons générer un nouvel "élément de liste", y placer l’élément et définir le pointeur next du dernier élément en cours sur ce nouvel élément de liste. Habituellement, nous stockons une référence au dernier élément en cours afin de ne pas avoir à parcourir toute la liste pour le trouver. Ainsi, l'insertion d'un nouvel élément n'est pas un problème réel avec les listes.

  • Ajout d'un nouvel élément quelque part au milieu: Considérons tout d'abord tableaux: ici, nous pourrions entrer dans la situation suivante: Nous avons un tableau avec les éléments 1 à 1000:

    1 | 2 | 3 | 4 | 5 | 6 | ... | 999 | 1000 | free | free

    Maintenant, nous voulons insérer 4.5 entre 4 et 5: Cela signifie que nous devons déplacer les éléments tous de 5 à 1000 d'une position à droite afin de laisser de la place pour le 4.5:

     1 | 2 | 3 | 4 | free | 5 | 6 | ... | 999 | 1000 | free
    
                      ||
                      vv
    
     1 | 2 | 3 | 4 | 4.5  | 5 | 6 | ... | 999 | 1000 | free
    

    Déplacer tous ces éléments est une opération très coûteuse. Alors mieux vaut ne pas le faire trop souvent.

    Nous considérons maintenant comment un liste peut effectuer cette tâche: supposons que nous avons actuellement la liste suivante:

     1 -> 2 -> 3 -> 4 -> 5 -> ... -> 999 -> 1000
    

    Encore une fois, nous voulons insérer 4.5 entre 4 et 5. Cela peut être fait très facilement: nous générons un nouvel élément de liste et mettons à jour les pointeurs/références:

     1 -> 2 -> 3 -> 4        5 -> ... -> 999 -> 1000
                    |        ^
                    +-> 4.5 -+
    

    Nous avons simplement créé un nouvel élément de liste et généré une sorte de "contournement" pour l'insérer - très bon marché (tant que nous avons un pointeur/une référence à l'élément de liste, le nouvel élément sera inséré après).

Donc, résumons: Les listes liées sont vraiment sympas quand il s'agit d'insérer des positions aléatoires (tant que vous avez un pointeur sur l'élément de liste adéquat). Si votre opération implique l'ajout dynamique de nombreux éléments et la traversée de tous les éléments all, une liste peut constituer un bon choix.

Un tableau est très bon pour les accès d'index. Si votre application a souvent besoin d'accéder à des éléments situés à des positions spécifiques, utilisez plutôt un tableau.

Choses notables:

  • Résolution du problème de taille fixe pour les tableaux: Comme indiqué précédemment, les tableaux (bruts) ont généralement une taille fixe. Cependant, ce problème n’a plus de raison d’être aujourd’hui, car presque tous les langages de programmation fournissent des mécanismes pour générer des tableaux qui se développent (et éventuellement se réduisent) de façon dynamique, au besoin. Cette croissance et cette réduction peuvent être mises en œuvre de telle sorte que nous ayons amortised runtime de O(1) pour insérer et supprimer des éléments (à la fin du tableau) et que le programmeur n'ait pas à appeler grow et shrink explicitement.

  • Comme les listes fournissent de telles propriétés de Nice pour les insertions, elles peuvent être utilisées comme structures de données sous-jacentes pour les arbres de recherche, etc. I.e. vous construisez un arbre de recherche dont le niveau le plus bas est constitué de la liste liée.

46
phimuemue

Les tableaux ont une taille fixe mais sont plus rapides d'accès: ils sont alloués à un endroit et l'emplacement de chaque élément est connu (vous pouvez passer au bon élément).

Les listes ne sont pas limitées en taille mais en fonction de la quantité de mémoire disponible. Leur accès est plus lent, car pour trouver un élément, vous devez parcourir la liste.

Ceci est une très courte explication: je vous conseillerais de vous procurer un livre sur les structures de données et de le lire. Ce sont des concepts de base que vous devrez comprendre parfaitement.

7
Matteo

Puisque vous avez marqué la question avec "structures de données", je vais répondre à cette question dans ce contexte.

Un tableau est de taille fixe lorsque vous le déclarez/le créez, ce qui signifie que vous ne pouvez plus y ajouter d’éléments. Ainsi, si j’ai un tableau de, disons, 5 éléments, vous pouvez en faire ce que vous voulez, mais vous ne pouvez pas ajouter d’autres éléments.

Une liste chaînée est essentiellement un moyen de représenter une liste où vous pouvez avoir autant d’éléments que vous le souhaitez. Il se compose d'une tête (le premier élément), d'une queue (le dernier élément) et d'éléments (appelés nœuds) situés entre la liste. 

Il existe de nombreux types de listes chaînées que vous rencontrerez probablement dans toutes les classes de structures de données.

La chose essentielle que vous apprendrez avec les listes chaînées est la maîtrise de la création de champs dans vos classes pour pointer vers d'autres objets, comme dans le cas des listes chaînées pour lesquelles vous devez construire votre liste de sorte que chaque nœud pointe vers le suivant nœud.

De toute évidence, cette réponse est très générale. Cela devrait vous donner une idée pour votre classe.

5
Andrés N. Robalino

Avantages du tableau par rapport à la liste chaînée

  1. Le tableau a une adresse spécifique pour chaque élément stocké et nous pouvons donc accéder directement à n’importe quelle mémoire. 

  2. Comme nous savons que la position de l'élément central et que d'autres éléments sont facilement accessibles, nous pouvons facilement effectuer une RECHERCHE BINAIRE dans le tableau.

Inconvénients de la matrice sur la liste chaînée

  1. Le nombre total d'éléments doit être mentionné ou l'allocation de mémoire doit être effectuée au moment de la création du tableau

  2. La taille du tableau, une fois mentionné, ne peut pas être augmentée dans le programme. Si le nombre d'éléments entrés dépasse la taille du tableau, ARRAY OVERFLOW EXCEPTION se produit. 

Avantages de la liste chaînée sur le tableau

  1. Il n'est pas nécessaire de mentionner la taille de la liste au début du programme. 

  2. Comme la liste chaînée n’a pas de limite de taille, nous pouvons continuer à ajouter de nouveaux nœuds (éléments) et à augmenter la taille de la liste dans n’importe quelle mesure.

Inconvénients de la liste chaînée sur tableau

  1. Les nœuds n'ont pas leur propre adresse. Seule l'adresse du premier nœud est stockée et pour atteindre n'importe quel nœud, nous devons parcourir toute la liste du début au nœud souhaité.

  2. Comme tous les nœuds n'ont pas d'adresse particulière, la recherche binaire est impossible. 

2
Koushambi

Bien qu'il ait été mentionné que les tableaux aient de meilleures performances que les listes chaînées, je suis surpris de ne voir aucune mention du "cache" de Word, où que ce soit. Le problème avec les listes chaînées, c’est principalement qu’elles garantissent à peu près que chaque saut d’un nœud à l’autre constituera un cache manquant, ce qui est incroyablement , brutalement coûteux en termes de performances.

Pour le dire simplement, si les performances comptent le moins du monde dans votre programme, vous devriez jamais utiliser une liste chaînée. Déjà. Il n'y a aucune excuse pour cela. Ils sont bien au-delà de "lents", ils sont catastrophiquement lents, et rien à leur sujet ne peut compenser ce fait. Leur utilisation est comme un sabotage intentionnel de votre performance, tout comme l’insertion d’une fonction "wait ()" dans votre code sans aucune raison.

0
antiHUMAN

Si vous ne connaissez pas la quantité d'objets que vous devez stocker au préalable, une liste est probablement ce que vous voulez, car il est très facile de la réduire ou de l'agrandir de manière dynamique, si nécessaire. Cela présente également l’avantage de pouvoir facilement insérer des éléments dans la liste moyenne sans qu’il soit nécessaire de les réaffecter.

L'inconvénient d'une liste vis-à-vis d'un tableau, en revanche, est qu'il est plus lent de sélectionner des éléments individuels, car vous devez effectuer une itération. Avec un tableau, vous n'aurez pas ce problème. Les tableaux, en revanche, sont difficiles à utiliser si vous devez les redimensionner, car cette opération est plus coûteuse que l’ajout ou la soustraction d’éléments à une liste chaînée.

Les listes devraient être utilisées plus couramment, car la facilité d'utilisation est souvent plus bénéfique que le faible gain de performances résultant de l'utilisation d'un tableau de taille statique.

0
korona