Diseño de Pilas y Colas ¿Recordamos qué era una Pila? TAD Pila(α α) Observadores básicos (~ vacía?(p)) Generadores vacía?: pila(α) → bool tope: pila(α) p → α vacía: → pila(α) apilar: α × pila(α) → pila(α) Otras Operaciones desapilar: pila(α) p → pila(α) (~ vacía?(p)) tamaño: pila(α) → nat ⋅ =pila ⋅ : pila(α) × pila(α) → bool Representación de Pilas con Arreglos Pila(α) se representa con tupla<p:arreglo(α) x tope:NAT> Invariante de representación: 0 <= tope <= tam(p) Función de abstracción: ABS([p1,p2,.....,ptam(p)],0) = vacía (pi ∈ NAT U {indefinido}, i=1..tam(p)) ABS([p1,p2,.....,ptam(p)], tope) = apilar (ptope,ABS ([p1,p2,.....,ptam(p)], tope-1) (pi ∈ NAT, i=1..tope, pi ∈ NAT U {indefinido}, i=tope+1..tam(p)) Representación de Pilas con Arreglos O sea...... Los elementos de la pila están en el arreglo, entre la posición 1 y la posición tope, ordenados por orden de llegada y p[tope] es el tope de la pila. Pi Pi tope = i Pila Vacía P2 P1 P2 P1 tope = 0 Pila no Vacía Representación de Pilas con Arreglos Idea de los Algoritmos Vacía: crear un arreglo, con tope=0 Apilar elemento: incrementar tope (previa verificación de que tope< tam(p)), p[tope]←elemento Tope: p[tope] Desapilar: if tope<>0 then tope←tope-1 Tamaño: tope Análisis de complejidad: Tiempo: suponiendo que las operaciones de asignación al arreglo, y las operaciones de incrementar, decrementar y comparar un NAT con 0 llevan tiempo constante, todas las operaciones llevan tiempo constante Memoria: Una pila que contendrá como máximo n elementos requiere espacio proporcional a n. Representación de Pilas con Listas Encadenadas Pila(α) se representa con lista(α) o .... Pila(α) se representa con puntero a nodo(α), donde nodo(α) es tupla<valor: α, siguiente: puntero a nodo(α) Invariante de representación: “En finitos pasos se llega a nil” (o sea, es una lista!) Función de abstracción: ABS(nil) = vacía ABS(a) = apilar (a.valor,ABS(a.siguiente)) Representación de Pilas con Listas Encadenadas O sea...... Los elementos de la pila están en la lista, ordenados por orden inverso al de llegada, o sea el primer elemento de la lista es el tope de la pila. Por ejemplo: Start PN-1 PN-2 Pi P0 Representación de Pilas con Listas Encadenadas Idea de los Algoritmos Vacía: crear una lista vacía Apilar elemento: agregar un elemento a la secuencia Tope(p): p^.valor (primer elemento de la secuencia) Desapilar(p): if not vacía? then p ^.siguiente ¿Y Tamaño? Análisis de complejidad: Tiempo: suponiendo que las operaciones de asignación de creación y asignación de punteros, y las de asignación del tipo base llevan tiempo constante, todas las operaciones llevan tiempo constante...salvo Tamaño! ¿Alguna idea? Memoria: Una pila que contiene n elementos requiere espacio proporcional a n. ¿Recordamos qué era una Cola? TAD Cola(α α) Observadores básicos vacía?: cola(α) → bool próximo: cola(α) c → α Generadores vacía: → cola(α) encolar: α × cola(α) → cola(α) Otras Operaciones desencolar: cola(α) c → cola(α) longitud: cola(α) → nat ⋅ =cola ⋅ : cola(α) × cola(α) → bool ( ~vacía?(c)) (~vacía?(c)) Representación de Colas con Arreglos Cola(α) se representa con tupla<p:arreglo(α) x prox:NAT x ult:NAT> Invariante de representación: 0 <= prox,ult <= tam(p) Función de abstracción: ABS([p0,p1,.....,ptam(p)-1], n+1,n) = vacía (pi ∈ NAT U {indefinido}, i=1..tam(p)) ABS ([p0,p1,.....,ptam(p)-1], n,m) = encolar (pm,ABS ([p0,p1,.....,ptam(p)-1], n,m-1) (si n≤m, pi ∈ NAT, i=n..m, pi ∈ NAT U {indefinido}, i=0..n-1 e i=m+1..tam(p), si n>m+1, pi ∈ NAT, i=n.. tam(p) e i=0..m pi ∈ NAT U {indefinido}, i=m+1..n-1) Representación de colas con Arreglos O sea...... Los elementos de la cola están en el arreglo, entre la posición prox y la posición ult, ordenados por orden de llegada y p[prox] es el próximo de la cola. P0 P1 P2 PK-3 PK-2 PK-1 Elemento no usado K=tam(p) prox ult Representación de Colas con Arreglos Idea de los Algoritmos Vacía: crear un arreglo, con prox=ult+1 Encolar elemento: incrementar ult módulo tam(p) (previa verificación de que tope < ult-1), p[ult]←elemento próximo: p[prox] Desencolar: if prox<>ult then prox←prox+1 Longitud: prox-ult+1 Análisis de complejidad: Tiempo: suponiendo que las operaciones de asignación al arreglo, y las operaciones de incrementar, decrementar y comparar un NAT con 0 llevan tiempo constante, todas las operaciones llevan tiempo constante Memoria: Una cola que contendrá como máximo n elementos requiere espacio proporcional a n. Representación de Colas con Listas Encadenadas Cola(α) se representa con tupla<prox: puntero a nodo(α) , ult: puntero a nodo (α) > donde nodo(α) es ...... Invariante de representación: Igual que antes...... y además prox<>nil ⇒ ult^.siguiente=nil Función de abstracción: ABS(<prox, ult>)= if prox=nil then cola_vacía() else c donde ~vacía(c) ∧L próximo(c)=prox^.valor ∧L desencolar(c)=abs(<prox^.siguiente, ult>) Representación de Colas con Listas Encadenadas O sea...... Los elementos de la pila están en la lista, ordenados por orden de llegada, el primer elemento de la lista es el próximo de la cola, y el último de la lista es el último de la cola. ult prox PN-1 PN-2 Pi P0 Representación de Colas con Listas Encadenadas Idea de los Algoritmos Vacía: crear una lista vacía Encolar: agregar un elemento al final de la secuencia prox: primer elemento de la secuencia (prox^.valor) Desencolar: if not vacía? then <prox^.siguiente, ult> ¿Y longitud? Análisis de complejidad: Tiempo: suponiendo que las operaciones de asignación de creación y asignación de punteros, y las de asignación del tipo base llevan tiempo constante, todas las operaciones llevan tiempo constante.....salvo longitud. ¿Alguna idea para mejorar eso? Memoria: Una cola que contiene n elementos requiere espacio proporcional a n.