Structure de données et algorithme - fonctionnement de base de la liste doublement chaînée (implémentation en langage C)

Nous avons appris à créer une liste doublement liée, et nous allons maintenant apprendre quelques opérations de base sur la liste doublement liée, c'est-à-dire comment ajouter, supprimer, rechercher ou modifier des éléments de données dans la liste doublement liée.

Les connaissances de cette section sont basées sur la maîtrise du processus de création de la liste doublement liée. Nous continuons à apprendre le contenu de cette section en continuant la liste doublement liée créée dans la section précédente. La liste doublement liée créée est affichée dans le figure suivante :

Diagramme schématique d'une liste doublement chaînée

Noeud d'ajout de liste doublement liée

Selon la position où les données sont ajoutées à la liste doublement liée, elles peuvent être subdivisées dans les trois situations suivantes :

ajouter à l'en-tête

Pour ajouter un nouvel élément de données à l'en-tête, il suffit d'établir une relation logique à deux couches entre l'élément et l'élément d'en-tête.

En d'autres termes, en supposant que le nouveau nœud d'élément est temp et que le nœud d'en-tête est head, vous devez effectuer les deux étapes suivantes :

  1. temp->suivant=tête ; tête->prior=temp ;
  2. Déplacez la tête vers temp et pointez à nouveau vers le nouvel en-tête ;

Par exemple, pour ajouter un nouvel élément 7 à l'en-tête de la liste doublement chaînée, le processus de mise en œuvre est illustré dans la figure suivante :

Ajouter des éléments à l'en-tête de la liste doublement liée

Ajouter au milieu de la table

Semblable à l'ajout de données dans une liste à liaison simple, l'ajout de données au milieu d'une liste à liaison double nécessite les deux étapes suivantes, comme illustré dans la figure suivante :

  1. Le nouveau nœud établit d'abord une relation logique à deux niveaux avec son nœud successeur direct ;
  2. Le nœud prédécesseur direct du nouveau nœud établit avec lui une relation logique à deux niveaux ;

Ajouter des éléments de données au milieu de la liste doublement liée

Ajouter au pied de page

Cela revient à ajouter à l'en-tête du tableau. Le processus de mise en œuvre est le suivant (comme illustré dans la figure ci-dessous) :

  1. Trouvez le dernier nœud dans la liste doublement liée ;
  2. Laissez le nouveau nœud avoir une relation logique à double couche avec le dernier nœud ;

Ajouter des éléments de données à la fin de la liste doublement liée

On peut donc essayer d'écrire le code en langage C pour ajouter des données à la liste doublement chaînée, le code de référence est le suivant :

line * insertLine(line * head,int data,int add){
    //新建数据域为data的结点
    line * temp=(line*)malloc(sizeof(line));
    temp->data=data;
    temp->prior=NULL;
    temp->next=NULL;
    //插入到链表头,要特殊考虑
    if (add==1) {
        temp->next=head;
        head->prior=temp;
        head=temp;
    }else{
        line * body=head;
        //找到要插入位置的前一个结点
        for (int i=1; i<add-1; i++) {
            body=body->next;
        }
        //判断条件为真,说明插入位置为链表尾
        if (body->next==NULL) {
            body->next=temp;
            temp->prior=body;
        }else{
            body->next->prior=temp;
            temp->next=body->next;
            body->next=temp;
            temp->prior=body;
        }
    }
    return head;
}

Nœud de suppression de liste doublement liée

Lors de la suppression d'un nœud dans une liste chaînée double, il vous suffit de parcourir la liste chaînée pour trouver le nœud à supprimer, puis de supprimer le nœud de la liste.

Par exemple, le processus d'opération de suppression de l'élément 2 de la base du premier schéma est illustré dans le schéma suivant :

Schéma de principe de l'opération de suppression d'éléments dans une double liste chaînée

Le code d'implémentation du langage C pour supprimer des nœuds dans la liste doublement liée est le suivant :

//删除结点的函数,data为要删除结点的数据域的值
line * delLine(line * head,int data){
    line * temp=head;
    //遍历链表
    while (temp) {
        //判断当前结点中数据域和data是否相等,若相等,摘除该结点
        if (temp->data==data) {
            temp->prior->next=temp->next;
            temp->next->prior=temp->prior;
            free(temp);
            return head;
        }
        temp=temp->next;
    }
    printf("链表中无该数据元素");
    return head;
}

nœud de recherche de liste doublement liée

Habituellement, une liste doublement liée, comme une liste simplement liée, n'a qu'un seul pointeur de tête. Par conséquent, la mise en œuvre de la recherche d'un élément spécifié dans une liste à double liaison est similaire à celle d'une liste à simple liaison, parcourant les éléments de la table de manière séquentielle à partir de l'en-tête.

Le code d'implémentation du langage C est :

//head为原双链表,elem表示被查找元素
int selectElem(line * head,int elem){
//新建一个指针t,初始化为头指针 head
    line * t=head;
    int i=1;
    while (t) {
        if (t->data==elem) {
            return i;
        }
        i++;
        t=t->next;
    }
    //程序执行至此处,表示查找失败
    return -1;
}

nœud de changement de liste doublement liée

L'opération de modification du champ de données du nœud spécifié dans la liste à double lien est effectuée sur la base d'une recherche. Le processus de mise en œuvre est : trouver le nœud stockant l'élément de données par traversée et modifier directement son champ de données.

Le code d'implémentation du langage C pour réaliser cette opération est le suivant :

//更新函数,其中,add 表示更改结点在双链表中的位置,newElem 为新数据的值
line *amendElem(line * p,int add,int newElem){
    line * temp=p;
    //遍历到被删除结点
    for (int i=1; i<add; i++) {
        temp=temp->next;
    }
    temp->data=newElem;
    return p;
}

Résumer

Voici le code d'implémentation complet des opérations "ajout, suppression, vérification et modification" sur les données de la liste doublement chaînée :

#include <stdio.h>
#include <stdlib.h>
typedef struct line{
    struct line * prior;
    int data;
    struct line * next;
}line;
//双链表的创建
line* initLine(line * head);
//双链表插入元素,add表示插入位置
line * insertLine(line * head,int data,int add);
//双链表删除指定元素
line * delLine(line * head,int data);
//双链表中查找指定元素
int selectElem(line * head,int elem);
//双链表中更改指定位置节点中存储的数据,add表示更改位置
line *amendElem(line * p,int add,int newElem);
//输出双链表的实现函数
void display(line * head);
int main() {
    line * head=NULL;
    //创建双链表
    head=initLine(head);
    display(head);
    //在表中第 3 的位置插入元素 7
    head=insertLine(head, 7, 3);
    display(head);
    //表中删除元素 2
    head=delLine(head, 2);
    display(head);
    printf("元素 3 的位置是:%d\n",selectElem(head,3));
    //表中第 3 个节点中的数据改为存储 6
    head = amendElem(head,3,6);
    display(head);
    return 0;
}
line* initLine(line * head){
    head=(line*)malloc(sizeof(line));
    head->prior=NULL;
    head->next=NULL;
    head->data=1;
    line * list=head;
    for (int i=2; i<=5; i++) {
        line * body=(line*)malloc(sizeof(line));
        body->prior=NULL;
        body->next=NULL;
        body->data=i;
        list->next=body;
        body->prior=list;
        list=list->next;
    }
    return head;
}
line * insertLine(line * head,int data,int add){
    //新建数据域为data的结点
    line * temp=(line*)malloc(sizeof(line));
    temp->data=data;
    temp->prior=NULL;
    temp->next=NULL;
    //插入到链表头,要特殊考虑
    if (add==1) {
        temp->next=head;
        head->prior=temp;
        head=temp;
    }else{
        line * body=head;
        //找到要插入位置的前一个结点
        for (int i=1; i<add-1; i++) {
            body=body->next;
        }
        //判断条件为真,说明插入位置为链表尾
        if (body->next==NULL) {
            body->next=temp;
            temp->prior=body;
        }else{
            body->next->prior=temp;
            temp->next=body->next;
            body->next=temp;
            temp->prior=body;
        }
    }
    return head;
}
line * delLine(line * head,int data){
    line * temp=head;
    //遍历链表
    while (temp) {
        //判断当前结点中数据域和data是否相等,若相等,摘除该结点
        if (temp->data==data) {
            temp->prior->next=temp->next;
            temp->next->prior=temp->prior;
            free(temp);
            return head;
        }
        temp=temp->next;
    }
    printf("链表中无该数据元素");
    return head;
}
//head为原双链表,elem表示被查找元素
int selectElem(line * head,int elem){
//新建一个指针t,初始化为头指针 head
    line * t=head;
    int i=1;
    while (t) {
        if (t->data==elem) {
            return i;
        }
        i++;
        t=t->next;
    }
    //程序执行至此处,表示查找失败
    return -1;
}
//更新函数,其中,add 表示更改结点在双链表中的位置,newElem 为新数据的值
line *amendElem(line * p,int add,int newElem){
    line * temp=p;
    //遍历到被删除结点
    for (int i=1; i<add; i++) {
        temp=temp->next;
    }
    temp->data=newElem;
    return p;
}
//输出链表的功能函数
void display(line * head){
    line * temp=head;
    while (temp) {
        if (temp->next==NULL) {
            printf("%d\n",temp->data);
        }else{
            printf("%d->",temp->data);
        }
        temp=temp->next;
    }
}

Le résultat d'exécution du programme est :

1->2->3->4->5
1->2->7->3->4->5
1->7->3->4->5
元素 3 的位置是:3
1->7->6->4->5

2023 nouvelle version du didacticiel vidéo Java sur la structure de données et l'algorithme (partie 1), structure de données et algorithme que les programmeurs java seniors doivent apprendre
2023 nouvelle version du didacticiel vidéo Java sur la structure de données et l'algorithme (partie 2), structure de données et algorithme que le programmeur java senior doit apprendre

Je suppose que tu aimes

Origine blog.csdn.net/Itmastergo/article/details/131822673
conseillé
Classement