¿Qué es una lista enlazada simple y cómo podemos implementarla en Python?
Trabajar con nodos y estructuras de datos en Python puede volverse complejo, especialmente al manejar una gran cantidad de datos. La implementación de una lista enlazada simple o "Single Linked List" es una solución eficaz. Esta estructura nos ayudará a mantener el orden y la secuencia de nodos de manera más organizada, facilitando la manipulación y acceso a los datos sin crear un código demasiado complicado.
¿Cómo empezamos a construir una lista enlazada simple?
Para comenzar, necesitamos crear una clase para la lista enlazada. La implementación inicial incluye definir los atributos esenciales como tail (último nodo) y size (tamaño de la lista). Estos atributos ayudan a tener un control claro sobre la estructura de nuestra lista.
Añadir nodos es una de las operaciones fundamentales. Usamos un método denominado append, que toma como argumento los datos que queremos agregar y los convierte en nodos. Luego, mediante condicionales, verifica si la lista tiene nodos existentes o está vacía, para finalmente enlazar correctamente los nuevos nodos.
defappend(self, data): new_node = Node(data)if self.tail isNone: self.tail = new_node
else: current = self.tail
while current.next: current = current.next current.next= new_node
self.size +=1
¿Cómo iteramos sobre nuestra lista?
Definir un método iterador es crucial para poder recorrer nuestra lista y trabajar con sus valores. El método iter usa el concepto de generadores en Python para producir los valores uno por uno sin almacenarlos en memoria, facilitando el manejo de grandes volúmenes de datos.
defiter(self): current = self.tail
while current: val = current.data
current = current.nextyield val
¿Cómo eliminamos nodos?
La eliminación de nodos puede ser algo más compleja porque requiere ajustar los enlaces entre los nodos. Este método se asegura de mantener la integridad de la lista a medida que los nodos se eliminan.
defdelete(self, data): current = self.tail
previous = self.tail
while current:if current.data == data:if current == self.tail: self.tail = current.nextelse: previous.next= current.next self.size -=1return current.data
previous = current
current = current.next
¿Cómo organizamos y optimizamos nuestro código?
Es esencial documentar y comentar nuestro código, explicando por qué se utilizan ciertos nodos, el tipo de información que se almacena y la secuencia de la relación entre nodos. Esto no solo te ayudará a comprender mejor tu código, sino que también será útil para otros que trabajen con él en el futuro.
¿Qué otros aspectos deberíamos considerar?
Método search: permite encontrar datos específicos dentro de la lista.
Método clear: resetea la lista a su estado original (vacía).
Desafío: Intenta tomar datos de un array unidimensional y transferirlos a una lista enlazada simple.
En resumen, la estructura de listas enlazadas simples no solo organiza los datos de manera eficiente, sino que también ofrece posibilidades de mejora y optimización del código en situaciones más complejas. ¡Te animo a practicar e implementar esta estructura para dominar su funcionamiento y sus beneficios!
Pienso que le falto explicar bien la "anatomía" de lo que creó, por donde empieza la lista, y en donde se ingresan los nuevos valores?
Por defecto, cuando insertamos valores en una Linked list los insertamos en el "head" de la lista haciendo el objeto recien insertado la cabecera de la lista, un poco similar al funcionamiento de las pilas en cuanto a su metodo "add()"
No es por defecto, realmente se asigna a tail como la cabecera y desde alli se van agregando los valores en secuencia.
Amigo muchas gracias, el video me sirvió mucho. Muy recomendado que lo vean para las personas que no les quedó claro como a mi.
Le falto mejor explicación, creo que solo se agarro hablando y escribiendo.
Totalmente de acuerdo... Ya lo vi 14 veces y no termino de entender. Hora de ir a YouTube
No puedo estar más de acuerdo. La verdad era lo mismo sólo presentar el código porque sólo lo va leyendo. No me convence el método de este profesor. Desde el inicio siento que se salta varias cosas.
Que terrible explicación la del método delete... más que explicar, dictaste lo que estabas escribiendo pero no se entiende el motivo
:'v Donde esta facundo cuando uno lo necesita?
Ya no vuelve
¿Que paso con facundo? ME quede esperando su tercer curso de Django :(
Lista enlazada lineal simple (singly linked list) – Implementación en Python
Una lista enlazada (linked list en inglés), es un tipo de estructura de datos compuesta de nodos. Cada nodo contiene los datos de ese nodo y enlaces a otros nodos.
Se pueden implementar distintos tipos de listas enlazadas. En este post vamos a implementar una lista enlazada lineal simple (singly linked list). En este tipo de listas, cada nodo contiene sus datos y un enlace al siguiente nodo. Además la lista tendrá un método para contar el número de elementos de la lista, un método para insertar un elemento en la lista y un método para eliminar un elemento de la lista.
En primer lugar, definimos una clase que va a ser la clase Node. Los objetos de esta contendrán sus propios datos y un enlace al siguiente elemento de la lista:
classNode: def __init__(self, data): self.data= data
self.next=None
A continuación definimos la clase de la lista SinglyLinkedList, que contiene el primer elemento de la lista:
classSinglyLinkedList: def __init__(self, head): self.head= head
El método que cuenta los elementos de la lista, length(), primero comprueba que la lista no esté vacía, y luego recorre todos los elementos de la lista incrementando un contador por cada elemento. Al final devuelve el contador:
def length(self)-> int: current = self.headif current is not None: count =1while current.next is not None: count +=1 current = current.nextreturn count
else:return0
El siguiente método, insert(datos, posición), inserta un elemento tras la posición indicada. Si se indica la posición 0, el nuevo elemento pasa a ser la cabecera de la lista. En esta implementación, si la posición que se pasa como argumento excede el tamaño de la lista,el elemento se inserta al final:
def insert(self, data, position): new_node =Node(data)if position ==0: new_node.next= linked_list.head linked_list.head= new_node
else: current = linked_list.head k =1while current.next is not None and k < position: current = current.next k +=1 new_node.next= current.next current.next= new_node
El método delete(posición) borra el elemento en la posición pasada como parámetro. Si es el primer elemento la lista de la cabeza pasa a ser el segundo elemento. Si se encuentra el elemento en la lista y se borra devolvemos True, en caso contrario devolvemos False:
def delete(self, position):if position !=1: current = self.head k =1while current.next is not None and k < position -1: current = current.next k +=1if current.next is not None: current.next= current.next.nextreturnTrueelse:returnFalseelse: self.head= self.head.nextreturnTrue
Creamos la lista
linked_list =SinglyLinkedList(Node(1))
Rellenamos la lista
for i inrange(2,10): linked_list.insert(i, i-1)
Insertamos un elemento
linked_list.insert(999,3)
Eliminamos un elemento
linked_list.delete(6)
Mostramos la lista
current = linked_list.headwhile current is not None:print(current.data) current = current.next
Sinceramente entendí poco y nada. Todas las clases desde Array se las ha saltado sin explicaciones de como funciona cada cosa dejándonos a la deriva. Espero que no sea así en el futuro.
Efectivamente, se nota que sabe mucho pero no siempre significa que sepa enseñar, en Youtube debes complementar estos temas.
Solución
# Reto array =[2,4,6] datos =SinglyLinkedList()for i inarray: datos.append(i) current = datos.tailwhilecurrent:print(current.data) current = current.next
Excelente
Acá mismo abandono el curso, la explicación del profesor no se alinea para NADA con la ruta de aprendizaje que sugieren en "Desarrollo Backend con Python". Una lástima
Literalmente pienso lo mismo
comonme gustaría desertar pero ocupo aprender esto para poder pasar mibreto de 21 días de Python pero no entiendo nada
Metodo delete gráficamente:
Gracias, me ayudó bastante a entender que fue lo que se hizo.
Creo que pasa mucho en varias clases de los cursos que los profesores o saben exactamente como explicar un tema que solo van tirando código como locos si explicar de forma entendible que va haciendo cada línea, y creo que este es el caso de esta clase
from node importNodeclassLinkedList: def __init__(self): self.head=None def insert_at_begining(self, data): node=Node(data,self.head) self.head=node
def insert_at_end(self, data): #caso de que sea el primero
if self.head is None: self.head=Node(data,None)return itr =self.headwhile itr.next: itr=itr.next itr.next=Node(data,None) #de una Lista a una LinkedList def insert_value_from_list(self, data_list): self.head=Nonefor data indata_list: self.insert_at_end(data)def print(self):if self.head is None:print("Linked list is empty")return itr=self.head llstr=''whileitr: llstr+=str(itr.data)+'-->' itr =itr.nextprint(llstr)if __name__=="__main__": ll=LinkedList() ll.insert_value_from_list(["banana","mango","fresa"]) ll.print()
esta en lo cierto GERMAN GARCIA, no hay error en el codigo del profe, efectivamente se logra eliminar el elemento ingresado tanto al principio, final o entre ellos.
classNode:def__init__(self, data,next=None): self.data = data
self.next=nextdef__repr__(self):ifisinstance(self.next, Node):returnf"<Node({self.data}) {hex(id(self))}> -> Node({self.next.data})"else:returnf"<Node({self.data}) {hex(id(self))}> -> {self.next}"classSinglyLinkedList:def__init__(self): self.tail:Node|None=None self.size =0def__str__(self): result =""for item in self.iter(): result +=f"{item} -> " result +=f"None"return result
defappend(self, data): node = Node(data)if self.tail ==None: self.tail = node
else: current = self.tail
while current.next: current = current.next current.next= node
self.size +=1defsize(self):returnstr(self.size)defiter(self): current = self.tail
while current: val = current.data
current = current.nextyield val
defdelete(self, data): state =False current = self.tail
previous = self.tail
while current:if current.data == data: state =Trueif current == self.tail: self.tail = current.nextelse: previous.next= current.next self.size -=1 previous = current
current = current.nextreturn state
defsearch(self, data):for node in self.iter():if data == node:returnTruereturnFalsedefempty(self): self.tail =None self.head =None self.size =0
Hola, creo que la función "Delete" del profesor está mala. Me corrigen si estoy equivocado pero creo que la forma correcta es la siguiente:
def delete(self, data):
current = self.tail prev =current
whilecurrent:if current.data== data:if current == self.tail: self.tail= current.nextelse: prev.next= current.next current = current.next self.size-=1return current.dataelse: prev = current
current = current.next
Estas en lo cierto, cuando llamo al metodo delete no borra nada, por otra parte tu modificacion del codigo es buena a excepcion del ultimo valor de la lista el cual no lo borra.
Es cierto no lo borra tal cual, pero lo que hace es simplemente cortar las referencias al nodo en particular, ya no podemos encontrarlo porque cambiamos el puntero, es decir, queda aislado.
Pues logré hacer que mostrará el mensaje cuando no encuentra un dato. Además logré implementar head & tail en esta lista:
from node importNodeclassSinglyLinkedList: def __init__(self): self.head=None self.tail=None self.size=0 def append(self, data): node =Node(data)if self.tail==None and self.head==None: self.head= node
self.tail= node
else: current = self.tailwhile current.next: current = current.next current.next= node
self.tail= current.next self.size+=1 def size(self):returnstr(self.size) def iter(self): current = self.tailwhilecurrent: value = current.data current = current.nextyield value #*Genera valores pero NO los almacena
def delete(self, data): current = self.tail previous = self.tailwhilecurrent:if current.data== data:if current == self.tail: self.tail= current.nextelse: previous.next= current.next self.size-=1return current.data previous = current
current = current.next def search(self, data): flag =Falsefor node in self.iter():if data == node: flag =Trueprint(f'Data {data} found 😎')if not flag:print(f'Data {data} not found 😞') def clear(self): self.tail=None self.head=None self.size=0games =SinglyLinkedList()games.append('GTA V')print(f'head: {games.head.data} & tail: {games.tail.data}')games.append('Fifa')print(f'head: {games.head.data} & tail: {games.tail.data}')games.append('Mario')print(f'head: {games.head.data} & tail: {games.tail.data}')
Fue muy listo de tu parte crear esa variable flag para mostrar cuando no se encuentra un elemento.
NO deberíamos depender de los aportes de los compañeros para poder entender todas las clases, realmente es un desastre la pedagogía del profesor Héctor Vega.
pesima clase, no explica nada , primero debe explicar de modo grafico que se quiere hacer , empieza a hacer código sin explicar nada
Que hace el siguiente statement?
while current.next: current = current.next
Mientras Exista un next actualizo current con el next. Va a dejar de hacerlo cuando el current no posea un next.
.
El tener una lista linkeada, te permite saber si hay un siguiente, por lo tanto si queres recorrerla, podes preguntar esa condición; ya que el último no tendrá un siguiente y por lo tanto ya estas en el final de tu lista.
Hola amigo, yo también no me quedaban del todo claro estas lineas(no le encontraba el motivo) porque yo pensaba que el currentalmacenaba el ultimo nodo de la lista. Pero me apoye en el debug de VisualStudioCode y ya vi que cada vez que llamamos a la función append el current se sitúa en el primer nodo de la lista y ahí se activa ese while en donde va recorriendo el current hasta llegar al nodo que tiene next = None, entonces sale del while y le asigna:
current.next= node
Lo siento trato de explicar lo más claro que puedo pero es muy difícil, te invito a que uses el debug de VSCode para que veas como funciona linea por linea del código y veas que valores van agarrando las variables.
Les comparto una imagen que lo explica de forma grafica como es la secuencia en la lista

Hice un método importando la clase array de las clases anteriores