Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Especificaciones algebraicas completas 1

Universidad Nacional de Rio Negro - Sede Andina

Especificaciones Algebraicas completas para secuencias

Objetivos observables

Este capítulo cataloga las especificaciones algebraicas rigurosas de las estructuras de datos más utilizadas en programación. Cada especificación integra:

Estas especificaciones son implementación-agnósticas: funcionan con arrays dinámicos, listas enlazadas, o cualquier representación que respete los axiomas.


TDA Array (Arreglo)

Un arreglo es una secuencia estática de elementos de igual tipo, accesibles mediante índices enteros en rango [0,n)[0, n) donde nn es el tamaño.

Sorts y Signatura

Sorts:Array,Element,Bool,NGeneradores:empty:Arraycreate:NArray(crea arreglo de taman˜o fijo)Modificadores:set:Array×N×ElementArrayObservadores:get:Array×NElementlength:ArrayNeq:Array×ArrayBool\begin{align} \text{Sorts:} \quad & \mathtt{Array}, \mathtt{Element}, \mathtt{Bool}, \mathbb{N} \\ \\ \text{Generadores:} \\ \quad & \text{empty} : \to \mathtt{Array} \\ \quad & \text{create} : \mathbb{N} \to \mathtt{Array} \quad \text{(crea arreglo de tamaño fijo)} \\ \\ \text{Modificadores:} \\ \quad & \text{set} : \mathtt{Array} \times \mathbb{N} \times \mathtt{Element} \to \mathtt{Array} \\ \\ \text{Observadores:} \\ \quad & \text{get} : \mathtt{Array} \times \mathbb{N} \to \mathtt{Element} \\ \quad & \text{length} : \mathtt{Array} \to \mathbb{N} \\ \quad & \text{eq} : \mathtt{Array} \times \mathtt{Array} \to \mathtt{Bool} \end{align}

Axiomas

Axioma 1 (length de empty):

length(empty)=0\text{length}(\text{empty}) = 0

Axioma 2 (length de create):

length(create(n))=nnN\text{length}(\text{create}(n)) = n \quad \forall n \in \mathbb{N}

Axioma 3 (get de set con índice coincidente):

get(set(a,i,v),i)=va,i,v\text{get}(\text{set}(a, i, v), i) = v \quad \forall a, i, v

Axioma 4 (get de set con índice distinto):

ij    get(set(a,i,v),j)=get(a,j)i \neq j \implies \text{get}(\text{set}(a, i, v), j) = \text{get}(a, j)

Axioma 5 (igualdad de arreglos):

eq(a1,a2)=true    length(a1)=length(a2)i<length(a1),get(a1,i)=get(a2,i)\text{eq}(a_1, a_2) = \text{true} \iff \text{length}(a_1) = \text{length}(a_2) \land \forall i < \text{length}(a_1), \text{get}(a_1, i) = \text{get}(a_2, i)

Invariante

I(Array):a,  length(a)0i,  0i<length(a)I(\text{Array}) : \forall a, \; \text{length}(a) \geq 0 \land \forall i, \; 0 \leq i < \text{length}(a)

El tamaño es siempre no negativo y los índices válidos están en rango.

Contratos

OperaciónPrecondiciónPostcondiciónComplejidad
create(n)ningunalength(result)=n\text{length}(\text{result}) = nO(n)O(n) tiempo, O(n)O(n) espacio
set(a, i, v)0i<length(a)0 \leq i < \text{length}(a)get(result,i)=v\text{get}(\text{result}, i) = vO(1)O(1) tiempo, O(1)O(1) espacio
get(a, i)0i<length(a)0 \leq i < \text{length}(a)devuelve elemento en posición iiO(1)O(1) tiempo, O(1)O(1) espacio

TDA Stack (Pila)

Una pila es una secuencia dinámica LIFO (last-in, first-out). Solo el elemento superior es accesible.

Sorts y Signatura

Sorts:Stack,Element,BoolGeneradores:empty:StackModificadores:push:Stack×ElementStackpop:StackStackObservadores:top:StackElementisEmpty:StackBoolsize:StackN\begin{align} \text{Sorts:} \quad & \mathtt{Stack}, \mathtt{Element}, \mathtt{Bool} \\ \\ \text{Generadores:} \\ \quad & \text{empty} : \to \mathtt{Stack} \\ \\ \text{Modificadores:} \\ \quad & \text{push} : \mathtt{Stack} \times \mathtt{Element} \to \mathtt{Stack} \\ \quad & \text{pop} : \mathtt{Stack} \to \mathtt{Stack} \\ \\ \text{Observadores:} \\ \quad & \text{top} : \mathtt{Stack} \to \mathtt{Element} \\ \quad & \text{isEmpty} : \mathtt{Stack} \to \mathtt{Bool} \\ \quad & \text{size} : \mathtt{Stack} \to \mathbb{N} \end{align}

Axiomas

Axioma 1 (pop de vacía):

pop(empty)=empty\text{pop}(\text{empty}) = \text{empty}

Axioma 2 (size vacía):

size(empty)=0\text{size}(\text{empty}) = 0

Axioma 3 (isEmpty vacía):

isEmpty(empty)=true\text{isEmpty}(\text{empty}) = \text{true}

Axioma 4 (pop de push):

pop(push(s,e))=ssStack,eElement\text{pop}(\text{push}(s, e)) = s \quad \forall s \in \mathtt{Stack}, e \in \mathtt{Element}

Axioma 5 (top de push):

top(push(s,e))=e\text{top}(\text{push}(s, e)) = e

Axioma 6 (isEmpty de push):

isEmpty(push(s,e))=false\text{isEmpty}(\text{push}(s, e)) = \text{false}

Axioma 7 (size de push):

size(push(s,e))=size(s)+1\text{size}(\text{push}(s, e)) = \text{size}(s) + 1

Invariante

I(Stack):s,  size(s)0(isEmpty(s)=true    size(s)=0)I(\text{Stack}) : \forall s, \; \text{size}(s) \geq 0 \land (\text{isEmpty}(s) = \text{true} \iff \text{size}(s) = 0)

El tamaño es no negativo y vacío es equivalente a tamaño cero.

Contratos

OperaciónPrecondiciónPostcondiciónComplejidad
push(s, e)ningunatop(result)=eisEmpty(result)=false\text{top}(\text{result}) = e \land \text{isEmpty}(\text{result}) = \text{false}O(1)O(1) amortizado tiempo, O(1)O(1) amortizado espacio
pop(s)ninguna (falla gracefully si vacía)si isEmpty(s)=true\text{isEmpty}(s) = \text{true}, resultado = empty; sino, top se restauraO(1)O(1) amortizado tiempo, O(1)O(1) amortizado espacio
top(s)isEmpty(s)=false\text{isEmpty}(s) = \text{false}devuelve elemento más recienteO(1)O(1) tiempo, O(1)O(1) espacio

TDA Queue (Cola)

Una cola es una secuencia dinámica FIFO (first-in, first-out). Se agregan elementos al final; se retiran del frente.

Sorts y Signatura

Sorts:Queue,Element,BoolGeneradores:empty:QueueModificadores:enqueue:Queue×ElementQueuedequeue:QueueQueueObservadores:front:QueueElementisEmpty:QueueBoolsize:QueueN\begin{align} \text{Sorts:} \quad & \mathtt{Queue}, \mathtt{Element}, \mathtt{Bool} \\ \\ \text{Generadores:} \\ \quad & \text{empty} : \to \mathtt{Queue} \\ \\ \text{Modificadores:} \\ \quad & \text{enqueue} : \mathtt{Queue} \times \mathtt{Element} \to \mathtt{Queue} \\ \quad & \text{dequeue} : \mathtt{Queue} \to \mathtt{Queue} \\ \\ \text{Observadores:} \\ \quad & \text{front} : \mathtt{Queue} \to \mathtt{Element} \\ \quad & \text{isEmpty} : \mathtt{Queue} \to \mathtt{Bool} \\ \quad & \text{size} : \mathtt{Queue} \to \mathbb{N} \end{align}

Axiomas

Axioma 1 (dequeue de vacía):

dequeue(empty)=empty\text{dequeue}(\text{empty}) = \text{empty}

Axioma 2 (isEmpty vacía):

isEmpty(empty)=true\text{isEmpty}(\text{empty}) = \text{true}

Axioma 3 (enqueue-dequeue FIFO):

front(enqueue(empty,e))=e\text{front}(\text{enqueue}(\text{empty}, e)) = e

Axioma 4 (dequeue preserva frente): Si la cola tiene múltiples elementos, dequeue lo retira:

dequeue(enqueue(q,enuevo))=qsi isEmpty(q)=false\text{dequeue}(\text{enqueue}(q, e_{\text{nuevo}})) = q \quad \text{si } \text{isEmpty}(q) = \text{false}

Axioma 5 (dequeue-enqueue conmutan casi):

dequeue(enqueue(q,e1))=enqueue(dequeue(q),e1)si isEmpty(q)=false\text{dequeue}(\text{enqueue}(q, e_1)) = \text{enqueue}(\text{dequeue}(q), e_1) \quad \text{si } \text{isEmpty}(q) = \text{false}

Axioma 6 (isEmpty de enqueue):

isEmpty(enqueue(q,e))=false\text{isEmpty}(\text{enqueue}(q, e)) = \text{false}

Axioma 7 (size de enqueue):

size(enqueue(q,e))=size(q)+1\text{size}(\text{enqueue}(q, e)) = \text{size}(q) + 1

Invariante

I(Queue):q,  size(q)0(isEmpty(q)=true    size(q)=0)I(\text{Queue}) : \forall q, \; \text{size}(q) \geq 0 \land (\text{isEmpty}(q) = \text{true} \iff \text{size}(q) = 0)

Contratos

OperaciónPrecondiciónPostcondiciónComplejidad
enqueue(q, e)ningunaelemento agregado al final; isEmpty(result)=false\text{isEmpty}(\text{result}) = \text{false}O(1)O(1) amortizado tiempo, O(1)O(1) amortizado espacio
dequeue(q)ningunasi vacía, resultado = empty; sino, primer elemento removidoO(1)O(1) amortizado tiempo, O(1)O(1) amortizado espacio
front(q)isEmpty(q)=false\text{isEmpty}(q) = \text{false}devuelve elemento al frenteO(1)O(1) tiempo, O(1)O(1) espacio

TDA LinkedList (Lista Enlazada Simple)

Una lista enlazada simple es una secuencia dinámica de nodos donde cada nodo referencia al siguiente. Permite inserción/remoción eficiente en cualquier posición conocida.

Sorts y Signatura

Sorts:LinkedList,Element,N,BoolGeneradores:empty:LinkedListsingleton:ElementLinkedListModificadores:insertAt:LinkedList×N×ElementLinkedListremoveAt:LinkedList×NLinkedListprepend:LinkedList×ElementLinkedListappend:LinkedList×ElementLinkedListObservadores:get:LinkedList×NElementsize:LinkedListNisEmpty:LinkedListBoolcontains:LinkedList×ElementBool\begin{align} \text{Sorts:} \quad & \mathtt{LinkedList}, \mathtt{Element}, \mathbb{N}, \mathtt{Bool} \\ \\ \text{Generadores:} \\ \quad & \text{empty} : \to \mathtt{LinkedList} \\ \quad & \text{singleton} : \mathtt{Element} \to \mathtt{LinkedList} \\ \\ \text{Modificadores:} \\ \quad & \text{insertAt} : \mathtt{LinkedList} \times \mathbb{N} \times \mathtt{Element} \to \mathtt{LinkedList} \\ \quad & \text{removeAt} : \mathtt{LinkedList} \times \mathbb{N} \to \mathtt{LinkedList} \\ \quad & \text{prepend} : \mathtt{LinkedList} \times \mathtt{Element} \to \mathtt{LinkedList} \\ \quad & \text{append} : \mathtt{LinkedList} \times \mathtt{Element} \to \mathtt{LinkedList} \\ \\ \text{Observadores:} \\ \quad & \text{get} : \mathtt{LinkedList} \times \mathbb{N} \to \mathtt{Element} \\ \quad & \text{size} : \mathtt{LinkedList} \to \mathbb{N} \\ \quad & \text{isEmpty} : \mathtt{LinkedList} \to \mathtt{Bool} \\ \quad & \text{contains} : \mathtt{LinkedList} \times \mathtt{Element} \to \mathtt{Bool} \end{align}

Axiomas

Axioma 1 (isEmpty vacía):

isEmpty(empty)=true\text{isEmpty}(\text{empty}) = \text{true}

Axioma 2 (size vacía):

size(empty)=0\text{size}(\text{empty}) = 0

Axioma 3 (prepend a vacía):

get(prepend(empty,e),0)=e\text{get}(\text{prepend}(\text{empty}, e), 0) = e

Axioma 4 (prepend desplaza índices):

get(prepend(l,e),i+1)=get(l,i)i0\text{get}(\text{prepend}(l, e), i+1) = \text{get}(l, i) \quad \forall i \geq 0

Axioma 5 (append a vacía):

get(append(empty,e),0)=e\text{get}(\text{append}(\text{empty}, e), 0) = e

Axioma 6 (size de prepend):

size(prepend(l,e))=size(l)+1\text{size}(\text{prepend}(l, e)) = \text{size}(l) + 1

Axioma 7 (removeAt índice válido):

size(removeAt(l,i))=size(l)1si 0i<size(l)\text{size}(\text{removeAt}(l, i)) = \text{size}(l) - 1 \quad \text{si } 0 \leq i < \text{size}(l)

Axioma 8 (removeAt preserva otros elementos):

j<i    get(removeAt(l,i),j)=get(l,j)j < i \implies \text{get}(\text{removeAt}(l, i), j) = \text{get}(l, j)

jij<size(l)1    get(removeAt(l,i),j)=get(l,j+1)j \geq i \land j < \text{size}(l) - 1 \implies \text{get}(\text{removeAt}(l, i), j) = \text{get}(l, j+1)

Invariante

I(LinkedList):l,  size(l)0(isEmpty(l)=true    size(l)=0)no circular referencesI(\text{LinkedList}) : \forall l, \; \text{size}(l) \geq 0 \land (\text{isEmpty}(l) = \text{true} \iff \text{size}(l) = 0) \land \text{no circular references}

Contratos

OperaciónPrecondiciónPostcondiciónComplejidad
insertAt(l, i, e)0isize(l)0 \leq i \leq \text{size}(l)elemento insertado en posición ii; size aumentaO(n)O(n) tiempo (búsqueda + inserción), O(1)O(1) espacio
removeAt(l, i)0i<size(l)0 \leq i < \text{size}(l)elemento removido; elementos posteriores se desplazanO(n)O(n) tiempo (búsqueda + remoción), O(1)O(1) espacio
get(l, i)0i<size(l)0 \leq i < \text{size}(l)devuelve elemento en posición iiO(n)O(n) tiempo (búsqueda lineal), O(1)O(1) espacio
prepend(l, e)ningunaelemento agregado al inicioO(1)O(1) tiempo, O(1)O(1) espacio
append(l, e)ningunaelemento agregado al finalO(n)O(n) tiempo (sin tail pointer) o O(1)O(1) (con tail pointer), O(1)O(1) espacio

TDA DoublyLinkedList (Lista Enlazada Doble)

Una lista enlazada doble permite navegación bidireccional. Cada nodo referencia al siguiente y al anterior.

Sorts y Signatura

Sorts:DoublyLinkedList,Element,N,BoolGeneradores:empty:DoublyLinkedListModificadores:insertAt:DoublyLinkedList×N×ElementDoublyLinkedListremoveAt:DoublyLinkedList×NDoublyLinkedListprepend:DoublyLinkedList×ElementDoublyLinkedListappend:DoublyLinkedList×ElementDoublyLinkedListObservadores:get:DoublyLinkedList×NElementgetFromEnd:DoublyLinkedList×NElement(desde el final)size:DoublyLinkedListNisEmpty:DoublyLinkedListBool\begin{align} \text{Sorts:} \quad & \mathtt{DoublyLinkedList}, \mathtt{Element}, \mathbb{N}, \mathtt{Bool} \\ \\ \text{Generadores:} \\ \quad & \text{empty} : \to \mathtt{DoublyLinkedList} \\ \\ \text{Modificadores:} \\ \quad & \text{insertAt} : \mathtt{DoublyLinkedList} \times \mathbb{N} \times \mathtt{Element} \to \mathtt{DoublyLinkedList} \\ \quad & \text{removeAt} : \mathtt{DoublyLinkedList} \times \mathbb{N} \to \mathtt{DoublyLinkedList} \\ \quad & \text{prepend} : \mathtt{DoublyLinkedList} \times \mathtt{Element} \to \mathtt{DoublyLinkedList} \\ \quad & \text{append} : \mathtt{DoublyLinkedList} \times \mathtt{Element} \to \mathtt{DoublyLinkedList} \\ \\ \text{Observadores:} \\ \quad & \text{get} : \mathtt{DoublyLinkedList} \times \mathbb{N} \to \mathtt{Element} \\ \quad & \text{getFromEnd} : \mathtt{DoublyLinkedList} \times \mathbb{N} \to \mathtt{Element} \quad \text{(desde el final)} \\ \quad & \text{size} : \mathtt{DoublyLinkedList} \to \mathbb{N} \\ \quad & \text{isEmpty} : \mathtt{DoublyLinkedList} \to \mathtt{Bool} \end{align}

Axiomas (adicionales a los de LinkedList)

Axioma 1 (navegación bidireccional):

getFromEnd(l,i)=get(l,size(l)1i)i<size(l)\text{getFromEnd}(l, i) = \text{get}(l, \text{size}(l) - 1 - i) \quad \forall i < \text{size}(l)

Axioma 2 (get es consistente en ambas direcciones):

get(l,i)=getFromEnd(l,size(l)1i)\text{get}(l, i) = \text{getFromEnd}(l, \text{size}(l) - 1 - i)

Axioma 3 (prepend refleja en navegación desde fin):

getFromEnd(prepend(l,e),0)=get(l,size(l)1)si isEmpty(l)=false\text{getFromEnd}(\text{prepend}(l, e), 0) = \text{get}(l, \text{size}(l) - 1) \quad \text{si } \text{isEmpty}(l) = \text{false}

Invariante (extendida)

I(DoublyLinkedList):LinkedList invariantsi,  next[prev[i]]=iprev[next[i]]=iI(\text{DoublyLinkedList}) : \text{LinkedList invariants} \land \forall i, \; \text{next}[\text{prev}[i]] = i \land \text{prev}[\text{next}[i]] = i

Cada nodo tiene referencias bidireccionales consistentes.

Contratos

OperaciónPrecondiciónPostcondiciónComplejidad
insertAt(l, i, e)0isize(l)0 \leq i \leq \text{size}(l)elemento insertado en posición iiO(n)O(n) tiempo (búsqueda), O(1)O(1) espacio
removeAt(l, i)0i<size(l)0 \leq i < \text{size}(l)elemento removidoO(n)O(n) tiempo (búsqueda), O(1)O(1) espacio
get(l, i)0i<size(l)0 \leq i < \text{size}(l)devuelve elemento en posición iiO(min(i,ni))O(\min(i, n-i)) tiempo (búsqueda desde ambos extremos), O(1)O(1) espacio
getFromEnd(l, i)0i<size(l)0 \leq i < \text{size}(l)devuelve elemento desde el finalO(min(i,ni))O(\min(i, n-i)) tiempo, O(1)O(1) espacio
prepend(l, e)ningunaelemento agregado al inicioO(1)O(1) tiempo, O(1)O(1) espacio
append(l, e)ningunaelemento agregado al finalO(1)O(1) tiempo (con tail pointer), O(1)O(1) espacio

TDA CircularLinkedList (Lista Enlazada Circular)

Una lista enlazada circular es una secuencia donde el último nodo referencia al primero, formando un ciclo cerrado.

Sorts y Signatura

Sorts:CircularLinkedList,Element,N,BoolGeneradores:empty:CircularLinkedListModificadores:insertAt:CircularLinkedList×N×ElementCircularLinkedListremoveAt:CircularLinkedList×NCircularLinkedListrotate:CircularLinkedList×NCircularLinkedListObservadores:get:CircularLinkedList×NElementsize:CircularLinkedListNisEmpty:CircularLinkedListBool\begin{align} \text{Sorts:} \quad & \mathtt{CircularLinkedList}, \mathtt{Element}, \mathbb{N}, \mathtt{Bool} \\ \\ \text{Generadores:} \\ \quad & \text{empty} : \to \mathtt{CircularLinkedList} \\ \\ \text{Modificadores:} \\ \quad & \text{insertAt} : \mathtt{CircularLinkedList} \times \mathbb{N} \times \mathtt{Element} \to \mathtt{CircularLinkedList} \\ \quad & \text{removeAt} : \mathtt{CircularLinkedList} \times \mathbb{N} \to \mathtt{CircularLinkedList} \\ \quad & \text{rotate} : \mathtt{CircularLinkedList} \times \mathbb{N} \to \mathtt{CircularLinkedList} \\ \\ \text{Observadores:} \\ \quad & \text{get} : \mathtt{CircularLinkedList} \times \mathbb{N} \to \mathtt{Element} \\ \quad & \text{size} : \mathtt{CircularLinkedList} \to \mathbb{N} \\ \quad & \text{isEmpty} : \mathtt{CircularLinkedList} \to \mathtt{Bool} \end{align}

Axiomas

Axioma 1 (circularidad: acceso modular):

get(l,i)=get(l,imodsize(l))isize(l)\text{get}(l, i) = \text{get}(l, i \bmod \text{size}(l)) \quad \forall i \geq \text{size}(l)

(Los índices se envuelven circularmente.)

Axioma 2 (rotación preserva elementos):

size(rotate(l,k))=size(l)\text{size}(\text{rotate}(l, k)) = \text{size}(l)

get(rotate(l,k),i)=get(l,(i+k)modsize(l))\text{get}(\text{rotate}(l, k), i) = \text{get}(l, (i + k) \bmod \text{size}(l))

Axioma 3 (isEmpty vacía):

isEmpty(empty)=true\text{isEmpty}(\text{empty}) = \text{true}

Axioma 4 (removeAt en lista circular):

size(removeAt(l,i))=size(l)1si isEmpty(l)=false\text{size}(\text{removeAt}(l, i)) = \text{size}(l) - 1 \quad \text{si } \text{isEmpty}(l) = \text{false}

Invariante

I(CircularLinkedList):uˊltimo nodoprimer nodosin terminacioˊn nulaI(\text{CircularLinkedList}) : \text{último nodo} \to \text{primer nodo} \land \text{sin terminación nula}

Todos los nodos están conectados en un ciclo cerrado.

Contratos

OperaciónPrecondiciónPostcondiciónComplejidad
rotate(l, k)ningunaorden cíclico rotado kk posicionesO(k)O(k) tiempo (actualizar referencias), O(1)O(1) espacio
get(l, i)ninguna (índices envolventes)devuelve elemento; imodsizei \bmod \text{size} si isizei \geq \text{size}O(n)O(n) tiempo (búsqueda desde inicio), O(1)O(1) espacio
insertAt(l, i, e)ningunaelemento insertado; ciclo preservadoO(n)O(n) tiempo (búsqueda + inserción), O(1)O(1) espacio
removeAt(l, i)isEmpty(l)=false\text{isEmpty}(l) = \text{false}elemento removido; ciclo preservadoO(n)O(n) tiempo (búsqueda + remoción), O(1)O(1) espacio

Comparativa: Propiedades Algebraicas y Complejidad

TDAAccesoInserciónRemociónIteraciónComplejidad TípicaInvariante clave
ArrayO(1) directoEstáticaEstáticaLinealAcceso O(1), modificación O(1)Tamaño fijo
StackLIFOFinalFinalLIFOpush/pop/top O(1)Vacía ↔ size = 0
QueueFIFOFinalInicioFIFOenqueue/dequeue/front O(1)FIFO order
LinkedListO(n)CualquierCualquierUnidireccionalget O(n), insert/remove O(n)No circular
DoublyLinkedListO(n)CualquierCualquierBidireccionalget O(min(i,n-i)), insert/remove O(n)Refs. simétricas
CircularLinkedListO(n)CualquierCualquierCíclicaget O(n), rotate O(k), insert/remove O(n)Ciclo cerrado

Validación: Demostración de Axiomas

Ejemplo: Stack

Proposición: Para toda pila ss y elemento ee:

isEmpty(pop(push(s,e)))=isEmpty(s)\text{isEmpty}(\text{pop}(\text{push}(s, e))) = \text{isEmpty}(s)

Demostración por inducción:

Base: s=emptys = \text{empty}

isEmpty(pop(push(empty,e)))=isEmpty(empty)(Axioma 4: pop de push)=true(Axioma 3)=isEmpty(empty)(hipoˊtesis)\begin{align} \text{isEmpty}(\text{pop}(\text{push}(\text{empty}, e))) &= \text{isEmpty}(\text{empty}) && \text{(Axioma 4: pop de push)} \\ &= \text{true} && \text{(Axioma 3)} \\ &= \text{isEmpty}(\text{empty}) && \text{(hipótesis)} \end{align}

Paso inductivo: Asumimos isEmpty(pop(push(s,e)))=isEmpty(s)\text{isEmpty}(\text{pop}(\text{push}(s, e))) = \text{isEmpty}(s) para pila ss.

Para s=push(s,e)s' = \text{push}(s, e'):

isEmpty(pop(push(push(s,e),e)))=isEmpty(push(s,e))(Axioma 4)=isEmpty(s)(definicioˊn)\begin{align} \text{isEmpty}(\text{pop}(\text{push}(\text{push}(s, e'), e))) &= \text{isEmpty}(\text{push}(s, e')) && \text{(Axioma 4)} \\ &= \text{isEmpty}(s') && \text{(definición)} \end{align}

Por inducción, la proposición vale. ∎

Ejemplo: LinkedList

Proposición: Para lista ll, índice ii válido y elemento ee:

get(removeAt(insertAt(l,i,e),i),i)e\text{get}(\text{removeAt}(\text{insertAt}(l, i, e), i), i) \neq e

(Insertar y luego remover en el mismo lugar restaura la lista original.)

Esta proposición se valida por análisis de casos sobre la estructura de la lista, similar a la demostración de stack.

Resumen

Las especificaciones algebraicas de estructuras de datos fundamentales proporcionan:

Estas especificaciones son el cimiento sobre el cual se construyen implementaciones seguras, testables y reemplazables en cualquier lenguaje de programación.

Próximo paso

Una vez que comprendés las especificaciones algebraicas completas de estructuras fundamentales, el siguiente paso es implementarlas en Java respetando los contratos algebraicos. Esto significa escribir código que satisfaga todos los axiomas, con tests que validen cada axioma para garantizar que la implementación es correcta.

Ejercicios de verificación

  1. Resolvé un caso mínimo usando la estructura/algoritmo del capítulo y documentá por qué esa elección es válida.

  2. Construí un contraejemplo donde una elección alternativa falle (rendimiento o corrección).

  3. Escribí una prueba corta en Java que verifique un invariante crítico.