Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Pila: Una pila representa una estructura lineal de datos en la que se puede agregar o quitar
elementos únicamente por uno de los dos extremos.
Utiliza la estructura lifo, el primer elemento que entra, es el último en salir, de la pila solo
podemos acceder al tope, al último elemento que se agregó, no podemos acceder otro lugar
que no sea el tope.
TAD <Pila>
Igualdad Observacional
Si a y b son dos pilas a es igual a b si se cumple que: Las longitudes de a y b son iguales Y
cada elemento en a es igual al correspondiente elemento en b.
Usa
Natural, Bool, Secuencia, None
Parámetro Formal
a
Géneros
Pila <a>
Generadores
vacía () → Pila
{Post: La pila retornada está vacía}
a_partir_de(Secuencia) → Pila
{Post: La pila contiene apilados los elementos de la secuencia recibida}
observadores básicos
Otras Operaciones
apilar (Pila, a) → None
{Post: la pila no está vacía}
desapilar(Pila) → a
{Pre: la pila tiene al menos un elemento}
{Post: la pila perdió el tope que tenía antes de desapilar}
Axiomas
vacía (): Crea una pila (sin elementos)
a_partir_de(Secuencia s): crea una pila que contiene apilados los elementos de la secuencia
s siendo el último elemento de la secuencia el que quede en el tope de la pila.
apilar (Pila p, a elem): apila en el tope de p el elemento elem.
Exporta
Pila, vacía, a_partir_de, es_vacía, tope, tamaño, apilar, desapilar
Lista doblemente enlazada: Una lista doblemente enlazada es una colección de nodos que
se ordena según su posición, tal que cada uno de ellos es accedido mediante el campo de
enlace del nodo anterior o siguiente. La lista doble es homogénea, dinámica, lineal y tiene
acceso secuencial en ambos sentidos.
TAD
ListaDoble <a>
Igualdad Observacional
Si a y b son dos listas dobles a es igual a b si se cumple que: Las longitudes de a y b son
iguales Y cada elemento en a es igual al correspondiente elemento en b.
Usa
Natural, Bool, Secuencia, None, coordenada<ListaDoble<a>>
Parámetro Formal
a
Géneros
ListaDoble <a>
observadores básicos
tamaño(ListaDoble) → Natural
es_vacia(ListaDoble) → Bool
primero(ListaDoble)→ a
{Pre: la lista doble tiene al menos un elemento}
último(ListaDoble)→ a
{Pre: la lista doble tiene al menos un elemento}
Generadores
vacía () → ListaDoble
{Post: La lista doble retornada está vacía}
a_partir_de(Secuencia)→ ListaDoble
{Post: La lista doble contiene los elementos de la secuencia recibida con el mismo orden que
tienen en la secuencia}
Otras Operaciones
agregar_frente(ListaDoble, a) → None
{Post: la Lista Doble tiene al menos un elemento}
agregar_final(ListaDoble, a) → None
{Post: la Lista Doble tiene al menos un elemento}
Otras Operaciones insertar(ListaDoble, coordenada>, a)→None
{Pre: la coordenada es válida}
Axiomas
vacía (): Crea una lista doble (sin elementos)
a_partir_de(Secuencia s): crea una lista doble que contiene los elementos de la secuencia
recibida con el mismo orden que tienen en la secuencia
insertar(ListaDoble l, coordenada<ListaDoble<a>>
c, a elem): agrega elem en l en la posición que hace referencia la coordenada c
borrar(ListaDoble l, coordenada<ListaDoble<a>>
c): borra de la lista l el elemento que se encuentra en la posición que hace referencia c.
Retorna la coordenada siguiente a c.
Exporta
ListaDoble<a>, vacía, a_partir_de, insertar, borrar, tamaño, es_vacía, primero, último,
agregar_frente, agregar_final, inicio, fin
Coordenada
Como esta lista doble tiene coordenadas, esta última tiene su TAD
Toda coordenada debería soporta dos operaciones básicas: Obtener el elemento al que
hace referencia y avanzar al próximo elemento del contenedor
Como estamos especificando una lista doble su coordenada debería ser bidireccional que
además puede retroceder al elemento anterior
Coordenada
TAD
Coordenada <b<a>>
Igualdad Observacional
Si a y b son dos coordenadas a es igual a b si se cumple que: hacen referencia a la misma
posición dentro del mismo contenedor
Usa
Parámetro Formal
b, a
Géneros
Coordenada <b<a>>
observadores básicos
valor (Coordenada <b<a>>) → a
{Pre: La coordenada es válida}
Generadores
a_partir_de(Coordenada <b<a>>) → Coordenada <b<a>>
Otras Operaciones
avanzar (Coordenada <b<a>>) → Coordenada <b<a>>
Axiomas
a_partir_de(Coordenada <b<a>> c): crea una coordenada a partir de la coordenada c
valor (Coordenada <b<a>> c): retorna el valor al que hace referencia la coordenada c}
siguiente (Coordenada <b<a>> c): retorna una nueva coordenada que hace referencia a la
posición siguiente de c.
previo (Coordenada <b<a>> c): retorna una nueva coordenada que hace referencia a la
posición anterior de c.
avanzar (Coordenada <b<a>> c) avanza a la siguiente a c
Ambos métodos devuelven una referencia del elemento, indicando el inicio y el fin de las
mismas, podemos obtener una de estas coordenadas y hacerlas avanzar para por ejemplo
ingresar un elemento en otra posición.
Fin, devuelve una referencia al siguiente del ultimo
El len en la coordenada no tiene sentido, ya que es una dirección de memoria, no contiene
un conjunto de elementos, no corresponde a una coordenada
Otra cosa a tener en cuenta de las coordenadas es que cuando creamos una, esta no se crea
vacía ya que no tiene sentido crear una coordenada que no apunte a nada, no tendría razón
de ser.
La lista doble contiene un nodo escondido, este no tiene dato y representa el fin de la lista
doblemente enlazada, y lo necesito para implementar la coordenada, para poder
referenciar a alguien que sea el siguiente del ultimo
@dataclass
class _Node:
value: Any
prev: '_Node' = None
next: '_Node' = None
@dataclass
class _Head:
prev: '_Node'= None
next: '_Node'= None
Al crear una lista vacía, esta crea un nodo escondido y se inicia apuntándose a sí misma,
indicando que la lista está vacía
def __init__(self, iterable=None):
self._head = DoublyLinkedList._Head ()
def __len__(self):
n=0
nodo = self._head.next
while nodo is not self._head: #corta cuando llega al nodo escondido
n += 1
nodo = nodo.next
return n
def is_empty(self):
return self._head.next is self._head
Este retorna true si el nodo escondido se está auto apuntado, sino false
def front(self):
assert not self.is_empty(), 'lista vacía'
return self._head.next.value ## A menos de que este vacía la lista, devuelve el primer elemento
def back(self):
assert not self.is_empty(), 'lista vacía'
return self._head.prev.value ## A menos de que este vacía la lista, devuelve el último elemento
A partir de ahora los métodos que se van a ver estará relacionados con la clase coordenadas
new_node.prev.next = new_node #engancha el puntero next del nodo escondido en el nuevo nodo
new_node.next.prev = new_node #encgancha el puntero prev del siguiente nodo al nuevo nodo
En este caso el insert va a hacer 4 enganches, en general hace los enganches necesarios
para que ningún nodo quede en el aire
El aprend front inserta antes del primero, este recibe a una coordenada, en este caso begin
que hace referencia al primer elemento y un valor
self.insert(self.end(), value)
def begin(self):
return DoublyLinkedList._Coordinate(self._head.next)
Retorna una referencia al primer elemento
def end(self):
return DoublyLinkedList._Coordinate(self._head)
Hace una referencia al nodo escondido, el fin de la lista doble
Implementación de la coordenada
class _Coordinate:
__slots__ = ['_node']
else:
self._node = coor_or_node #sino asigno el parámetro que me pasan
La coordenada se crea a partir de una referencia que a mí me envían, por ejemplo, end,
que pasa una referencia al nodo cabecera
@property
def value(self):
return self._node.value
Da el valor al que se le está haciendo referencia, osea cuando desreferenciamos
@value. setter
def value(self, value):
self._node.value = value
Desreferenciamos un elemento y asignamos un nuevo valor
Recursión
La pila de activación nos va ayudar a hacer ciertas cosas a la vuelta de la recursión, por
ejemplo, sumar los numero que están es esta pila, o hacer los enganches necesarios, pero si
no le encontramos una utilidad, seria de gusto usar la recursión.
En general para un mismo algoritmo la recursión permite una expresión más clara y sintética
lo que simplifica la comprensión y el mantenimiento. A su vez las soluciones recursivas son
normalmente más costosas en tiempo y memoria (menos eficientes).