En aquest tema, explorarem algunes estructures de dades avançades que són útils per a la resolució de problemes complexos i l'optimització del rendiment en Python. Aquestes estructures de dades inclouen piles, cues, deques, heaps i grafos. Aprendrem com utilitzar-les, les seves aplicacions i implementacions pràctiques.
Continguts
Piles (Stacks)
Què és una Pila?
Una pila és una estructura de dades que segueix el principi LIFO (Last In, First Out), és a dir, l'últim element que s'afegeix és el primer que es treu.
Operacions Bàsiques
- push(x): Afegeix l'element
x
a la pila. - pop(): Treu i retorna l'element del cim de la pila.
- peek(): Retorna l'element del cim sense treure'l.
- is_empty(): Retorna
True
si la pila està buida,False
en cas contrari.
Implementació en Python
class Stack: def __init__(self): self.items = [] def push(self, item): self.items.append(item) def pop(self): if not self.is_empty(): return self.items.pop() else: raise IndexError("pop from empty stack") def peek(self): if not self.is_empty(): return self.items[-1] else: raise IndexError("peek from empty stack") def is_empty(self): return len(self.items) == 0 def size(self): return len(self.items) # Exemple d'ús stack = Stack() stack.push(1) stack.push(2) print(stack.pop()) # Sortida: 2 print(stack.peek()) # Sortida: 1
Cues (Queues)
Què és una Cua?
Una cua és una estructura de dades que segueix el principi FIFO (First In, First Out), és a dir, el primer element que s'afegeix és el primer que es treu.
Operacions Bàsiques
- enqueue(x): Afegeix l'element
x
a la cua. - dequeue(): Treu i retorna l'element del front de la cua.
- front(): Retorna l'element del front sense treure'l.
- is_empty(): Retorna
True
si la cua està buida,False
en cas contrari.
Implementació en Python
class Queue: def __init__(self): self.items = [] def enqueue(self, item): self.items.insert(0, item) def dequeue(self): if not self.is_empty(): return self.items.pop() else: raise IndexError("dequeue from empty queue") def front(self): if not self.is_empty(): return self.items[-1] else: raise IndexError("front from empty queue") def is_empty(self): return len(self.items) == 0 def size(self): return len(self.items) # Exemple d'ús queue = Queue() queue.enqueue(1) queue.enqueue(2) print(queue.dequeue()) # Sortida: 1 print(queue.front()) # Sortida: 2
Deques (Double-ended Queues)
Què és una Deque?
Una deque (Double-ended Queue) és una estructura de dades que permet l'addició i eliminació d'elements tant pel front com pel final.
Operacions Bàsiques
- append(x): Afegeix l'element
x
al final de la deque. - appendleft(x): Afegeix l'element
x
al front de la deque. - pop(): Treu i retorna l'element del final de la deque.
- popleft(): Treu i retorna l'element del front de la deque.
- is_empty(): Retorna
True
si la deque està buida,False
en cas contrari.
Implementació en Python
from collections import deque # Creació d'una deque d = deque() # Afegeix elements d.append(1) d.appendleft(2) # Treu elements print(d.pop()) # Sortida: 1 print(d.popleft()) # Sortida: 2
Heaps
Què és un Heap?
Un heap és una estructura de dades especialitzada que satisfà la propietat de heap. En un min-heap, el valor del node pare és sempre menor o igual que els valors dels seus fills. En un max-heap, el valor del node pare és sempre major o igual que els valors dels seus fills.
Operacions Bàsiques
- heappush(heap, x): Afegeix l'element
x
al heap. - heappop(heap): Treu i retorna l'element més petit del heap.
- heapify(x): Converteix la llista
x
en un heap.
Implementació en Python
import heapq # Creació d'un min-heap heap = [] # Afegeix elements heapq.heappush(heap, 3) heapq.heappush(heap, 1) heapq.heappush(heap, 2) # Treu l'element més petit print(heapq.heappop(heap)) # Sortida: 1
Grafos (Graphs)
Què és un Grafo?
Un grafo és una estructura de dades que consisteix en un conjunt de nodes (o vèrtexs) i un conjunt d'arestes que connecten parells de nodes.
Representació d'un Grafo
Els grafos es poden representar de diverses maneres, incloent llistes d'adjacència i matrius d'adjacència.
Implementació en Python
Llista d'Adjacència
class Graph: def __init__(self): self.graph = {} def add_edge(self, u, v): if u not in self.graph: self.graph[u] = [] self.graph[u].append(v) def get_neighbors(self, u): return self.graph.get(u, []) # Exemple d'ús g = Graph() g.add_edge(1, 2) g.add_edge(1, 3) g.add_edge(2, 4) print(g.get_neighbors(1)) # Sortida: [2, 3]
Matriu d'Adjacència
import numpy as np class GraphMatrix: def __init__(self, num_nodes): self.matrix = np.zeros((num_nodes, num_nodes)) def add_edge(self, u, v): self.matrix[u][v] = 1 def get_neighbors(self, u): return np.where(self.matrix[u] == 1)[0] # Exemple d'ús gm = GraphMatrix(5) gm.add_edge(1, 2) gm.add_edge(1, 3) gm.add_edge(2, 4) print(gm.get_neighbors(1)) # Sortida: [2 3]
Exercicis Pràctics
Exercici 1: Implementació d'una Pila
Implementa una pila utilitzant una llista en Python i prova les operacions bàsiques.
Exercici 2: Implementació d'una Cua
Implementa una cua utilitzant una llista en Python i prova les operacions bàsiques.
Exercici 3: Utilització de Deques
Utilitza la classe deque
de la biblioteca collections
per implementar una cua de doble extrem i prova les operacions bàsiques.
Exercici 4: Treballant amb Heaps
Utilitza la biblioteca heapq
per crear un min-heap i realitza operacions d'inserció i eliminació.
Exercici 5: Representació de Grafos
Implementa un grafo utilitzant una llista d'adjacència i una matriu d'adjacència. Afegeix algunes arestes i mostra els veïns d'un node donat.
Resum
En aquesta secció, hem explorat diverses estructures de dades avançades com piles, cues, deques, heaps i grafos. Hem après les seves operacions bàsiques i com implementar-les en Python. Aquestes estructures de dades són fonamentals per a la resolució de problemes complexos i l'optimització del rendiment en aplicacions reals.
Curs de Programació en Python
Mòdul 1: Introducció a Python
- Introducció a Python
- Configuració de l'Entorn de Desenvolupament
- Sintaxi de Python i Tipus de Dades Bàsics
- Variables i Constants
- Entrada i Sortida Bàsiques
Mòdul 2: Estructures de Control
Mòdul 3: Funcions i Mòduls
- Definició de Funcions
- Arguments de Funció
- Funcions Lambda
- Mòduls i Paquets
- Visió General de la Biblioteca Estàndard
Mòdul 4: Estructures de Dades
Mòdul 5: Programació Orientada a Objectes
Mòdul 6: Gestió de Fitxers
- Lectura i Escriptura de Fitxers
- Treballant amb Fitxers CSV
- Gestió de Dades JSON
- Operacions amb Fitxers i Directoris
Mòdul 7: Gestió d'Errors i Excepcions
Mòdul 8: Temes Avançats
- Decoradors
- Generadors
- Gestors de Context
- Concurrència: Fils i Processos
- Asyncio per a Programació Asíncrona
Mòdul 9: Proves i Depuració
- Introducció a les Proves
- Proves Unitàries amb unittest
- Desenvolupament Guiat per Proves
- Tècniques de Depuració
- Ús de pdb per a la Depuració
Mòdul 10: Desenvolupament Web amb Python
- Introducció al Desenvolupament Web
- Conceptes Bàsics del Framework Flask
- Construcció d'APIs REST amb Flask
- Introducció a Django
- Construcció d'Aplicacions Web amb Django
Mòdul 11: Ciència de Dades amb Python
- Introducció a la Ciència de Dades
- NumPy per al Càlcul Numèric
- Pandas per a la Manipulació de Dades
- Matplotlib per a la Visualització de Dades
- Introducció al Machine Learning amb scikit-learn