Vous êtes sur la page 1sur 19

Structures de données Python

Presque tous les programmes utilisent des données. L'organisation, la gestion et le stockage des
données sont importants car ils permettent un accès plus facile et des modifications efficaces. Les
structures de données vous permettent de stocker et de gérer vos données.

Python a un certain nombre de structures de données intégrées :

- Cordes
- Listes
- Dictionnaires
- Tuples
- Ensembles

Au cours de ce cours, nous découvrirons ces structures de données, les utiliserons pour stocker des
données et verrons leurs applications réelles. Si vous n'êtes pas familiarisé avec les bases de Python,
veuillez d'abord suivre notre cours Python pour débutants.

En plus des structures de données intégrées, Python vous permet de créer vos propres structures de
données, vous permettant d'avoir un contrôle total sur leurs fonctionnalités.

Les structures de données les plus importantes sont :

- Piles

- Files d'attente

- Des arbres

- Listes liées

Ces structures de données ont de nombreuses utilisations dans les algorithmes populaires. Nous les
découvrirons dans les prochains modules.

Chaine de caractères

Les chaînes sont utilisées pour stocker du texte et constituent l'une des structures de données les
plus simples et les plus utilisées. Tout texte entre deux guillemets simples ou doubles est une chaîne.

Par exemple:

La variable x représente maintenant une chaîne.


Caractères spéciaux

Il existe un certain nombre de caractères spéciaux qui peuvent être utilisés dans les chaînes.

\n représente une nouvelle ligne :

De même, \t représente un onglet.

Si vous souhaitez inclure un guillemet simple dans une chaîne entre guillemets simples (ou un
guillemet double dans une chaîne entre guillemets doubles), vous devez l'échapper à l'aide d'une
barre oblique inverse :

La barre oblique inverse est également appelée caractère d'échappement.

Accéder aux chaînes


Les chaînes peuvent être considérées comme une séquence de caractères. Chaque caractère de la
chaîne a sa position (ou index) unique. Vous pouvez accéder à un caractère d'une chaîne en utilisant
son index :

Le code ci-dessus accède au 3ème caractère de la chaîne.


L'index commence à 0, ce qui signifie que le premier caractère a l'index 0. Vous pouvez également
utiliser des indices négatifs, qui accèdent aux caractères de la chaîne en partant de la fin.

Par exemple:

Le code ci-dessus accède au dernier caractère de la chaîne. Vous pouvez parcourir les caractères
d'une chaîne à l'aide d'une boucle for :

A chaque itération, la variable c représentera le caractère courant de la chaîne.

L'opérateur in peut être utilisé pour vérifier si une chaîne fait partie d'une autre chaîne.

Par exemple:

L'opérateur not in peut être utilisé pour vérifier si une chaîne ne fait pas partie d'une autre chaîne.
Fréquence des lettres
Vous créez un programme pour analyser du texte.

Prenez le texte comme première entrée et une lettre comme deuxième entrée, et affichez la
fréquence de cette lettre dans le texte sous forme de pourcentage entier.

Exemple d'entrée :

bonjour

je

Exemple de sortie :

40

Explication : La lettre l apparaît 2 fois dans le texte bonjour, qui comporte 5 lettres. Ainsi, la
fréquence serait (2/5)*100 = 40.

Le résultat de la division est un flotteur. Utilisez la fonction int() pour convertir le résultat en entier.

Longueur moyenne des mots

Étant donné une phrase en entrée, calculez et produisez la longueur moyenne des mots de cette
phrase.

Pour calculer la longueur moyenne des mots, vous devez diviser la somme de toutes les longueurs de
mots par le nombre de mots dans la phrase.

Exemple d'entrée :

ceci est un texte

Exemple de sortie :

3.5

Explication : Il y a 4 mots dans l'entrée donnée, avec un total de 14 lettres, donc la longueur
moyenne sera : 14/4 = 3,5
Guichet

Vous analysez les données de vente d'une billetterie.

Le billet pour un adulte est de 20 $, tandis que le billet pour un enfant de moins de 18 ans est de 5 $.

Les données qui vous sont fournies sont sous forme de dictionnaire, où les clés sont les numéros de
billets vendus et les valeurs sont l'âge des clients.

Par exemple, "123-08": 24 signifie que le billet a été acheté à un jeune de 24 ans.

Votre objectif est de calculer combien d'argent supplémentaire le bureau gagnerait s'il modifiait l'âge
de la réduction du billet en fonction de l'entrée donnée.

Ainsi, votre programme doit prendre un entier comme entrée et sortie le pourcentage de croissance
des revenus, si la remise a été accordée à des personnes de moins de cet âge.

Par exemple, si le bureau gagnait 15 000 $ avec l'âge de remise d'origine et gagnait 18 000 $ avec
14 ans comme âge de remise, alors la croissance serait de ((18000-15000)/15000)*100 = 20 %

Ainsi, pour l'entrée 14, votre programme doit afficher 20. La sortie doit être un entier (utilisez int()
pour convertir le résultat).

Pour parcourir les valeurs d'un dictionnaire, vous pouvez utiliser la fonction .values() :

pour la valeur dans data.values()

Parenthèses équilibrées

Les parenthèses sont équilibrées si toutes les parenthèses ouvrantes ont leurs parenthèses
fermantes correspondantes.

Étant donné une expression en entrée, nous devons savoir si les parenthèses sont équilibrées ou
non.

Par exemple, "(x+y)*(z-2*(6))" est équilibré, tandis que "7-(3(2*9))4) (1" n'est pas équilibré.

Le problème peut être résolu en utilisant une pile.


Poussez chaque parenthèse ouvrante vers la pile et faites apparaître la dernière parenthèse ouvrante
insérée chaque fois qu'une parenthèse fermante est rencontrée.

Si la parenthèse fermante ne correspond pas à la parenthèse ouvrante, arrêtez-vous et dites que les
parenthèses ne sont pas équilibrées.

De plus, après avoir vérifié toutes les parenthèses, nous devons vérifier que la pile est vide - si elle
n'est pas vide, les parenthèses ne sont pas équilibrées.

Implémentez la fonction balancing() pour renvoyer True si les parenthèses de l'expression donnée
sont équilibrées, et False sinon.

Exemple d'entrée :

(un( )eee) )

Exemple de sortie :

Faux

Vous pouvez utiliser une simple liste pour une pile. Utilisez list.insert(0, item) pour pousser sur la pile
et list.pop(0) pour faire apparaître l'élément supérieur. Vous pouvez accéder à l'élément supérieur
de la pile en utilisant list[0].

def balanced(expression):
    a = expression.count('(')
    b = expression.count(')')
    lst = []
    for i in range(len(expression)):
        if expression[i] == '(' or expression[i]==')':
                lst.append(expression[i])
    if a==b:
        if lst[0]==')' or lst[len(lst)-1]=='(':
            return False
        else:
                  return True
    elif a>b or b>a:
        return False

print(balanced(input()))
Structures de données définies par l'utilisateur

Dans les modules précédents, nous avons vu les structures de données intégrées dans Python, qui
incluent des listes, des dictionnaires, des tuples et des ensembles.

Certaines applications nécessitent des fonctionnalités supplémentaires lorsqu'elles travaillent avec


des données, par exemple, les traitements de texte ont une fonction annuler-rétablir, les
planificateurs de tâches ont besoin de mécanismes de mise en file d'attente, les cartes doivent
trouver le chemin le plus court, etc.

Dans ces cas, nous devons définir nos propres structures de données qui fournissent les
fonctionnalités requises.

Certaines des structures de données les plus populaires sont :

- Piles

- Files d'attente

- Listes liées

- Graphiques

Nous allons implémenter les structures de données ci-dessus et les utiliser pour résoudre des
problèmes courants.

Empiler

Une pile est une structure de données simple qui ajoute et supprime des éléments dans un ordre
particulier. Chaque fois qu'un élément est ajouté, il va sur le "haut" de la pile. Seul un élément en
haut de la pile peut être supprimé, tout comme une pile d'assiettes. Ce comportement est appelé
LIFO (Last In, First Out).
Définissons et implémentons la classe Stack avec ses méthodes push, pop, is_empty et print_stack
correspondantes.

Nous utiliserons une liste pour stocker les données.

class Stack:
    def __init__(self):
        self.items = []  
 
    def is_empty(self):
        return self.items == []
 
    def push(self, item):
        self.items.insert(0, item)
   
    def pop(self):
        return self.items.pop(0)
   
    def print_stack(self):
        print(self.items)
   
s = Stack()
s.push('a')
s.push('b')
s.push('c')
s.print_stack()

s.pop()
s.print_stack()

Comme vous pouvez le constater, il est facile de créer une pile à l'aide d'une liste.

Nous utilisons une liste appelée éléments pour stocker nos éléments.

La méthode push ajoute un élément au début de la liste, tandis que la méthode pop supprime le
premier élément de la liste.

Jouez avec le code et voyez le Stack fonctionner en action !


exercice
Vous devez créer un bouton de retour pour un navigateur.

Vous utilisez une pile pour stocker les liens de sites Web visités. Chaque nouveau lien visité est
poussé sur la pile.

Le bouton de retour doit faire apparaître le lien supérieur de la pile et y accéder.

Le code donné déclare une classe Browser en tant que pile et implémente certaines de ses
méthodes. Ensuite, certains liens sont poussés sur la pile.

Une boucle while est ensuite utilisée pour revenir à tous les liens et les imprimer.

Implémentez la méthode pop() requise pour le navigateur, afin que le code donné fonctionne
comme prévu.

Notez que la méthode pop() doit renvoyer la valeur, afin qu'elle puisse être imprimée.

class Browser:
    def __init__(self):
      self.links = []  
 
    def is_empty(self):
      return self.links == []
 
    def push(self, link):
      self.links.insert(0, link)
   
   
 
x = Browser()
x.push('about:blank')
x.push('www.sololearn.com')
x.push('www.sololearn.com/courses/')
x.push('www.sololearn.com/courses/python/')

while not x.is_empty():


    print(x.pop())
class Browser:
    def __init__(self):
      self.links = []  
 
    def is_empty(self):
      return self.links == []
 
    def push(self, link):
      self.links.insert(0, link)
    def pop(self):
     return  self.links.pop(0)
   
 
x = Browser()
x.push('about:blank')
x.push('www.sololearn.com')
x.push('www.sololearn.com/courses/')
x.push('www.sololearn.com/courses/python/')

while not x.is_empty():


    print(x.pop())

File d'attente

Une file d'attente est similaire à une pile, mais définit une manière différente d'ajouter et de
supprimer des éléments.

Les éléments sont insérés à partir d'une extrémité, appelée l'arrière, et supprimés à l'autre
extrémité, appelée l'avant.

Ce comportement est appelé FIFO (First in First Out).

Terminologie
Le processus d'ajout de nouveaux éléments dans la file d'attente est appelé mise en file d'attente. Le
processus de retrait d'un élément de la file d'attente est appelé dequeue.

Applications

Les files d'attente sont utilisées chaque fois que nous devons gérer des objets dans l'ordre en
commençant par le premier.

Les scénarios incluent l'impression de documents sur une imprimante, les systèmes de centre
d'appels répondant aux personnes en attente, etc.

Les listes Python sont le moyen le plus simple d'implémenter une fonctionnalité de file d'attente.

Implémentons la classe Queue avec ses méthodes correspondantes


enqueue, dequeue, is_empty et print.

Nous allons utiliser une liste pour stocker les éléments.


class Queue:
    def __init__(self):
        self.items = []

    def is_empty(self):
        return self.items == []

    def enqueue(self, item):


        self.items.insert(0, item)

    def dequeue(self):
        return self.items.pop()

    def print_queue(self):
        print(self.items)

q = Queue()
q.enqueue('a')
q.enqueue('b')
q.enqueue('42')
q.print_queue()

q.dequeue()
q.print_queue()

Exercice :

File d'attente
Vous créez une application de centre d'appels, qui doit gérer les clients dans une file d'attente.

La classe CallCenter est implémentée en tant que file d'attente. Chaque élément de la file d'attente a
le sujet de l'appel comme valeur. Les deux valeurs possibles sont 'général' et 'technique'. Un appel «
général » prend en moyenne 5 minutes à traiter, tandis qu'un appel « technique » nécessite 10
minutes.

Le code donné ajoute plusieurs clients à la file d'attente à partir de l'entrée de l'utilisateur.

Vous devez retirer de la file d'attente tous les clients ajoutés, calculer et afficher le temps total requis
pour traiter tous les appels.

Utilisez une boucle while pour retirer tous les clients de la file d'attente, jusqu'à ce qu'elle soit vide.

#this code is true 👩‍💻


class CallCenter:
    def __init__(self):
      self.customers = []

    def is_empty(self):
      return self.customers == []

    def add(self, x):


      self.customers.insert(0, x)

    def next(self):
      return self.customers.pop()

c = CallCenter()
time_count=0
while True:
    n = input()
    if n == 'end':
        break
    c.add(n)
    if n=="general":
      time_count +=5
    elif n =="technical":
      time_count+=10
      c.next()
print(time_count )

Liste liée
Une liste chaînée est une séquence de nœuds où chaque nœud stocke ses propres données et un
lien vers le nœud suivant. Un nœud est lié à un autre formant ce qui peut être considéré comme une
chaîne liée :

Le premier nœud est appelé la tête, et il est utilisé comme point de départ pour toute itération dans
la liste. Le dernier nœud doit avoir son lien pointant vers Aucun pour déterminer la fin de la liste.

Contrairement aux piles et aux files d'attente, vous pouvez insérer et supprimer des nœuds à
n'importe quelle position de la liste liée (similaire à une liste standard).

Applications

Les listes liées sont utiles lorsque vos données sont liées. Par exemple, lorsque vous avez besoin de la
fonctionnalité annuler/rétablir, les nœuds peuvent représenter l'état avec des liens vers les états
précédent et suivant. Un autre exemple serait une liste de lecture de musique, où chaque clip est lié
au suivant.

Les listes chaînées peuvent également être utilisées pour créer d'autres structures de données, telles
que des piles, des files d'attente et des graphiques.

Chaque nœud comprendra des données et le lien vers le nœud suivant.

Commençons par créer la classe Node :

class Node:
def __init__(self, data, next):
self.data = data
self.next = next

Nous pouvons maintenant créer la classe LinkedList avec les méthodes correspondantes :

class Node:
    def __init__(self, data, next):
        self.data = data
        self.next = next
class LinkedList:
    def __init__(self):
        self.head = None
   
    def add_at_front(self, data):
        self.head = Node(data, self.head)      

    def add_at_end(self, data):


        if not self.head:
            self.head = Node(data, None)
            return
        curr = self.head
        while curr.next:
            curr = curr.next
        curr.next = Node(data, None)

    def get_last_node(self):
        n = self.head
        while(n.next != None):
            n = n.next
        return n.data

    def is_empty(self):
        return self.head == None

    def print_list(self):
        n = self.head
        while n != None:
            print(n.data, end = " => ")
            n = n.next
        print()

s = LinkedList()
s.add_at_front(5)
s.add_at_end(8)
s.add_at_front(9)

s.print_list()
print(s.get_last_node())

La méthode add_at_front() ajoute un nouveau Node comme tête de liste et y lie la tête précédente.

La méthode add_at_end() itère jusqu'à la fin de la liste à l'aide d'une boucle while et ajoute le
nouveau nœud comme lien du dernier nœud.
Exercices :

Vous créez un lecteur de musique, qui vous permet de créer une liste de lecture de pistes. Le code
donné définit les classes Player et Track, où Player est une liste chaînée, enchaînant des objets Track.
Le code prend un certain nombre de pistes à partir de l'entrée de l'utilisateur et les ajoute à la liste
de lecture.

Vous devez parcourir la liste liée et sortir toutes les pistes de la liste de lecture dans l'ordre de
lecture. Utilisez une boucle while pour parcourir la liste chaînée.

class Track:
    def __init__(self, title, next):
        self.title = title
        self.next = next

class Player:
    def __init__(self):
        self.head = None

    def add(self, title):


        if not self.head:
            self.head = Track(title, None)
            return
        curr = self.head
        while curr.next:
            curr = curr.next
        curr.next = Track(title, None)

p = Player()
while True:
    x = input()
    if x == 'end':
        break
    p.add(x)
    print(x)

Graphique

Les graphiques sont utilisés pour représenter de nombreuses applications réelles telles que les
réseaux, les voies de transport d'une ville et les connexions aux réseaux sociaux.

Un graphe est un ensemble de nœuds connectés où chaque nœud est appelé un sommet et la
connexion entre deux d'entre eux est appelée une arête.
Voici un exemple de graphique :

Cela peut représenter, par exemple, des connexions sur un réseau social, où chaque Vertex
représente une personne et les Edges représentent des connexions.

Appuyez sur Continuer pour découvrir l'implémentation du graphique en Python !

Un graphique peut être représenté à l'aide d'une matrice carrée, où chaque élément représente les
arêtes : 0 indique qu'il n'y a pas d'arête, tandis que 1 indique une arête. Les lignes et les colonnes
représentent les sommets.

011
100
100

La matrice ci-dessus représente un graphe à 3 sommets (c'est pourquoi c'est une matrice 3x3).

Les 1 représentent les arêtes. Il y a 2 arêtes : le 1er sommet est relié au 2ème et au 3ème.

Il y a quatre 1 dans la matrice, car si A est connecté à B, alors B est connecté à A.

Ce type de matrice est appelé matrice d'adjacence, car il indique si les sommets correspondants sont
adjacents ou non.

Implémentons la classe Graph :

class Graph():
    def __init__(self, size):
        self.adj = [ [0] * size for i in range(size)]
        self.size = size
   
    def add_edge(self, orig, dest):
        if orig > self.size or dest > self.size or orig < 0 or dest < 0:
            print("Invalid Edge")
        else:
            self.adj[orig-1][dest-1] = 1
            self.adj[dest-1][orig-1] = 1
       
    def remove_edge(self, orig, dest):
        if orig > self.size or dest > self.size or orig < 0 or dest < 0:
            print("Invalid Edge")
        else:
            self.adj[orig-1][dest-1] = 0
            self.adj[dest-1][orig-1] = 0
           
    def display(self):
        for row in self.adj:
            print()
            for val in row:
                print('{:4}'.format(val),end="")

#a sample Graph
G = Graph(4)
G.add_edge(1, 3)
G.add_edge(3, 4)
G.add_edge(2, 4)
G.display()

Exercices
Vous créez un réseau social appelé X.

Les connexions entre les utilisateurs sont stockées sous forme de graphique.

Le code donné déclare une classe X avec sa méthode add_friend() et crée des connexions pour 5
utilisateurs.

Vous devez prendre un nombre en entrée et sortir le nombre de connexions de l'utilisateur


correspondant.

Les connexions de chaque utilisateur sont stockées dans la matrice adj.

class X():
    def __init__(self, size):
        self.adj = [ [0] * size for i in range(size)]
        self.size = size
   
    def add_friend(self, x, y):
        if x > self.size or y > self.size or x < 0 or y < 0:
            print("Error")
        else:
            self.adj[x-1][y-1] = 1
            self.adj[y-1][x-1] = 1
       
    def remove_friend(self, x, y):
        if x > self.size or y > self.size or x < 0 or y < 0:
            print("Error")
        else:
            self.adj[x-1][y-1] = 0
            self.adj[y-1][x-1] = 0
           

x = X(5)

x.add_friend(1, 3)
x.add_friend(1, 5)
x.add_friend(2, 5)
x.add_friend(2, 4)
x.add_friend(4, 5)

n = int(input())
#your code goes here
a =0
for i in range (len(x.adj)):
    if i+1==n:
        for j in x.adj[i]:
            if  j==1:
                a += 1
print(a)

Parenthèses équilibrées

Les parenthèses sont équilibrées si toutes les parenthèses ouvrantes ont leurs parenthèses
fermantes correspondantes.

Étant donné une expression en entrée, nous devons savoir si les parenthèses sont équilibrées ou
non.

Par exemple, "(x+y)*(z-2*(6))" est équilibré, tandis que "7-(3(2*9))4) (1" n'est pas équilibré.

Le problème peut être résolu en utilisant une pile.

Poussez chaque parenthèse ouvrante vers la pile et faites apparaître la dernière parenthèse ouvrante
insérée chaque fois qu'une parenthèse fermante est rencontrée.

Si la parenthèse fermante ne correspond pas à la parenthèse ouvrante, arrêtez-vous et dites que les
parenthèses ne sont pas équilibrées.

De plus, après avoir vérifié toutes les parenthèses, nous devons vérifier que la pile est vide - si elle
n'est pas vide, les parenthèses ne sont pas équilibrées.
Implémentez la fonction balancing() pour renvoyer True si les parenthèses de l'expression donnée
sont équilibrées, et False sinon.

Exemple d'entrée :

(un( )eee) )

Exemple de sortie :

Faux

def balanced(expression):
    a = expression.count('(')
    b = expression.count(')')
    lst = []
    for i in range(len(expression)):
        if expression[i] == '(' or expression[i]==')':
                lst.append(expression[i])
    if a==b:
        if lst[0]==')' or lst[len(lst)-1]=='(':
            return False
        else:
                  return True
    elif a>b or b>a:
        return False

print(balanced(input()))

Vous aimerez peut-être aussi