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?
Introducción a las estructuras de datos
Python como base de programación
Elementos de la programación en Python
Tipos de colecciones
Operaciones esenciales en colecciones
Colecciones incorporadas en Python
Arrays
Arrays
Crear un array
Arrays de dos dimensiones
Linked lists
Nodos y singly linked list
Crear nodos
Crear singly linked list
Operaciones en single linked structures
Operaciones a detalle
Circular linked list
Double linked list
Stacks
¿Qué son stacks?
Crear un stack
Queues
¿Qué son las queues?
Queue basada en listas
Queue basada en dos stacks
Queue basada en nodos
Reto: simulador de playlist musical
Próximos pasos
Más allá de las estructuras lineales
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Convierte tus certificados en títulos universitarios en USA
Antes: $249
Paga en 4 cuotas sin intereses
Termina en:
Aportes 105
Preguntas 10
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?
Dejo un video que me ayudó a entender el tema del “current” y self.tail
https://www.youtube.com/watch?v=oXuKUkIlv_o
Le falto mejor explicación, creo que solo se agarro hablando y escribiendo.
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?
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:
class Node:
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:
class SinglyLinkedList:
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.head
if current is not None:
count = 1
while current.next is not None:
count += 1
current = current.next
return count
else:
return 0
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 = 1
while 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 = 1
while current.next is not None and k < position - 1:
current = current.next
k += 1
if current.next is not None:
current.next = current.next.next
return True
else:
return False
else:
self.head = self.head.next
return True
Creamos la lista
linked_list = SinglyLinkedList(Node(1))
Rellenamos la lista
for i in range(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.head
while 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.
Solución
# Reto
array = [2, 4, 6]
datos = SinglyLinkedList()
for i in array:
datos.append(i)
current = datos.tail
while current:
print(current.data)
current = current.next
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
Metodo delete gráficamente:
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 import Node
class LinkedList:
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.head
while 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=None
for data in data_list:
self.insert_at_end(data)
def print(self):
if self.head is None:
print("Linked list is empty")
return
itr=self.head
llstr=''
while itr:
llstr+=str(itr.data) + '-->'
itr =itr.next
print(llstr)
if __name__=="__main__":
ll=LinkedList()
ll.insert_value_from_list(["banana","mango","fresa"])
ll.print()
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
while current:
if current.data == data:
if current == self.tail:
self.tail = current.next
else:
prev.next = current.next
current = current.next
self.size -= 1
return current.data
else:
prev = current
current = current.next
Pues logré hacer que mostrará el mensaje cuando no encuentra un dato. Además logré implementar head & tail en esta lista:
from node import Node
class SinglyLinkedList:
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.tail
while current.next:
current = current.next
current.next = node
self.tail = current.next
self.size += 1
def size(self):
return str(self.size)
def iter(self):
current = self.tail
while current:
value = current.data
current = current.next
yield value #* Genera valores pero NO los almacena
def delete(self, data):
current = self.tail
previous = self.tail
while current:
if current.data == data:
if current == self.tail:
self.tail = current.next
else:
previous.next = current.next
self.size -= 1
return current.data
previous = current
current = current.next
def search(self, data):
flag = False
for node in self.iter():
if data == node:
flag = True
print(f'Data {data} found 😎')
if not flag:
print(f'Data {data} not found 😞')
def clear(self):
self.tail = None
self.head = None
self.size = 0
games = 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}')
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
Les comparto una imagen que lo explica de forma grafica como es la secuencia en la lista
![](
Sí alguien le quedo la duda de como ordena la linked list, pues esta usando el algoritmo de ordenamiento de Burbuja, que en big O notation es O(n°2)
Hice un método importando la clase array de las clases anteriores
Y le hice un cambio al metodo search
Otra manera de verlo
class SingleLinkedList:
def __init__(self) -> None:
self.head = Node("head")
self.length = 0
def __iter__(self):
current_node = self.head
while current_node.next:
current_node = current_node.next
yield current_node.data
def append(self, data):
current_node = self.head
while current_node.next:
current_node = current_node.next
current_node.next = Node(data)
self.length += 1
def delete(self, data):
current_node = self.head
while current_node.next:
prev_node = current_node
current_node = current_node.next
if current_node.data == data:
prev_node.next = current_node.next
del current_node
current_node = prev_node
self.length -= 1
def clear(self):
for item in self:
self.delete(item)
def search(self, data):
for node in self:
if node == data:
print(f"found {node}")
def length(self):
return str(self.length)
El zen de python 🐱👤
>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
llamen al metodo size de otra forma, ya que existe un atributo llamado size.
array = ['hola', 'como','estas', '?']
words = SingleLinkedList()
for i in array:
words.append(i)
for item in words.iter():
print(item)
Espero que platzi agregue una clase de generadores, creo que hasta ahora en los cursos que he tomado de python no lo han explicado.
Les recomiendo aprender sobre ellos ya que son muy importantes cuando se van a iterar los datos pero no queremos guardarlos en memoria.
En el método iter de nuestra clase se usa el keyword yield que permite crear un generador.
Si les gusta leer más sobre ellos:
https://wiki.python.org/moin/Generators
https://es.stackoverflow.com/questions/6048/cuál-es-el-funcionamiento-de-yield-en-python/6084
En momentos como este es cuando detesto mi dislexia, me confundí con el reto no se si era hacer que los nodos se comportaran como un array de dos dimensiones o convertir el array de tipo matriz de las clases pasadas a nodos usando un método de conversión, o reconvertir la clase nodo para que fuera una matriz T^T
Bueno aquí mi código
class Nodo:
def __init__(self, valor, siguiente_nodo = None):
self.valor = valor
self.siguiente_nodo = siguiente_nodo
class Lista_nodo:
def __init__(self):
self.limpiar()
def limpiar(self):
self.nodo_actual = None
self.__SEGURO__ = False
self.nodo_tmp = None
self.tam = 0
def append(self,valor):
nodo_nuevo = Nodo(valor)
self.tam += 1
if not self.nodo_actual:
self.nodo_actual = nodo_nuevo
return
nodo_siguiente = self.nodo_actual
while nodo_siguiente.siguiente_nodo:
nodo_siguiente = nodo_siguiente.siguiente_nodo
nodo_siguiente.siguiente_nodo = nodo_nuevo
def index(self,indice):
if not self.tam:
raise AssertionError("Error sin elementos")
def INDEX(INDICE):
if INDICE > self.tam - 1 or INDICE < 0:
raise AssertionError("Error de indice fuera de los limites")
i = 0
nodo = self.nodo_actual
while i != INDICE:
self.nodo_tmp = nodo
nodo = nodo.siguiente_nodo
i += 1
if self.__SEGURO__:
return nodo.siguiente_nodo
return self.nodo_tmp.valor
if indice < 0:
return INDEX(self.tam + indice)
else:
return INDEX(indice)
def pop(self,indice = -1):
self.__SEGURO__ = True
try:
self.nodo_tmp.siguiente_nodo = self.index(indice)
self.tam -= 1
except AssertionError:
raise AssertionError("Indice inexistente")
finally:
self.__SEGURO__ = False
def find(self,valor):
for val , indice in self.iter_items():
if val == valor:
print("valor encontrado")
return indice
print("el valor no existe")
return None
def printing(self,elementos_mostrados_en_fila = 10):
print("|",end="")
salto = elementos_mostrados_en_fila - 1
for val, i in self.iter_items():
if i < salto:
print(f" {val} |",end="")
else:
salto += elementos_mostrados_en_fila - 1
print("")
print("")
def iter(self):
for val, i in self.iter_items():
yield val
def iter_items(self):
nodo_siguiente = self.nodo_actual
if not nodo_siguiente:
return
i = 0
while nodo_siguiente.siguiente_nodo:
val = nodo_siguiente.valor
nodo_siguiente = nodo_siguiente.siguiente_nodo
yield (val, i)
i += 1
yield (nodo_siguiente.valor,i)
def absorver(self, estructura_de_datos):
# Eto... la neta no entendi el reto XD
pass
if __name__ == "__main__":
from random import randint
lista = Lista_nodo()
print("\nmetodo append [ Nodo.append(",end="")
for i in range(1,8):
val = randint(1,20)
print(f"{val},",end="")
lista.append(val)
print(") ]\n")
print("metodo pop [Nodo.pop(\"con o si indice\")]\n")
lista.printing()
i = -2
lista.pop(i)
print(f"Nodo.pop({i})")
lista.printing()
print("\nmetodo index [Nodo.index(int)]\n")
print(f"Nodo[{i}] = {lista.index(i)}")
print("\nmetodo iter [Nodo.iter()]\n")
for val in lista.iter():
print(val,end= ",")
print("\n\nmetodo iter_items [Nodo.iter_items()]\n")
for val, idx in lista.iter_items():
print(f"[{idx}] = {val}",end=" | ")
print("\n\nmetodo find [Nodo.find(\"valor\")]\n")
j = 11
print(f"indice = {lista.find(j)} Nodo.find({j})")
para una mejor comprensión, Bing me ayudo lo admito, porque el profe pff naa solo transcribió y mal porque trunca tail por head confundiendo mas.
use el append method del código, pues al usar el de head entraría en otro orden los nodos, y eso ayuda a entender mejor el porque de las cosas.
me pesa el cerebro jajajajajaja
Les dejo la solucion al reto, hice algunas modificaciones a la rutina para crear un array
class array:
def __init__(self,capacity,fill_value = None):
self.capacity = capacity
self.items =list()
for i in range(capacity):
self.items.append(fill_value)
def __len__(self):
return len(self.items)
def __str__(self) -> str:
return str(self.items)
def __iter__(self):
return iter(self.items)
def __getitem__(self,index):
return str(self.items[index])
def __setitem__(self,index,new_item):
self.items[index] = new_item
def __randomnumbers__(self):
for i in range(self.capacity):
self.__setitem__(i,random.randint(0,9))
return self.items
def __sumelements__(self):
count = 0
for i in range(self.capacity):
count += self.items[i]
return count
#Metodo para insertar elementos por medio del teclado al array
def __insert_elements__(self):
for i in range(self.capacity):
self.__setitem__(i,input("Ingresa un dato: "))
from crear_node import Node
from crear_array import array
class linked_list:
def __init__(self) -> None:
self.tail = None #es none por que es el ultimo nodo
self.size = 0 #0 por que no hay nodos
def __append__(self,data):
node = Node(data) #Entra un dato y con mi clase nodo creo un nodo ocn un valor y un puntoro como none
if self.tail == None:
self.tail = node # si no hay nodos en mi lista voy a decir que mi colo es igual al primer nodo por que no habia nodos
else:
current = self.tail #pero si hay nodo voy decir que mi estado actual es donde esta mi cola
while current.next: #mientras que haya algo que iterar avanzo
current = current.next # como hay algo avanzo a la siguiente posicion de memoria
current.next = node #y eso que avanze ahi coloco mi nuevo nodo bien bonito y aumento en 1 el tamaño de mi lista
self.size += 1
def __size__(self):
return str(self.size)
def __iter__(self):
current = self.tail #me voy al final de mi lista
while current: #mientra que haya algo en current
val = current.data #mi valor actual donde estoy
current = current.next #avanzo a mi siguiente valor
yield val #regeso el valor donde estoy
def __delete__(self,data):
current = self.tail
previous = self.tail
while current:
if current.data == data:
if current == self.tail:
self.tail == current.next
else:
previous.next = current.next
self.size -= 1
return current.data
previous = current
current = current.next
def __search__(self,data):
for node in self.__iter__():
if data == node:
print(f"Data {data} found")
def __clear__(self):
self.tail = None
self.head = None
self.size = 0
if __name__ == '__main__':
# words = linked_list()
# words.__append__("Salmon")
# words.__append__("Atun")
# words.__append__("Queso")
# current = words.tail
# while current:
# print(current.data)
# current = current.next
# print(words.__size__())
# words.__delete__("Queso")
# current = words.tail
# while current:
# print(current.data)
# current = current.next
# print(words.__size__())
# words.__search__("Salmon")
words = array(5)
words.__insert_elements__()
print(words.__str__())
list_of_words = linked_list()
for i in range(words.capacity):
#print(words.__getitem__(i))
list_of_words.__append__(words.__getitem__(i))
current = list_of_words.tail
while current:
print(current.data)
current = current.next
comparto mi version del reto, si hay algun error porfavor me avisan
from array1 import Array
from linked_list import SinglyLinkedList
# RETO
if __name__ == "__main__":
num_array = Array(5)
for i in range(5):
num_array.__setitem__(i,i)
num_linked_list = SinglyLinkedList()
for num in num_array.__iter__():
num_linked_list.append(num)
current = num_linked_list.tail
while current:
print(current.data)
current = current.next
reto:
num = [x for x in range(1, 10)]
for i in num:
my_list.append(i)
implemente mi propio metodo delete que elimina el nodo sin importar el lugar en que se encuentre
Voy a buscar más información acerca de eso, porque la verdad entendí bastante poco.
reto: pasar valores de un array a una linked list
from clase_5_nodos import Node
from clase_6_linked_list import Singly_linked_list
from clase_3_crear_un_array import new_Array
# array de 5 elementos usando la clase new_Array
array = new_Array(5)
# agregar valores
for i in range(1, 6):
array[i - 1] = i
# nuevo Singly_linked_list
linked_list = Singly_linked_list()
# por medio de un ciclo: Transferimos los vals del array a la linked list
for i in range(len(array)):
#agregamos el valor de la iteración a un nuevo nodo usando la ƒ "append_nodes"
linked_list.append_nodes(array[i])
#en otro ciclo, imprimimos sus valores, iteramos usando la ƒ "iter()"
for nodo in linked_list.iter():
print(nodo)
#R: 1,2,3,4,5
from node import Node
class SinglyLinkedList:
def __init__(self):
self.tail = None
self.size = 0
def append(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 += 1
def size(self):
return str(self.size)
def iter(self):
current = self.tail
while current:
val = current.data
current = current.next
yield val
def delete(self, data):
current = self.tail
previous = self.tail
while current:
if current.data == data:
if current == self.tail:
self.tail = current.next
else:
previous.next = current.next
self.size -= 1
return current.data
previous = current
current = current.next
def search(self, data):
for node in self.iter():
if data == node:
print(f"Data {data} found!")
def clear(self):
self.tail = None
self.head = None
self.size = 0
Crea la clase Node que representará un nodo en la lista enlazada. Cada nodo contendrá un dato y una referencia al siguiente nodo.
Nude.py
class Node:
def __init__(self, data):
self.data = data
self.next = None
LinkedList.py
class LinkedList:
def __init__(self):
self.head = None
def add_element(self, data):
new_node = Node(data)
if self.head is None:
self.head = new_node
else:
current = self.head
while current.next is not None:
current = current.next
current.next = new_node
array.py
# Crear el array unidimensional
my_array = [1, 2, 3, 4, 5]
# Crear la lista enlazada
my_list = LinkedList()
# Transferir los datos del array a la lista enlazada
for data in my_array:
my_list.add_element(data)
el codigo lo transcribio mal el profe que ni lo subio a su github. Naaa, toca buscar por otro lado.
Que clase más horrible
esta fue la forma en que realice el reto
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]
numeros = SinglyLinkedList()
for i in nums:
numeros.append(i)
current = numeros.tail
while current:
print(current.data)
current = current.next
Dejo el challenge resuelto 😃 con su output:
"""
Reto:
Crear un array unidimensional.
Tranferir los datos a una linked structure sencilla
"""
from my_array import Array
from linked_list import SinglyLinkedList
# Creo mi Array
my_array = Array(10, 0)
# Imprimo mi array para verificar que esté creado.
# Al imprimir el objeto recurre a su metodo __str__
print(my_array)
print()
# Asigno valores random a mi array:
my_array.__randomitem__()
# Vuelvo a imprimir mi array con valores random
print(my_array)
print()
# Creo mi linked list:
my_linked = SinglyLinkedList()
# Cargo mi linked list con los valores del array:
for value in my_array.__iter__():
my_linked.append(value)
# Imprimo los valores de mi linked list ya cargada:
for value in my_linked.iter():
print(value)
print()
"""
23:36:12 👽 with 🤖 mgobea 🐶 in develop/python/data_structs_python …
➜ python3 challenge_single.py
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[6, 15, 10, 53, 50, 34, 90, 76, 32, 85]
6
15
10
53
50
34
90
76
32
85
"""
Solución para imprimir un mensjae también en el caso donde el nodo buscado no se encuentre en la lista:
def search(self, data):
check = True
for node in self.iter():
if data == node:
check = True
else:
check = False
if check:
print(f"Data: {data} found!")
else:
print(f"{data} not found in the list!")
Pésima clase, el profe habla de un head que no existe, bueno lo deja en None en el metodo clear (es decir le sirve para nada), tocó buscar material adicional para recordar bien este tema que por cierto en su momento lo vi en C que era un poco mas complejo
El reto queda así:
Utilicé la clase Array del reto anterior y la clase SinglyLinkedList de la clase para sacarlo:
La clase Array es:
class Array:
def __init__(self, capacity, fill_value=None):
self.items = list()
for i in range(capacity):
self.items.append(fill_value)
def __len__(self):
return len(self.items)
def __str__(self):
return str(self.items)
def __iter__(self):
return iter(self.items)
def __getitem__(self, index):
return self.items[index]
def __setitem__(self, index, new_item):
self.items[index] = new_item
def __random_fill__(self):
import random
for i in range(len(self.items)):
self.items[i] = random.randint(i + 1, len(self.items))
def __secuence_fill__(self):
for i in range(len(self.items)):
self.items[i] = i + 1
def __custom_sum__(self):
from functools import reduce
return reduce(lambda a, b: a + b, self.items)
La clase SinglyLinkedList es:
from . node import Node
class SinglyLinkedList:
def __init__(self):
self.tail = None
self.size_list = 0
def append(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_list += 1
def size(self):
return self.size_list
def iter(self):
current = self.tail
while current:
val = current.data
current = current.next
yield val
def delete(self, data):
current = self.tail
previous = self.tail
while current:
if current.data == data:
if current == self.tail:
self.tail = current.next
else:
previous.next = current.next
self.size_list -= 1
return current.data
previous = current
current = current.next
def search(self, data):
found = False
for node in self.iter():
if data == node:
print(f"Data {data} found!")
found = True
if not found:
print(f"Data {data} not found!")
def clear(self):
self.tail = None
self.head = None
self.size_list = 0
def show(self):
for node in self.iter():
print(node)
El código del reto:
from linked_lists.linked_list import SinglyLinkedList
from arrays.random_array import Array
if __name__ == '__main__':
numbers = Array(5)
numbers.__random_fill__()
print("The array numbers is: ")
for i in range(numbers.__len__()):
print(numbers[i])
# Transfer data in a single linked list
list_array = SinglyLinkedList()
for number in numbers.__iter__():
list_array.append(number)
# Print the single linked list
print("The single linked list is: \n")
list_array.show()
Hola el metodo delete del profesor esta errado, para este metodo es importante seguir o traquear dos nodos, al que le estamos verificando la data y al anterior, por lo que es mas fácil llevar dos variables. Acá les comparto mi código, que me ha funcionado.
def delete(self, data):
previous = self.tail
current = previous.next
if previous.data == data:
self.tail = current
previous = None
print(f'{data} deleted!')
return
while current and current.data != data:
previous = current
current = current.next
if current is None:
print("Data is not in the list")
return
previous.next = current.next
current = None
self.size -= 1
print(f'{data} deleted!')
return
Recomiendo que Platzi tenga más cursos tratando el tema de las estrucutras de datos de una manera más profunda, explicando el porqué de cada cosa, así se forma un esquema mental lógico de cómo funciona cada estructura.
Me parece que las explicaciones de esta clase — y en general podría decir del curso — son un poco planas. Pueden hacerlo mejor.
Si sienten que necesitan cualquier tipo de documentación alguna vez acerca de estructuras de datos, algoritmos, métodos, funciones, librerías, etc., GeeksforGeeks es una excelente opción.
Links:
Modificación del método search para el caso de uso cuando no exista un nodo con lo que estamos buscando.
.
def search(self, data):
find = False
data_search = None
for node in self.iter():
if node == data:
find = True
data_search = node
break
if find:
print(f"Element {data_search} found in the list")
else:
print(f"Element {data} not found in the list")
Comparto mi solución del reto
from array import Array
from linked_list import SinglyLinkedList
numbers = Array(5)
for counter in range(0,5):
numbers.__setitem__(counter, counter)
linked_list = SinglyLinkedList()
for counter in range(0,5):
linked_list.append(numbers.__getitem__(counter))
for link in linked_list.iter():
print(link)
esta es la solucion al reto:
#Familia(Single Linked List)
family_list = ["Omar", "Liliana", "Santiago", "Mauricio"]
family_array = Array(4, family_list)
familia = SinglyLinkedList()
for member in family_array.__iter__():
familia.append(member)
print(familia.size)
for member in familia.iter():
print(member)
ademas de esto adecue la clase Array para que al introducirse una lista la “Descomponga” y de esta manera se cree rápidamente el Array.
Entonces quedo así:
def __init__(self, capacity, fill_value= None):
self.items = list()
for i in fill_value:
self.items.append(i)
Horrible clase
Puse este metodo en la clase the la lista y usando ese decorador el metodo esta asociado a la clase, no a una instancia de esta. no es necesario crear una linked_list para usar el metodo
# Create array_to_singly_linked_list static method
@staticmethod
def array_to_singly_linked_list(array):
result_linked_list = SinglyLinkedList()
for item in array:
result_linked_list.append(item)
return result_linked_list
'''node.py'''
class Node():
def __init__(self, data, next=None):
self.data = data
self.next = next
def __str__(self):
return str(self.data)
if __name__ == '__main__':
node1 = None
node2 = Node('A', None)
node3 = Node('B', node2)
print(node2.data)
print(node2.next)
print(node3.data)
print(node3.next)
print(node3.next.data)
node1 = Node('C', node3)
print(node1.data)
print(node1.next.data)
head = None
for count in range(1, 5):
head = Node(count, head)
print(f'El objeto Node que quedo referenciada en head es Nodo{head.data}, pero este apunta al Nodo{head.next.data}este a su vez apunta al Nodo{head.next.next.data}, y este ultimo a apunta al Nodo{head.next.next.next.data}')
while head != None:
print(head.data)
head = head.next
node2
'''linked_list.py'''
class SinglyLinkedList:
def __init__(self):
self.tail = None
self.size = 0
def append(self, data):
node = Node(data)
if self.size == 0:
self.tail = node
else:
current = self.tail
while current.next != None:
current = current.next
current.next = node
self.size += 1
return print(f'Se ha añadido el nodo "{node}"')
def size(self):
return str(self.size)
def iter(self):
current = self.tail
while current:
val = current.data
current = current.next
yield val
def delete(self, data):
if self.size ==0:
return False
else:
current = self.tail
previous = self.tail
while current:
if current.data == data:
if current == self.tail:
self.tail = current.next
else:
previous.next = current.next
self.size -= 1
return current.data
previous = current
current = current.next
def search(self, data):
for node in self.iter():
if data == node:
print(f'Data {data} found!')
def clear(self):
self.tail = None
self.head = None
self.size = 0
def __str__(self):
string = '['
current = self.tail
for i in range(self.size):
string += str(current)
if i != self.size - 1:
string += str(', ')
current = current.next
string += ']'
return string
if __name__ == '__main__':
words = SinglyLinkedList()
words.delete('1')
words.append('egg')
words.append('ham')
words.append('spam')
words.delete('ham')
print(words.__str__())
print(words)
current = words.tail
while current:
print(current.data)
current = current.next
a = [word for word in words.iter()]
print(a)
words.search('spam')
words.clear()
while current:
print(current.data)
current = current.next
Algo para resaltar es que la propiedad next está apuntando a un objeto que ya existe en memoria y por tanto expone la dirección de memoria, y no explícitamente a una dirección de memoria.
En este clase explican estructuras de datos, entre ellas la Linked List. Me ayudo a entender mejor como funciona y como implementar algunas de sus propiedades.
CREA ARRAY Y LO PASA A UN LINKED SIMPLE STRUCTURE (EN EL ORDEN DE CREACION)
from c_array import Array
from node import Node
def main():
n = int(input("Ingrese un largo de Array: "))
arr = Array(n)
for i in range(len(arr)):
arr.items[i] = i
print(arr)
head = None
for i in range(len(arr)):
if head == None:
nodo = Node(arr.items[i])
head = nodo
tail = nodo
else:
nodo = Node(arr.items[i])
tail.next = nodo
tail = nodo
nodo = head
while nodo:
print(nodo.data)
nodo = nodo.next
print("--o--")
print("Head", " ", head.data)
print("Tail", " ", tail.data)
if name == ‘main’:
main()
SALUDOS FRIEND…!
Esta fue mi solución al reto :3
from linked_list import SinglyLinkedList
def run():
array = [1, 2, 3, 4, 5]
linkedList = SinglyLinkedList()
for item in array:
linkedList.append(item)
for item in linkedList.iter():
print(item)
if __name__ == '__main__':
run()
Reto. Creo que para practicidad y un mejor entendimiento de la clase, se debe cambiar tail por head (de todas formas dejo mi tarea con base a lo que dejo el profe).
from nodes import Node
from class_array import Array
from random import randint
class singleLinkedList():
def __init__(self):
self.head = None
self.tail = None
self.size = 0
## IMPORTANT: FROM THIS PART, TAIL ACTS LIKE A HEAD
def appe(self, data): #agregar datos desde el tail
new_node = Node(data)
if self.tail == None:
self.tail = new_node #si la lista esta vacía
else:
current = self.tail
while current.next: #forma de recorrer la lista
current = current.next
current.next = new_node #donde esta el 'None' colocar el nuevo nodo
self.size += 1 #aumenta de tamaño la lista
def takeFromArray(self, array=list()):# o una instancia de array
for i in array:
self.appe(i)
def size(self):
return str(self.size)
def iter(self):
current = self.tail
while current:
val = current.data
current = current.next
yield val
def printList(self):
current = self.tail
print('Data in Single Linked List:', end='\n')
while current is not None:
print(current.data, end=" ")
current = current.next
print('')
def delete(self, data):
current = self.tail #current y previous definen los datos que estrán en medio del que se va a eliminar
previous = self.tail
while current:
if current.data == data:
if current == self.tail:
self.tail = current.next #si el dato a eliminar esta de primero
else:
previous.next = current.next
self.size -= 1
return current.data
previous = current
current = current.next
def search(self, data):
count = 0
for node in self.iter():
count += 1
if data == node:
print (f'Data {data} found!')
break
elif count == self.size:
print ('Data not found!')
def clear(self):
self.head = None
self.tail = None
self.size = 0
if __name__ == '__main__':
LL = singleLinkedList()
LL.takeFromArray(Array(5))#o una lista normal
LL.printList()
Tras terminar la clase me parece que self.tail en realidad es self.head ya que esta siempre apunta al primer nodo creado.
Por si alguien más tuvo esa duda al interpretar el código.
Así complementé la función de busqueda, cuando no encuentra el elelemento.
def search(self, data):
for node in self.iter():
if data == node:
print(f'Data {data} found! :D')
break
if data not in self.iter():
print(f'Data {data} not found! :c')
En los archivos de las clases el código de singly linked list no está. En su lugar esta el de la class Node
Este es mi aporte: Asi quedo mi codigo de modo que podemos aplicar todas las demas funciones
from node import Node
class SinglyLinkedList:
def __init__(self):
self.tail = None
self.tamaño = 0
def append(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.tamaño +=1
def insert_value_from_list(self, data_list):
"""Agrega los datos de una lista al LinkedList"""
for data in data_list:
self.append(data)
current = datos.tail
while current:
print(current.data)
current = current.next
def size(self):
print("The size of the LinkedList is:")
return str(self.tamaño)
def iter(self):
current = self.tail
while current:
val = current.data
current = current.next
yield val
def delete(self, data):
current = self.tail
prev =current
while current:
if current.data == data:
if current == self.tail:
self.tail = current.next
else:
prev.next = current.next
self.tamaño -= 1
return print(f"The {current.data} was delete")
else:
prev = current
current = current.next
print(f"The {data} was not found to delete")
def search(self, data):
for node in self.iter():
if data == node:
print(f"The {data} was found!")
def display_list(self):
"""Muestra los datos del LinkedList"""
for node in self.iter():
print(node)
def clear(self):
self.tail = None
self.head = None
self.tamaño = 0
if __name__ == "__main__":
zoo = ["oso","gato","perro","lion"]
datos = SinglyLinkedList()
print("LinkedList...")
datos.insert_value_from_list(zoo)
print("\n")
print("Borrando elemento de la LinkedList (perro)")
datos.delete("perro")
print("Mostrando lo que queda de la LinkedList...\n")
datos.display_list()
Basicamente esto va pasando.
none
Node#1(value, none)
Node#2(value, Node#1(value, none))
Node#3(value, Node#2(value, Node#1(value, none)))
Node#4(value, Node#3(value, Node#2(value, Node#1(value, none))))
con eso mas claro, al inicio lo entendi al reves jajaja
Mi solucion al reto sin añadirlo como un metodo de SinglyLinkedList
def run():
random_int = Array(5)
random_int.__fillRandom__()
print(random_int)
random_int_linked = SinglyLinkedList()
print("Creating the random_int_linked")
for num in random_int.__iter__():
random_int_linked.append(num)
print("Printing all the created nodes in the linked list")
for random in random_int_linked.iter():
print(random)
if __name__ == "__main__":
run()
Resultado en terminal
[0, 7, 10, 2, 10]
Creating the random_int_linked
Printing all the created nodes in the linked list
0
7
10
2
10
Hago mi aporte al reto, usando la clase Array vista en clases anteriores:
from node import Node
from array import Array
class SinglyLinkedList:
def __init__(self):
self.tail = None
self.size = 0
def append(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 += 1
def size(self):
return str(self.size)
def iter(self):
current = self.tail
while current:
val = current.data
current = current.next
yield val
def delete(self, data):
current = self.tail
previous = self.tail
while current:
if current.data == data:
if current == self.tail:
self.tail = current.next
else:
previous.next = current.next
self.size -= 1
return current.data
previous = current
current = current.next
def search(self, data):
for node in self.iter():
if data == node:
print(f'Data {data} found!')
def turn_array_to_linked_list(self):
# Método para pasar un array a lista enlazada
array_numbers = Array(5)
array_numbers.__addrandomitems__()
# imprimir el array para observar los números generados de forma aleatoria
print(array_numbers)
for number in array_numbers:
self.append(number)
def clear(self):
self.tail = None
self.head = None
self.size = 0
🚩🚩🚩🚩🚩🚩
Es mucho más “cómodo” y “simple” manejar un 3er atributo en la clase => head
Mi solución al reto:
from my_array import Array
from linked_list import SinglyLinkedList
def main():
new_array = Array(5)
new_array.set_values(80,13)
linked_list = SinglyLinkedList()
for i in new_array.__iter__():
linked_list.append(i)
print(new_array)
for i in linked_list.iter():
print(i)
if __name__ == '__main__':
main()
https://www.youtube.com/watch?v=oXuKUkIlv_o en este video de youtube pude comprender un poco mejor y de forma mas gráfica la singly linked list
Solucion al reto
from Arrays.arrays import Array
from linked_lists.singly_list import SinglyLinkedList as SLL
def run():
array = Array(10)
list = SLL()
array.rand_fill(20, 1000)
for i in array:
list.append(i)
print(list)
if __name__ == '__main__':
run()
Output:
465, 546, 294, 172, 308, 561, 252, 83, 185, 482
Process finished with exit code 0
Hay un error en el metodo delete y es que si elimina el elemento de la cabeza de la lista no retorna ningun valor y tampoco disminuye el tamaño de la lista lo correcto seria de la siguiente forma
while current is not None:
if current.data == instance:
if current == self.head:
self.head = current.next
else:
previous.next = current.next
self.size -= 1
return current.data
previous = current
current = current.next
from array import Array
from linked_list import SinglyLinkedList
if __name__ == '__main__':
mi_array = Array(5)
mi_array.__fillrandom__()
print(mi_array)
mi_linked_list = SinglyLinkedList()
for i in range(mi_array.__len__()):
mi_linked_list.append(mi_array.__getitem__(i))
for item in mi_linked_list.iter():
print(item)
Espero les ayude.
Reto:
from arreglo import Arreglo
from node import Node
from linked_list import SinglyLinkedList
size = 5
#.__replaceitems__() Función para replazar los valores del arreglo por numeros aleatorios
lista = Arreglo(size).__replaceitems__()
print(lista)
nodes = SinglyLinkedList()
for i in range(size):
nodes.append(data=lista[i])
current = nodes.tail
while current:
print(current.data)
current = current.next
Salida:
[80, 37, 49, 80, 52]
80
37
49
80
Reto:
from MiArray import Array
from linked_list import SinglyLinkedList
def run():
array = Array(6)
array.__populate__(0, 100)
print(array)
node = SinglyLinkedList()
for data in array.__iter__():
node.append(data)
del array
current = node.tail
while current:
print(current.data)
current = current.next
if __name__ == '__main__':
run()
Anotación: el metodo setvalues se creo en el reto de llenar el array con numeros random
from Array import Array
from linked_list import SinglyLinkedList
list = Array(5)
list.__setvalues__()
print(list.__str__())
data = SinglyLinkedList()
for i in list:
data.append(i)
current = data.tail
while current:
print(current.data)
current = current.next
pienso que me gustaría que las armara desde el principio y no utilizara cosas ya hechas, ya se que no hay que reinventar la rueda, pero me siento incompleto, alguien tiene material para complementar?
Agregar por indice:
Borrar un dato segun su indice:
Una forma para insertar data desde atras:
Les comparto mi segunda versión del reto, después de un tiempo de dejar abandonado el curso 😅
Hice los features para que la linked list pueda manipularse bajo las mismas características de un list.
from linked_list import SinglyLinkedList
# Se puede crear una linked list apartir de list, set o tuple.
singly_linked_list = SinglyLinkedList([1, 2, 3, 4, 5]) # 1 -> 2 -> 3 -> 4 -> 5
# Podemos acceder a los elementos de la linked list a traves de sus indices.
linked_list_slice = singly_linked_list[0:-2] # 1 -> 2 -> 3 -> 4
print(singly_linked_list[3]) # 4
for item in singly_linked_list[::2]:
print(item) # 1 -> 3 -> 5
# Comparación de listas
linked_list_2 = SinglyLinkedList(1, 2, 3, 4)
print(singly_linked_list == linked_list_2) # False
print(singly_linked_list >= linked_list_2) # True
print(singly_linked_list <= linked_list_2) # False
print(singly_linked_list > linked_list_2) # True
print(singly_linked_list < linked_list_2) # False
from pdb import set_trace
from typing import Any
from typing import Optional
from typing import Iterator
from typing import Union
from node import Node
class SinglyLinkedList:
"""Singly Linked List"""
_tail: Optional[Node]
_size: int
def __init__(self, *items) -> None:
"""Initialize an empty list
Args:
*items: Items to be added to the list.
"""
self._head = None
self._size = 0
if len(items) == 1 and isinstance(items[0], (list, tuple, set)):
items = items[0]
for item in items:
self.append(item)
def append(self, value: Any):
"""Appends a new value at the end of the list.
Time complexity: O(n) where n is the length of the nodes.
"""
node = Node(value)
if self._head is None:
self._head = node
else:
pointer = self._head
while pointer.next is not None:
pointer = pointer.next
pointer.next = node
self._size += 1
@property
def size(self):
"""Returns the size of the linked list.
Time complexity: O(1)
"""
return self._size
def delete(self, target: object):
"""Deletes an item from the list.
Time complexity: O(n)
"""
current = self._head
previous = current
while current is not None:
if current.value == target:
if current == self._head:
self._head = current.next
else:
previous.next = current.next
self.size -= 1
break
previous = current
current = current.next
def search(self, target: object) -> bool:
"""Check if the provided value is in the list.
Time complexity: O(n) where n is the length of the nodes.
Args:
target: Value to be searched inside the list.
Returns:
bool: True if found. False otherwise.
"""
return target in self
def clear(self):
"""Clears the list.
Removes all the items inside the list.
"""
self._head = None
self.size = 0
def __len__(self):
"""Returns the size of the linked list when using the built-in function len."""
return self._size
def __iter__(self) -> Iterator[Node]:
"""Allows to iterate over the list using a generator.
Time complexity: O(n)
"""
if self._head is not None:
pointer = self._head
while pointer is not None:
val = pointer
pointer = pointer.next
yield val
return None
def __contains__(self, target: object) -> bool:
"""Check if a value is in the list when using the 'in' operator.
Time complexity: O(n) where n is the length of the nodes.
"""
output = False
pointer = self._head
while pointer is not None and pointer.value != target and pointer.next is not None:
pointer = pointer.next
if pointer is not None and pointer.value == target:
return target
return output
def __reversed__(self) -> Iterator[Node]:
"""Returns a new instance of the linked list but reversed when using the 'reversed' built-in function.
Time complexity: O(n) where n is the length of the nodes.
"""
new_list = SinglyLinkedList()
if self._head is not None:
current_node: None = self._head
remaining_values: Optional[Node] = self._head.next
# Set the head next value to None beacuse now it will be the tail
current_node.next = None
while remaining_values is not None:
temp_ref = current_node
current_node: Node = remaining_values
remaining_values = current_node.next
current_node.next = temp_ref
new_list._head = current_node
return new_list
def __getitem__(self, index: Union[int, slice]):
"""Get item with the index or slice from the linked list.
Time Complexity: O(n) where n is the length of the nodes.
Returns:
Any: Item with the index or slice.
"""
if isinstance(index, slice):
items = list(self)[index]
new_list = SinglyLinkedList(items)
return new_list
if index > self.size - 1:
raise IndexError('Index out of range')
if index < 0:
index = self._size + index
for idx, value in enumerate(self):
if index == idx:
return value
return None
def __lt__(self, other: 'SinglyLinkedList') -> bool:
"""Check if the list is less than the other list.
Time Complexity: O(n) where n is the length of the nodes of the list with less nodes.
Args:
other (SinglyLinkedList): Other list to be compared.
Returns:
bool: True if the list is equals to the other list. False otherwise.
"""
if self.size >= other.size:
return False
for self_item, other_item in zip(self, other):
if self_item.value != other_item.value:
return False
return True
def __le__(self, other: 'SinglyLinkedList') -> bool:
"""Check if the list is less than or equals to the other list.
Time Complexity: O(n) where n is the length of the nodes of the list with less nodes.
Args:
other (SinglyLinkedList): Other list to be compared.
Returns:
bool: True if the list is equals to the other list. False otherwise.
"""
if self.size > other.size:
return False
for self_item, other_item in zip(self, other):
if self_item.value != other_item.value:
return False
return True
def __eq__(self, other: 'SinglyLinkedList') -> bool:
"""Check if the list is equal to the other list.
Time Complexity: O(n) where n is the length of the nodes of the list with less nodes.
Args:
other (SinglyLinkedList): Other list to be compared.
Returns:
bool: True if the list is equals to the other list. False otherwise.
"""
if self._size != other.size:
return False
for self_item, other_item in zip(self, other):
if self_item.value != other_item.value:
return False
return True
def __ge__(self, other: 'SinglyLinkedList') -> bool:
"""
Check if the list is greater or equal than the other list.
Time Complexity: O(n) where n is the length of the nodes of the list with less nodes.
Args:
other (SinglyLinkedList): Other list to be compared.
Returns:
bool: True if the list is greater or equal than the other list. False otherwise.
"""
if self._size < other._size:
return False
for self_item, other_item in zip(self, other):
if self_item.value != other_item.value:
return False
return True
def __gt__(self, other: 'SinglyLinkedList') -> bool:
"""
Check if the list is greater than the other list.
Time Complexity: O(n) where n is the length of the nodes of the list with less nodes.
Args:
other (SinglyLinkedList): Other list to be compared.
Returns:
bool: True if the list is greater than the other list. False otherwise.
"""
if self.size <= other.size:
return False
for self_item, other_item in zip(self, other):
if self_item.value != other_item.value:
return False
return True
Propuesta anterior: https://platzi.com/comentario/2616441/
Reto…
from linkedList import SinglyLinkedList
from customArray import Array
def arrayToList(array: Array) -> SinglyLinkedList:
linkedList = SinglyLinkedList()
for item in iter(array):
linkedList.append(item)
return linkedList
def run():
array = Array(10) #Crates an Array object
array.randomitems(0,10) # Fill the array with random int numbers between 0 ans 10
print(str(array)) # Prints the str format representation of the array
numbers = arrayToList(array) #Turn the array into a SinglyLinkedList
numbers.str() # Print the str format representation of the SinglyLinkedList
if __name__=="__main__":
run()
Implementación del método str de la clase SinlyLinkedList
def str(self):
current = self.tail
items = ""
while current:
items += str(current.data) + " "
current = current.next
print(items)
Implementación de caso de uso para def search(self, data)
Para en caso de no encontrar el elemnto.
def search(self, data):
found=False
for node in self.iter():
if data == node:
print(f'Data: "{data}" found!')
found = True
if found==False:
print(f'Sorry...Data: "{data}" NOT found!')
Reto:
# Reto
print("RETO")
values = [i for i in range(1, 15)]
values = [Node(i) for i in values]
numbers = SingleLinkedList()
for value in values:
numbers.append(value.data)
for number in numbers.iter():
print(number)
print(f"size {numbers.list_size()=}")
print(numbers.search(5))
print(numbers.search("potato"))
Una buena forma de usar un format-string para ver los datos es:
data = 'spam'
print(f"{data=} found)
# imprime
data='spam' found
Mi implementación:
Mi código de la clase, hice algunas cosas ligeramente distintas:
from node import Node
class SingleLinkedList:
"""Create a Single Linked List """
def __init__(self):
"""Initialize a single linked list"""
self.head = None
self.tail = None
self.size = 0
def append(self, data):
"""Add a new node to the end of the list"""
new_node = Node(data)
if self.head is None:
self.head = new_node
self.tail = new_node
else:
self.tail.next = new_node
self.tail = new_node
self.size += 1
def size(self):
"""Return the size of the list"""
return str(self.size)
def iter(self):
"""Iterate over the list"""
current = self.head
while current:
yield current
current = current.next
def delete(self, data):
"""Delete a node from the list"""
current = self.head
previous = None
found = False
while current and found is False:
if current.data == data:
found = True
else:
previous = current
current = current.next
if current is None:
raise ValueError("Data not in list")
if previous is None:
self.head = current.next
else:
previous.next = current.next
self.size -= 1
def search(self, data):
"""Search for a node in the list"""
current = self.head
found = False
while current and found is False:
if current.data == data:
print(f'Data {data} was found')
found = True
else:
current = current.next
if current is None:
raise ValueError("Data not in list")
return current
def clear(self):
"""Clear the list"""
self.head = None
self.tail = None
self.size = 0
if __name__ == '__main__':
sll = SingleLinkedList()
sll.append(1)
sll.append('hey')
sll.append(3.14)
sll.append('Hola')
current = sll.tail
for node in sll.iter():
print(node.data)
print(sll.size)
sll.search('hey').data
sll.search('545').data
Aqui cumpliendo con el reto
mi version de search
def search(self, data):
result = 'not found'
for node in self.iter():
if data == node:
result = 'found'
print(f'Data {data} {result}!!')
Mi solución al reto:
.
.
Les comparto mi solución del problema, traté de hacer las mejores soluciones que se me ocurrieron al momento basado en la teoría de la complejidad computacional.
PD: El método de delete no me termina de gustar, me gustaría saber si tienen alguna sugerencia
class Node:
def __init__(self, value, next = None) -> None:
self.value = value
self.next = next
class SinglyLinkedList:
"""Singly Llinked list."""
def __init__(self) -> None:
"""Initalize the linked list.
Time complexity: O(1)
"""
self._head = None
self._tail = None
self._size = 0
@property
def size(self):
return self._size
def append(self, value):
"""Adds a new item to the current linked list instance.
Time complexity: O(1)
"""
node = Node(value)
if self._head is None:
self._head = node
elif self._tail is None:
self._tail = Node(value)
self._head.next = self._tail
else:
self._tail.next = Node(value)
self._tail = self._tail.next
self._size += 1
def iter(self):
"""Returns an iterator object of the current instance.
Time complexity: O(n)
"""
currentRef = self._head
while currentRef is not None:
value = currentRef.value
currentRef = currentRef.next
yield value
def __iter__(self):
"""Returns an iterator object.
Time complexity: O(n)
"""
return self.iter()
def delete(self, data):
"""Removes the node that matches with the provided data.
Time complexity: O(n)
"""
deleted = False
currentRef = self._head
previousRef = None
while currentRef is not None:
if currentRef.value == data:
if previousRef is not None:
previousRef.next = currentRef.next
else:
self._head = currentRef.next
deleted = True
self._size -= 1
break
previousRef = currentRef
currentRef = currentRef.next
# Find the new tail
currentRef = self._head
while currentRef is not None and currentRef.next is not None:
currentRef = currentRef.next
self._tail = currentRef
return deleted
def search(self, value) -> bool:
"""Returns True if the provided value is found in the current linked list instance.
Time complexity: O(n)
"""
result = False
for item in self:
if item == value:
result = True
break
return result
def clear(self):
"""Resets the current linked list instance.
Time complexity: O(1)
"""
self._size = 0
self._head = None
self._tail = None
@staticmethod
def from_array(source: list):
"""Creates a new instance of a singly linked list from a simple python list.
Time complexity: O(n)
"""
_list = SinglyLinkedList()
for item in source:
_list.append(item)
return _list
def __str__(self) -> str:
return repr(list(self))
def __repr__(self) -> str:
return str(self)
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?