logo

Structure de données de liste liée en C++ avec illustration

UN liste chaînée est une sorte de structure de données dynamique linéaire que nous utilisons pour stocker des éléments de données. Les tableaux sont également un type de structure de données linéaire dans laquelle les éléments de données sont stockés dans des blocs de mémoire continus.

Contrairement aux tableaux, la liste chaînée n'a pas besoin de stocker des éléments de données dans des régions ou des blocs de mémoire contigus.

UN liste chaînée est composé d'éléments appelés « nœuds » divisés en deux parties. Le premier composant est la partie où nous stockons les données réelles, et le second est une partie où nous stockons le pointeur vers le nœud suivant. Ce type de structure est connu sous le nom de « liste chaînée unique .'

Liste chaînée en C++

Ce didacticiel examinera en profondeur la liste à chaînage unique.

La structure d'une liste à chaînage unique est illustrée dans le diagramme ci-dessous

Structure de données de liste liée en C++ avec illustration
  • Comme nous l'avons vu dans la partie ci-dessus, le premier nœud de la liste chaînée est appelé « tête », tandis que le dernier nœud est appelé « queue ». C'est parce qu'aucune adresse mémoire n'est spécifiée dans le dernier nœud, le nœud final de la liste chaînée aura un pointeur suivant nul.
  • Étant donné que chaque nœud inclut un pointeur vers le nœud suivant, les éléments de données de la liste chaînée n'ont pas besoin d'être conservés dans des emplacements contigus. Les nœuds peuvent être dispersés dans la mémoire. Étant donné que chaque nœud a l’adresse de celui qui le suit, nous pouvons accéder aux nœuds quand nous le souhaitons.
  • Nous pouvons rapidement ajouter et supprimer des éléments de données de la liste connectée. En conséquence, la liste chaînée peut augmenter ou se contracter de manière dynamique. La liste chaînée n’a pas de quantité maximale d’éléments de données qu’elle peut contenir. En conséquence, nous pouvons ajouter autant d’éléments de données que nous le souhaitons à la liste chaînée tant qu’il y a de la RAM disponible.
  • Parce que nous n'avons pas besoin de spécifier à l'avance le nombre d'éléments dont nous avons besoin dans la liste chaînée, la liste chaînée économise de l'espace mémoire en plus d'être simple à insérer et à supprimer. Le seul espace utilisé par une liste chaînée est de stocker le pointeur vers le nœud suivant, ce qui ajoute un certain coût.

Nous passerons ensuite en revue les différentes opérations pouvant être effectuées sur une liste chaînée.

1) Insertion

La liste chaînée est développée par l’action d’y ajouter des éléments. Bien que cela semble simple, étant donné la structure de la liste chaînée, nous savons que chaque fois qu'un élément de données est ajouté, nous devons changer les pointeurs suivants des nœuds précédent et suivant du nouvel élément que nous avons ajouté.

L’endroit où le nouvel élément de données sera inséré est le deuxième aspect à prendre en compte.

java factoriel

Il existe trois endroits où un élément de données peut être ajouté à la liste chaînée.

un. En commençant par la liste chaînée

Vous trouverez ci-dessous une liste connectée des nombres 2->4->6->8->10. La tête pointant vers le nœud 2 pointera désormais vers le nœud 1, et le prochain pointeur du nœud 1 aura l'adresse mémoire du nœud 2, comme le montre l'illustration ci-dessous, si nous ajoutons un nouveau nœud 1 comme premier nœud de la liste. .

Structure de données de liste liée en C++ avec illustration

En conséquence, la nouvelle liste chaînée est 1->2->4->6->8->10.

b. Après le nœud donné

Dans ce cas, on nous donne un nœud et nous devons ajouter un nouveau nœud derrière lui. La liste chaînée ressemblera à ceci si le nœud f est ajouté à la liste chaînée a->b->c->d->e après le nœud c :

Structure de données de liste liée en C++ avec illustration

On vérifie donc si le nœud spécifié est présent dans le schéma ci-dessus. S'il est présent, un nouveau nœud f est créé. Après cela, nous pointons le prochain pointeur du nœud c vers le tout nouveau nœud f. Le pointeur suivant du nœud f pointe désormais vers le nœud d.

c. Le dernier élément de la liste chaînée

Dans le troisième cas, un nouveau nœud est ajouté à la fin de la liste chaînée. Tenez compte de la liste chaînée ci-dessous : a->b->c->d->e, avec l'ajout du nœud f à la fin. Après avoir ajouté le nœud, la liste chaînée apparaîtra comme ceci.

haricot java
Structure de données de liste liée en C++ avec illustration

En conséquence, nous construisons un nouveau nœud f. Le pointeur de queue menant à null est alors pointé sur f, et le pointeur suivant du nœud f est pointé sur null. Dans le langage de programmation ci-dessous, nous avons généré les trois types de fonctions d'insertion.

Une liste chaînée peut être déclarée comme structure ou comme classe en C++. Une liste chaînée déclarée comme structure est une instruction classique de style C. Une liste chaînée est utilisée comme classe dans le C++ moderne, principalement lors de l'utilisation de la bibliothèque de modèles standard.

La structure a été utilisée dans l'application suivante pour déclarer et générer une liste chaînée. Ses membres seront des données et un pointeur vers l'élément suivant.

Programme C++ :

les bases de Java
 #include using namespace std; struct Node { int data; struct Node *next; }; void push ( struct Node** head, int nodeData ) { struct Node* newNode1 = new Node; newNode1 -&gt; data = nodeData; newNode1 -&gt; next = (*head); (*head) = newNode1; } void insertAfter ( struct Node* prevNode, int nodeData ) { if ( prevNode == NULL ) { cout <data = nodedata; newnode1 -> next = prevNode -&gt; next; prevNode -&gt; next = newNode1; } void append ( struct Node** head, int nodeData ) { struct Node* newNode1 = new Node; struct Node *last = *head; newNode1 -&gt; data = nodeData; newNode1 -&gt; next = NULL; if ( *head == NULL ) { *head = newNode1; return; } while ( last -&gt; next != NULL ) last = last -&gt; next; last -&gt; next = newNode1; return; } void displayList ( struct Node *node ) { while ( node != NULL ) { cout <data <'; node="node" -> next; } if ( node== NULL) cout<next, 55 ); cout << 'final linked list: ' endl; displaylist (head); return 0; } < pre> <p> <strong>Output:</strong> </p> <pre> Final linked list: 35--&gt;25--&gt;55--&gt;15--&gt;45--&gt;null </pre> <h3>2) Deletion</h3> <p>Similar to insertion, deleting a node from a linked list requires many points from which the node might be eliminated. We can remove the linked list&apos;s first, last, or kth node at random. We must correctly update the next pointer and all other linked list pointers in order to maintain the linked list after deletion.</p> <p>In the following C++ implementation, we have two deletion methods: deleting the list&apos;s initial node and deleting the list&apos;s last node. We begin by adding nodes to the head of the list. The list&apos;s contents are then shown following each addition and deletion.</p> <p> <strong>C++ Program:</strong> </p> <pre> #include using namespace std; struct Node { int data; struct Node* next; }; Node* deletingFirstNode ( struct Node* head ) { if ( head == NULL ) return NULL; Node* tempNode = head; head = head -&gt; next; delete tempNode; return head; } Node* removingLastNode ( struct Node* head ) { if ( head == NULL ) return NULL; if ( head -&gt; next == NULL ) { delete head; return NULL; } Node* secondLast = head; while ( secondLast -&gt; next -&gt; next != NULL ) secondLast = secondLast-&gt;next; delete ( secondLast -&gt; next ); secondLast -&gt; next = NULL; return head; } void push ( struct Node** head, int newData ) { struct Node* newNode1 = new Node; newNode1 -&gt; data = newData; newNode1 -&gt; next = ( *head ); ( *head ) = newNode1; } int main() { Node* head = NULL; push ( &amp;head, 25 ); push ( &amp;head, 45 ); push ( &amp;head, 65); push ( &amp;head, 85 ); push ( &amp;head, 95 ); Node* temp; cout &lt;&lt; &apos;Linked list created &apos; &lt; next ) cout <data <'; if ( temp="=" null ) cout << 'null' endl; head="deletingFirstNode" (head); 'linked list after deleting node' < next <data cout<<'null'<<endl; last data 'null'; return 0; } pre> <p> <strong>Output:</strong> </p> <pre> Linked list created 95--&gt;85--&gt;65--&gt;45--&gt;25--&gt;NULL Linked list after deleting head node 85--&gt;65--&gt;45--&gt;25--&gt;NULL Linked list after deleting last node 85--&gt;65--&gt;45--&gt;NULL </pre> <h3>Node Count</h3> <p>While traversing the linked list, the process of counting the number of nodes can be performed. In the preceding approach, we saw that if we needed to insert/delete a node or display the contents of the linked list, we had to traverse the linked list from the beginning.</p> <p>Setting a counter and incrementing as well as we traverse each node will provide us the number of nodes in the linked list.</p> <h3>Differences between Array and Linked list:</h3> <table class="table"> <tr> <th>Array</th> <th>Linked list</th> </tr> <tr> <td>Arrays have a defined size.</td> <td>The size of the linked list is variable.</td> </tr> <tr> <td>Inserting a new element is difficult.</td> <td>Insertion and deletion are simpler.</td> </tr> <tr> <td>Access is permitted at random.</td> <td>No random access is possible.</td> </tr> <tr> <td>Elements are in relatively close or contiguous.</td> <td>The elements are not contiguous.</td> </tr> <tr> <td>No additional room is required for the following pointer.</td> <td>The following pointer requires additional memory.</td> </tr> </table> <h3>Functionality</h3> <p>Since linked lists and arrays are both linear data structures that hold objects, they can be utilised in similar ways for the majority of applications.</p> <p>The following are some examples of linked list applications:</p> <ul> <li>Stacks and queues can be implemented using linked lists.</li> <li>When we need to express graphs as adjacency lists, we can use a linked list to implement them.</li> <li>We can also use a linked list to contain a mathematical polynomial.</li> <li>In the case of hashing, linked lists are employed to implement the buckets.</li> <li>When a programme requires dynamic memory allocation, we can utilize a linked list because linked lists are more efficient in this instance.</li> </ul> <h2>Conclusion</h2> <p>Linked lists are data structures used to hold data elements in a linear but non-contiguous form. A linked list is made up of nodes with two components each. The first component is made up of data, while the second half has a pointer that stores the memory address of the following member of the list.</p> <p>As a sign that the linked list has ended, the last item in the list has its next pointer set to NULL. The Head is the first item on the list. The linked list allows for a variety of actions such as insertion, deletion, traversal, and so on. Linked lists are favoured over arrays for dynamic memory allocation.</p> <p>Linked lists are hard to print or traverse because we can&apos;t access the elements randomly like arrays. When compared to arrays, insertion-deletion procedures are less expensive.</p> <p>In this tutorial, we learned everything there is to know about linear linked lists. Linked lists can also be doubly linked or circular. In our forthcoming tutorials, we will go through these lists in detail.</p> <hr></data></pre></next,></data></data>

2) Suppression

Semblable à l'insertion, la suppression d'un nœud d'une liste chaînée nécessite de nombreux points à partir desquels le nœud peut être éliminé. Nous pouvons supprimer le premier, le dernier ou le kème nœud de la liste chaînée au hasard. Nous devons mettre à jour correctement le pointeur suivant et tous les autres pointeurs de liste chaînée afin de conserver la liste chaînée après la suppression.

Dans l'implémentation C++ suivante, nous avons deux méthodes de suppression : supprimer le nœud initial de la liste et supprimer le dernier nœud de la liste. Nous commençons par ajouter des nœuds en tête de liste. Le contenu de la liste est ensuite affiché après chaque ajout et suppression.

Programme C++ :

 #include using namespace std; struct Node { int data; struct Node* next; }; Node* deletingFirstNode ( struct Node* head ) { if ( head == NULL ) return NULL; Node* tempNode = head; head = head -&gt; next; delete tempNode; return head; } Node* removingLastNode ( struct Node* head ) { if ( head == NULL ) return NULL; if ( head -&gt; next == NULL ) { delete head; return NULL; } Node* secondLast = head; while ( secondLast -&gt; next -&gt; next != NULL ) secondLast = secondLast-&gt;next; delete ( secondLast -&gt; next ); secondLast -&gt; next = NULL; return head; } void push ( struct Node** head, int newData ) { struct Node* newNode1 = new Node; newNode1 -&gt; data = newData; newNode1 -&gt; next = ( *head ); ( *head ) = newNode1; } int main() { Node* head = NULL; push ( &amp;head, 25 ); push ( &amp;head, 45 ); push ( &amp;head, 65); push ( &amp;head, 85 ); push ( &amp;head, 95 ); Node* temp; cout &lt;&lt; &apos;Linked list created &apos; &lt; next ) cout <data <\'; if ( temp="=" null ) cout << \'null\' endl; head="deletingFirstNode" (head); \'linked list after deleting node\' < next <data cout<<\'null\'<<endl; last data \'null\'; return 0; } pre> <p> <strong>Output:</strong> </p> <pre> Linked list created 95--&gt;85--&gt;65--&gt;45--&gt;25--&gt;NULL Linked list after deleting head node 85--&gt;65--&gt;45--&gt;25--&gt;NULL Linked list after deleting last node 85--&gt;65--&gt;45--&gt;NULL </pre> <h3>Node Count</h3> <p>While traversing the linked list, the process of counting the number of nodes can be performed. In the preceding approach, we saw that if we needed to insert/delete a node or display the contents of the linked list, we had to traverse the linked list from the beginning.</p> <p>Setting a counter and incrementing as well as we traverse each node will provide us the number of nodes in the linked list.</p> <h3>Differences between Array and Linked list:</h3> <table class="table"> <tr> <th>Array</th> <th>Linked list</th> </tr> <tr> <td>Arrays have a defined size.</td> <td>The size of the linked list is variable.</td> </tr> <tr> <td>Inserting a new element is difficult.</td> <td>Insertion and deletion are simpler.</td> </tr> <tr> <td>Access is permitted at random.</td> <td>No random access is possible.</td> </tr> <tr> <td>Elements are in relatively close or contiguous.</td> <td>The elements are not contiguous.</td> </tr> <tr> <td>No additional room is required for the following pointer.</td> <td>The following pointer requires additional memory.</td> </tr> </table> <h3>Functionality</h3> <p>Since linked lists and arrays are both linear data structures that hold objects, they can be utilised in similar ways for the majority of applications.</p> <p>The following are some examples of linked list applications:</p> <ul> <li>Stacks and queues can be implemented using linked lists.</li> <li>When we need to express graphs as adjacency lists, we can use a linked list to implement them.</li> <li>We can also use a linked list to contain a mathematical polynomial.</li> <li>In the case of hashing, linked lists are employed to implement the buckets.</li> <li>When a programme requires dynamic memory allocation, we can utilize a linked list because linked lists are more efficient in this instance.</li> </ul> <h2>Conclusion</h2> <p>Linked lists are data structures used to hold data elements in a linear but non-contiguous form. A linked list is made up of nodes with two components each. The first component is made up of data, while the second half has a pointer that stores the memory address of the following member of the list.</p> <p>As a sign that the linked list has ended, the last item in the list has its next pointer set to NULL. The Head is the first item on the list. The linked list allows for a variety of actions such as insertion, deletion, traversal, and so on. Linked lists are favoured over arrays for dynamic memory allocation.</p> <p>Linked lists are hard to print or traverse because we can&apos;t access the elements randomly like arrays. When compared to arrays, insertion-deletion procedures are less expensive.</p> <p>In this tutorial, we learned everything there is to know about linear linked lists. Linked lists can also be doubly linked or circular. In our forthcoming tutorials, we will go through these lists in detail.</p> <hr></data>

Nombre de nœuds

Lors du parcours de la liste chaînée, le processus de comptage du nombre de nœuds peut être effectué. Dans l'approche précédente, nous avons vu que si nous devions insérer/supprimer un nœud ou afficher le contenu de la liste chaînée, nous devions parcourir la liste chaînée depuis le début.

Définir un compteur et incrémenter ainsi que nous parcourons chaque nœud nous fournira le nombre de nœuds dans la liste chaînée.

Différences entre un tableau et une liste chaînée :

Tableau Liste chaînée
Les tableaux ont une taille définie. La taille de la liste chaînée est variable.
L'insertion d'un nouvel élément est difficile. L'insertion et la suppression sont plus simples.
L'accès est autorisé de manière aléatoire. Aucun accès aléatoire n'est possible.
Les éléments sont relativement proches ou contigus. Les éléments ne sont pas contigus.
Aucune pièce supplémentaire n’est requise pour le pointeur suivant. Le pointeur suivant nécessite de la mémoire supplémentaire.

Fonctionnalité

Étant donné que les listes chaînées et les tableaux sont tous deux des structures de données linéaires contenant des objets, ils peuvent être utilisés de la même manière pour la majorité des applications.

Voici quelques exemples d’applications de listes chaînées :

  • Les piles et les files d'attente peuvent être implémentées à l'aide de listes chaînées.
  • Lorsque nous devons exprimer des graphiques sous forme de listes de contiguïté, nous pouvons utiliser une liste chaînée pour les implémenter.
  • Nous pouvons également utiliser une liste chaînée pour contenir un polynôme mathématique.
  • Dans le cas du hachage, des listes chaînées sont utilisées pour implémenter les buckets.
  • Lorsqu'un programme nécessite une allocation dynamique de mémoire, nous pouvons utiliser une liste chaînée car les listes chaînées sont plus efficaces dans ce cas.

Conclusion

Les listes chaînées sont des structures de données utilisées pour contenir des éléments de données sous une forme linéaire mais non contiguë. Une liste chaînée est composée de nœuds comportant chacun deux composants. Le premier composant est constitué de données, tandis que la seconde moitié possède un pointeur qui stocke l'adresse mémoire du membre suivant de la liste.

Comme signe que la liste chaînée est terminée, le dernier élément de la liste a son pointeur suivant défini sur NULL. La tête est le premier élément de la liste. La liste chaînée permet une variété d'actions telles que l'insertion, la suppression, le parcours, etc. Les listes chaînées sont privilégiées par rapport aux tableaux pour l'allocation dynamique de mémoire.

Les listes chaînées sont difficiles à imprimer ou à parcourir car nous ne pouvons pas accéder aux éléments de manière aléatoire comme les tableaux. Par rapport aux tableaux, les procédures d’insertion-suppression sont moins coûteuses.

Dans ce didacticiel, nous avons appris tout ce qu'il y a à savoir sur les listes chaînées linéaires. Les listes chaînées peuvent également être doublement liées ou circulaires. Dans nos prochains tutoriels, nous passerons en revue ces listes en détail.