Inverser la liste chaînée en C++
Cet article montrera comment inverser une structure de données de liste chaînée en C++.
Utilisez la fonction itérative pour inverser la liste chaînée en C++
Nous supposons que l’objet cible est une liste à chaînage unique et implémentons des extraits de code en conséquence. Dans un premier temps, nous devons examiner les utilitaires de fonction de base dans le code du pilote implémenté pour illustrer l’exemple.
Le nœud de liste chaînée est une simple struct
avec un seul objet de données string
et un pointeur vers le nœud suivant. Nous avons également la fonction addNewNode
qui prend deux arguments, Node*
et une référence à la string
. La fonction addNewNode
est invoquée plusieurs fois dans la routine main
pour construire un nouvel objet de liste et stocker les chaînes du vecteur data_set
. La fonction alloue chaque nœud en mémoire dynamique et renvoie le pointeur vers le nœud nouvellement créé.
Une autre fonction utile pour notre structure de données de liste chaînée est printNodes
, qui est utilisée pour sortir les données de chaque nœud vers le flux cout
. Ce dernier nous aidera à vérifier vaguement l’exactitude de la fonction d’inversion. Notez que printNodes
conserve le nombre de nœuds pendant le parcours de la liste et imprime l’index pour chaque élément. Enfin, nous devons désallouer tous les nœuds avant la fin du programme. Cette étape n’est pas nécessaire pour la démonstration de la fonction d’inversion, mais il est important pour tout projet réel de nettoyer toute la mémoire allouée pendant l’exécution.
#include <iostream>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
struct Node {
struct Node *next{};
string data;
};
struct Node *addNewNode(struct Node *node, string &data) {
auto new_node = new Node;
if (node) node->next = new_node;
new_node->next = nullptr;
new_node->data = data;
return new_node;
}
void freeNodes(struct Node *node) {
struct Node *tmp = nullptr;
while (node) {
tmp = node;
node = node->next;
delete tmp;
}
}
void printNodes(struct Node *node) {
auto count = 0;
while (node) {
cout << "node " << count << " - data: " << node->data << endl;
node = node->next;
count++;
}
}
int main() {
struct Node *tmp, *head = nullptr;
vector<string> data_set = {"Rocket Lake", "Alder Lake", "Tiger Lake",
"Meteor Lake"};
head = addNewNode(head, data_set.at(0));
tmp = head;
for (auto it = data_set.begin() + 1; it != data_set.end(); ++it) {
tmp = addNewNode(tmp, *it);
}
printNodes(head);
freeNodes(head);
return EXIT_SUCCESS;
}
Production:
node 0 - data : Rocket Lake node 1 - data : Alder Lake node 2 -
data : Tiger Lake node 3 -
data : Meteor Lake
Une fois que nous avons initialisé une nouvelle liste chaînée et stocké le début de la liste dans un pointeur séparé, nous pouvons l’utiliser pour inverser le contenu. Dans ce cas, nous avons implémenté la fonction reverseList
, qui accepte un seul argument Node*
et renvoie un nouveau nœud racine. Dans un premier temps, nous dupliquons le pointeur passé et le stockons en tant que variable head
. Nous avons également besoin de deux pointeurs supplémentaires de type Node*
pour faire la comptabilité interne pendant la boucle while
.
L’algorithme d’inversion peut être décrit comme suit : Nous stockons le pointeur de nœud suivant dans une variable temporaire (next
) et affectons la valeur nullptr
à celle d’origine. En conséquence, le nœud head
d’origine pointera vers le nullptr
comme son prochain nœud dans la liste. Ensuite, nous mettons à jour la variable head
pour stocker le nœud suivant (le deuxième) dans la liste d’origine et enregistrons également l’adresse du nœud principal d’origine dans une variable temporaire distincte.
Nous répétons les étapes précédentes jusqu’à ce que le pointeur head
évalue à nullptr
, ce qui signifierait que la fin de la liste est atteinte. Au final, on retourne l’adresse du nouveau nœud de tête stockée dans la variable temporaire n
. Par conséquent, le programme main
appelle la fonction printNodes
pour que l’utilisateur compare le contenu modifié des listes chaînées.
#include <iostream>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
struct Node {
struct Node *next{};
string data;
};
struct Node *addNewNode(struct Node *node, string &data) {
auto new_node = new Node;
if (node) node->next = new_node;
new_node->next = nullptr;
new_node->data = data;
return new_node;
}
void freeNodes(struct Node *node) {
struct Node *tmp = nullptr;
while (node) {
tmp = node;
node = node->next;
delete tmp;
}
}
void printNodes(struct Node *node) {
auto count = 0;
while (node) {
cout << "node " << count << " - data: " << node->data << endl;
node = node->next;
count++;
}
}
Node *reverseList(struct Node *node) {
auto head = node;
Node *n = nullptr;
Node *next = nullptr;
while (head) {
next = head->next;
head->next = n;
n = head;
head = next;
}
return n;
}
int main() {
struct Node *tmp, *head = nullptr;
vector<string> data_set = {"Rocket Lake", "Alder Lake", "Tiger Lake",
"Meteor Lake"};
head = addNewNode(head, data_set.at(0));
tmp = head;
for (auto it = data_set.begin() + 1; it != data_set.end(); ++it) {
tmp = addNewNode(tmp, *it);
}
printNodes(head);
cout << " ----------------------------------- " << endl;
printNodes(reverseList(head));
freeNodes(head);
return EXIT_SUCCESS;
}
Production:
node 0 - data : Rocket Lake node 1 - data : Alder Lake node 2 -
data : Tiger Lake node 3 -
data
: Meteor Lake-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -node 0 -
data
: Meteor Lake node 1 -
data : Tiger Lake node 2 - data : Alder Lake node 3 - data : Rocket Lake
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn FacebookArticle connexe - C++ Data Structure
- Empiler la structure de données à l'aide d'une liste chaînée en C++
- Implémenter Inorder Traversal pour l'arbre de recherche binaire en C++
- Implémenter un tableau circulaire en C++
- Implémenter une structure de données de file d'attente à l'aide d'une liste chaînée en C++
- Insertion d'arbre de recherche binaire en C++
- Liste circulaire doublement chaînée en C++