Curso de Programación Estructurada Maestría en Robótica y Manufactura Avanzada Curso de Programación Estructurada Dra. L. Abril Torres Méndez Saltillo Clase 6: Heap-sort y Quick-sort Periodo: Sept.-Dic, 2010.
Heapsort Definición. Un heap es un arreglo A con valores. Representa un árbol binario completo que cumple: A[padre(i)] A[i] y está constituido de la siguiente forma: A[1] contiene la raíz A[2i] y A[2i+1]contienen respectivamente, los hijos izquierdos y derechos de A[i] A[i/2] contiene al padre de A[i] Todo camino de una hoja a la raíz es una secuencia ordenada linealmente
Operaciones sobre un heap Insertar, quitar el mayor, reemplazar elementos Todos estos requieren menos de 2 log n comparaciones. Utilizando heaps resulta en un elegante y eficiente método de ordenamiento. No se utiliza memoria extra. Simplemente se construye un heap con los elementos a ordenar y después se van quitando en el orden. Heapsort entonces requiere menos de 2 n log n comparaciones.
Algoritmo Heapsort: Checando que la propiedad de heap se cumpla HEAPIFY(A,i) l = Left(i); r = Right(i); if l ≤ heap-size[A] y A[l]>A[i] then largest = l else largest = i if l ≤ heap-size[A] y A[r]>A[largest] then largest = r if largest ≠ i then intercambiar A[i] A[k]; HEAPIFY(A, largest) Ejemplo en pizarrón
Algoritmo Heapsort BUILD-HEAP(A) heap-size[A] = length[A] for i length[A]/2 downto 1 do HEAPIFY(A,i) HEAPSORT(A) BUILD-HEAP; for i length[A] downto 2 do intercambiar A[1] A[i] heap-size[A] = heap-size[A]-1 HEAPIFY (A,1) Ejemplo en pizarrón
Análisis del Algoritmo Heapsort The algoritmo de Heapsort toma un tiempo de O(n log n) dado que el procedimiento de BUILD-HEAP toma O(n) y cada una de las n-1 llamadas a HEAPIFY toma un tiempo de O(log n). Revisar esto en casa…
QuickSort Quicksort es tal vez el más usado de los algoritmos. No usa mucho espacio auxiliar y en promedio requiere O(n log n) operaciones. Pero es recursivo y en el peor caso usa O(n2) operaciones.
QuickSort Es un algoritmo recursivo (se basa, como el merge-sort en el paradigma divide y conquistarás): Divide: El arreglo A[p..r] se particiona (re-arregla) en dos subarreglos no-vacíos A[p..q] y A[q+1..r]. El índice q es calculado como parte de este proceso de particionar. Conquistar: Los dos subarreglos A[p..q] y A[q+1..r] son ordenados mediante llamadas recursivas a Quicksort. Combinar: Dado que los subarreglos se reordenan «en-lugar», ningún trabajo se necesita para combinarlos: el arreglo entero A[p..r] está ahora ordenado.
Algoritmo QuickSort QuickSort(A,p,r) if p<r { q=Particionar(A,p,r) Quicksort(A,p,q) Quicksort(A,q+1,r) }
QuickSort Particionar(A,p,r) x=A[p]; i=p-1; j=r+1; while TRUE repeat j=j-1 until A[j]<=x repeat i=i+1 until A[i]>=x if i<j then intercambiar A[i] y A[j] else return j Ejemplo en pizarrón
Análisis del Algoritmo QuickSort En el mejor caso, cada etapa que involucra el particionar el arreglo divide el archivo exactamente a la mitad. En ese caso la recurrencia es Tn=2 Tn/2 + n…pero esto no siempre sucede. Se puede eliminar la recursión usando una pila de manera explícita.
Tarea 2 1) Analizar el algoritmo Quicksort versión recursiva, mostrar el desarrollo para obtener la función de recurrencia Tn=2 Tn/2 + n en el mejor de los casos (es decir obtener su tiempo de ejecución). 2) Escribir y analizar el algoritmo Quicksort para la versión no-recursiva. Fecha de entrega: Jueves 2 de diciembre, al comienzo de la clase.
Estructuras de datos: Pilas y colas
Pilas Son estructuras utilizadas muy a menudo como herramientas de programación de tipo LIFO (Last in-First out). Permiten el acceso sólo a un elemento a la vez: el último elemento insertado. La mayoría de los procesadores utilizan una arquitectura basada en pilas
Pilas - Operaciones Básicamente poseen dos operaciones primarias: Push: inserta el elmento en el tope de la pila Pop: remueve el elemento del tope de la pila
Pilas implementadas en listas Constructores: Push (Insertar al inicio) Pop (Eliminar al inicio) Selectores: Pila-Vacía? (validar con: el apuntador de la cabeza es Null?) top (Mostrar el primero)
Algoritmos para pilas PilaVacia( S ) If top( S ) = 0 return true else return false Push( S, x ) top( S ) <– top( S ) + 1 S[ top( S ) ] <– x Pop( S ) If PilaVacia error else top( S ) <– top( S ) - 1 return S[ top( S ) + 1 ]
Pilas - Eficiencia El tiempo de ejecución de las operaciones primarias de una pila no depende del tamaño de la pila. Push y Pop se realizan en tiempo constante O(1) - no es necesario hacer ninguna comparación.
Colas Son estructuras de datos de tipo FIFO (First in-First out) Simulan una cola de personas en el cine Las colas son herramientas de programación como las pilas|
Colas - Operaciones Operaciones primarias: Enqueue (encolar): agrega un nuevo elemento al final de la cola. Dequeue (desencolar): elimina un elemento del principio de la cola
Colas implementadas en listas Constructores: Enqueue (Insertar al final) Dequeue (Eliminar al inicio) Selectores: Cola-Vacia? (El apuntador de Cabeza es Nil?) Primero-Cola (Mostrar el primero)
Algoritmos para colas Enqueue ( Q, x ) Q[ Fin( Q ) ] <– x if Fin( Q ) = length( Q ) then Fin( Q ) <– 1 else Fin( Q ) <– Fin( Q ) + 1 Dequeue( Q ) x <– Q[ Cabeza( Q ) ] if Cabeza( Q ) = Length( Q ) then Cabeza( Q ) <– 1 else Cabeza( Q ) <– Cabeza( Q ) + 1 return x Checar Capítulo 11 del Libro de Cormen (Elementary Data Structures)
Colas - Eficiencia Al igual que la estructura pila, el tiempo de ejecución de las operaciones primarias de una cola no depende del tamaño de la cola. Enqueue y Dequeue se realizan en tiempo constante O(1) - no es necesario hacer ninguna comparación.
Cola doble enlace La mejor implementación de cola, es con una lista, donde se tenga un apuntador a la cabeza y uno al último elemento de la lista. Apuntador a Cola Apuntador a Cabeza 3 2 1 5 Null Null
Tarea 3 Sobre «Pilas y colas» Será enviada por e-mail el día de mañana viernes y puesta en la página de internet. Fecha de entrega: Jueves 9 de diciembre al inicio de la clase.