Sujet 1052 : [Introduction à la programmation] Fusion de listes liées

Il existe deux listes chaînées a et b . Les nœuds de chaque liste chaînée incluent les numéros et les notes des étudiants . Il est nécessaire de fusionner les deux listes chaînées et de les trier par ordre croissant par numéro d'étudiant.

Format d'entrée

Dans la première ligne, les numéros N et M des deux éléments de liste chaînée a et b sont séparés par des espaces. Les N lignes suivantes sont les données de a, puis les M lignes sont les données de B. Chaque ligne de données se compose de deux parties : le numéro et la note de l'élève.

Format de sortie

Données triées par ordre croissant par numéro d'étudiant

Exemple de saisie

2 3
5 100
6 89
3 82
4 95
2 10

Exemple de sortie

2 10
3 82
4 95
5 100
6 89

Comment écrire le numéro d'étudiant par ordre croissant :

  1. Lors de l'insertion d'un nouveau nœud , le nœud doit être inséré dans la liste chaînée par ordre croissant du numéro d'étudiant.

  2. Pour la liste chaînée A et la liste chaînée B, elles peuvent être désordonnées au début. Mais lors de leur fusion dans une nouvelle liste chaînée , il est nécessaire de conserver les nœuds de la nouvelle liste chaînée par ordre croissant du nombre d'étudiants .

  3. Pour les opérations d'insertion, deux méthodes peuvent être utilisées :

    • Chaque fois que vous insérez, parcourez la liste chaînée pour trouver la position d'insertion appropriée. Comparez le numéro d'étudiant du nouveau nœud avec le numéro d'étudiant du nœud actuel. Après avoir trouvé la position appropriée, insérez le nouveau nœud dans cette position. La complexité temporelle de cette méthode est O(N), où N est la longueur de la liste chaînée.

    • Utilisez des méthodes récursives ou itératives pour conserver l'ordre de la liste chaînée lors de l'insertion de nouveaux nœuds. Comparez le numéro d'étudiant du nouveau nœud avec le numéro d'étudiant du nœud actuel et choisissez de l'insérer dans la position actuelle ou de continuer la récursion ou de passer au nœud suivant en fonction de la relation de taille. La complexité temporelle de cette méthode est également O(N).

Idée:

  1. mergeLinkedListLa fonction implémente l'opération de fusion de deux listes chaînées ordonnées . Il reçoit la somme des pointeurs de nœud principal des deux listes chaînées heada, headbpuis crée un nœud principal virtueldummy comme nœud précédent en tête de la liste chaînée fusionnée . En même temps, trois pointeurs sont définis , et pointent respectivement vers le noeud actuel de la liste chaînée A, B et la liste chaînée fusionnée . En comparant les numéros d'étudiant des deux nœuds de liste chaînée, le nœud de numéro d'étudiant le plus petit est sélectionné à chaque fois pour se connecter à la liste chaînée fusionnée jusqu'à ce que l'une des listes chaînées soit parcourue. Enfin, connectez les listes chaînées restantes directement à la fin de la liste chaînée fusionnée . Enfin, le pointeur du noeud principal de la liste chaînée fusionnée est renvoyé .papbpc

  2. getInputLa fonction obtient les informations sur l'étudiant à partir de l'entrée standard et crée un nouveau nœud pour stocker les informations sur l'étudiant. Renvoie un pointeur vers ce nouveau nœud.

  3. Dans mainla fonction, la somme des pointeurs du noeud principal des deux listes chaînées est d'abord initialisée . Lisez ensuite deux entiers à partir de l'entrée standard et représentez respectivement les longueurs de la liste chaînée A et de la liste chaînée B. Ensuite, utilisez une boucle pour lire les informations sur les étudiants et insérez les étudiants dans la liste chaînée A par « ordre croissant des numéros d'étudiants ». Utilisez ensuite une boucle pour lire les informations sur les étudiants et insérez les étudiants dans la liste chaînée B par ordre croissant des numéros d'étudiants.listalistbnullptrnumanumbnumanumb

  4. Appelez mergeLinkedListla fonction pour fusionner la liste chaînée A et la liste chaînée B dans une nouvelle liste chaînée, et enregistrez le pointeur de nœud principal de la liste chaînée fusionnée renvoyée dans mergedList.

  5. Utilisez une boucle pour imprimer le numéro d'étudiant et la note de chaque nœud de la liste chaînée fusionnée.

  6. Enfin, utilisez une boucle pour libérer la mémoire de chaque nœud de la liste chaînée fusionnée afin d'éviter les fuites de mémoire.

#include <iostream>

using namespace std;

struct student {
    int id;
    int grade;
};

struct Node {
    student data;
    Node* next;
};

Node* mergeLinkedList(Node* heada, Node* headb) {
    Node* dummy = new Node;  // 创建一个虚拟头节点
    dummy->next = nullptr;

    Node* pa = heada;
    Node* pb = headb;
    Node* pc = dummy;

    while (pa != nullptr && pb != nullptr) {
        if (pa->data.id < pb->data.id) {
            pc->next = pa;
            pa = pa->next;
        }
        else {
            pc->next = pb;
            pb = pb->next;
        }
        pc = pc->next;
    }

    if (pa != nullptr) {
        pc->next = pa;
    }
    else {
        pc->next = pb;
    }

    Node* result = dummy->next;
    delete dummy;
    return result;
}

Node* getInput() {
    int id, grade;
    cin >> id >> grade;
    Node* newNode = new Node{ {id, grade}, nullptr };
    return newNode;
}

int main() {
    Node* lista = nullptr;
    Node* listb = nullptr;
    int numa, numb;
    cin >> numa >> numb;

    student s;
    for (int i = 0; i < numa; i++) {
        cin >> s.id >> s.grade;
        Node* newNode = new Node{ s, nullptr };

        if (!lista || s.id < lista->data.id) {
            newNode->next = lista;
            lista = newNode;
        }
        else {
            Node* temp = lista;
            while (temp->next != nullptr && temp->next->data.id < s.id) {
                temp = temp->next;
            }
            newNode->next = temp->next;
            temp->next = newNode;
        }
    }

    for (int i = 0; i < numb; i++) {
        cin >> s.id >> s.grade;
        Node* newNode = new Node{ s, nullptr };

        if (!listb || s.id < listb->data.id) {
            newNode->next = listb;
            listb = newNode;
        }
        else {
            Node* temp = listb;
            while (temp->next != nullptr && temp->next->data.id < s.id) {
                temp = temp->next;
            }
            newNode->next = temp->next;
            temp->next = newNode;
        }
    }

    Node* mergedList = mergeLinkedList(lista, listb);

    // 打印合并后的链表
    Node* temp = mergedList;
    while (temp != nullptr) {
        cout << temp->data.id << " " << temp->data.grade << endl;
        temp = temp->next;
    }

    // 释放内存
    while (mergedList != nullptr) {
        Node* temp = mergedList;
        mergedList = mergedList->next;
        delete temp;
    }

    return 0;
}

Guess you like

Origin blog.csdn.net/qq_63999224/article/details/132925420