Outils pour utilisateurs

Outils du site


nsi:langages:go:solutions:liste

Implémentation d'une liste chaînée en Go

Une liste chaînée est une collection d'items formées par des maillons liés les uns aux autres. Chaque maillon correspond à un emplacement mémoire contenant un item et un lien vers le maillon suivant. Comme le type de l'item est connu et que le lien est une adresse vers la case mémoire du maillon suivant, l'occupation mémoire du maillon est connue et peut être réservée.

Éléments de la chaîne

Pointeurs

On a besoin de pointer sur un maillon, il s'agit donc d'une adresse.

Le type défini pour les maillons étant Maillon, l'adresse d'un tel élément sera en Go de type *Maillon. L'étoile sert à indiquer que l'on veut un pointeur sur l'élément.

Type Maillon

On définit le type Maillon contenant un entier et un pointeur vers le maillon suivant. Pour cela on utilise une structure:

type Maillon struct {
    data int
    next *Maillon
}

Entête

La liste elle-même est un conteneur chargé d'amorcer la liste.

type Liste struct {
    head *Maillon
}

Code complet

Retrouver ce script sur GoPlayground.

// Exemple d'une liste d'entiers
package main

import fmt

type Maillon struct {
    data int
    next *Maillon
}

type Liste struct {
    head *Maillon
}


func main(){
    L := CREER_LISTE_VIDE()
    l := LONGUEUR(L)
    fmt.Println("Longueur de la liste :", l)
    INSERER(L, 45, 0)
    INSERER(L, 17, 0)
    INSERER(L, 19, 0)
    INSERER(L, 50, 1)
    x := LIRE(L, 1)
    fmt.Println("Valeur lue à l'indice 1 :", x)
    fmt.Println("Valeur lue à l'indice 2 :", LIRE(L,2))
    SUPPRIMER(L, 1)
    x = LIRE(L,1)
    fmt.Println("Valeur lue à l'indice 1 :", x)
    l = LONGUEUR(L)
    fmt.Println("Longueur de la liste :", l)
    i := RECHERCHER(L, 45)
    fmt.Println("45 apparaît à l'indice :", i)
    fmt.Println("A l'indice 2 : ", LIRE(L,2))
    MODIFIER(L, 137, 2)
    fmt.Println("A l'indice 2, après modif : ", LIRE(L,2))
}

func CREER_LISTE_VIDE() *Liste{
    L := Liste{head:nil}
    return &L
}

func LONGUEUR(L *Liste) int{
    c := 0
    m := L.head
    for m != nil {
        c++
        m = m.next
    }
    return c
}

func INSERER(L *Liste, e int, i int) {
    if i < 0  {
        // interdit. On ne fait pas de gestion d'erreur,
        // on se contente de sortir
        return
    }
    new_maillon := Maillon{data:e, next:nil}
    if (i==0) {
        // insertion en premier
        new_maillon.next = L.head
        L.head = &new_maillon
        return
    }
    // sinon chercher le point d'insertion
    m := L.head
    for (m != nil) && (i > 1) {
        i--
        m = m.next;
    }
    if m == nil {
        // On est arrivé trop loin, pas d'insertion possible
        fmt.Println("Erreur insertion, i trop grand !")
        return
    }
    new_maillon.next = m.next
    m.next = &new_maillon
}

func LIRE(L *Liste, i int) int {
    // il faudrait vérifier i > 0
    if i < 0  {
        fmt.Println("Erreur lecture : indice négatif !")
        return 0
    }
    m := L.head
    for (i > 0) && (m != nil) {
        i--
        m = m.next
    }
    if m == nil {
        // On est arrivé trop loin, pas d'insertion possible
        fmt.Println("Erreur de lecture, i trop grand !")
        return 0
    }
    return m.data
}

func SUPPRIMER(L *Liste, i int) {
    if L.head == nil {
        fmt.Println("Erreur de suppression, liste vide !")
        return
    }
    if i < 0 {
        fmt.Println("Erreur de suppression, indice négatif !")
        return
    }
    m := L.head
    if i==0 {
        // Suppression premier maillon
        L.head = m.next
        return
    }
    // rercherche élément précédent point d'insertion
    for (m != nil) && (i > 1) {
        i--
        m = m.next
    }
    if (m == nil)||(m.next == nil) {
        fmt.Println("Erreur de suppression, indice trop grand !")
        return
    }
    m_to_delete := m.next
    m.next = m_to_delete.next
}

func RECHERCHER(L *Liste, e int) int {
    /* renvoie l'indice de la première apparition
       de e dans la liste s'il existe, -1 sinon */
    m := L.head
    i := 0
    for m != nil {
        if m.data == e {
            return i
        }
        i++
        m = m.next
    }
    return -1
}

func MODIFIER(L *Liste, e int, i int) {
    /* écrit la valeur e à l'indice i */
    if i < 0 {
        fmt.Println("Erreur de modification, indice négatif !")
        return
    }
    m := L.head
    for (m != nil) && (i > 0) {
        i--
        m = m.next
    }
    if m == nil {
        fmt.Println("Erreur de modification, indice trop grand !")
        return
    }
    m.data = e
}
nsi/langages/go/solutions/liste.txt · Dernière modification : de goupillwiki