Académique Documents
Professionnel Documents
Culture Documents
Introducci on
Tipo de Datos(TD): conjunto de valores que una variable puede tomar. Ej: un n umero entero es de tipo entero ). Representaci on interna: agrupaciones de bits. Necesidad de usar TDs: Elegir representaci on interna optima. Aprovechar las caracter sticas de un TD. Ej: operaciones aritm eticas. TD simples, elementales o primitivos: enteros, reales, booleanos y caracteres. Operaciones asociadas simples. Ej:multiplicaci on.
Introducci on (II)
Trabajar con matrices de n umeros denir un TD matriz y operaciones asociadas (Ej: multiplicaci on). Tipo Abstracto de Datos(TAD): modelo matem atico con una serie de operaciones denidas (procedimientos). TAD = generalizaci on de los TD simples. Procedimientos = generalizaciones de operaciones primitivas. La encapsulaci on o abstracci on permite: Localizar la denici on del TAD y sus operaciones en un lugar determinado. Librer as espec cas para un TAD. Cambiar la implementaci on seg un la adecuaci on al problema. Facilidad en la depuraci on de c odigo. Mayor orden y estructuraci on en los programas.
Introducci on (III)
Ej: TAD matriz implementaci on tradicional o para matrices dispersas. Implementaci on de un TAD: traducir en instrucciones de un lenguaje de programaci on la declaraci on de ese tipo. Un procedimiento por cada operaci on denida en el TAD. Una implementaci on elige una estructura de datos (ED) para el TAD. ED constru da a partir de TDs simples + dispositivos de estructuraci on del lenguaje de programaci on (vectores o registros).
Ejemplo
Denir TAD Matriz de Enteros: Matriz de Enteros agrupaci on de n umeros enteros ordenados por las y por columnas. El n umero de elementos en cada la es el mismo. Tambi en el n umero de elementos en cada columna es el mismo. Un n umero entero que forme parte de la matriz se identica por su la y columna. Representaci on l ogica: 3 7 9 M = 4 5 6 2 3 5 M [1, 2] = 4.
Ejemplo (II)
Operaciones: Suma Mat(A,B: Matriz) devuelve C: Matriz suma dos matrices que tienen igual n umero de las y de columnas. La suma se realiza sumando elemento a elemento cada n umero entero de la matriz A con el correspondiente n umero entero de la matriz B que tenga igual n umero de la e igual n umero de columna. Multiplicar Mat(A,B: Matriz) devuelve C: Matriz multiplica dos matrices que cumplen la condici on . . . . Inversa Mat(A: Matriz) devuelve C: Matriz en el caso de que la matriz A posea inversa, esta se calcula . . . .
Ejemplo: Implementaci on
En lenguaje C: #dene NUM_FILAS 10 #dene NUM_COLUMNAS 10 /* Definimos el TAD */ typedef int t_matriz[NUM_FILAS][NUM_COLUMNAS]; /* Definimos una variable */ t_matriz M;
void Suma_Mat(t_matriz A, t_matriz B, t_matriz C) { int i,j; for (i=0;i<NUM_FILAS;i++) for (j=0;j<NUM_COLUMNAS;j++) C[i][j] = A[i][j] + B[i][j]; }
Denici on y creaci on de una variable en tiempo de compilaci on Durante la codicaci on y compilaci on se dene el tipo de la variable y su tama no. Ejemplo La denici on int x; hace que cuando comienza la ejecuci on se reserve un espacio de memoria que puede almacenar un entero y al cual se puede acceder con la etiqueta x. x
De esa manera son v alidas las siguientes operaciones: En el c odigo x=5; x=x+2; En ejecuci on x x 5 7
Para estructuras m as complejas la situaci on es la misma: En el c odigo int v[3]; struct {oat r,i;} im; En ejecuci on v im Instrucci on v alida v[0]=1; im.r=5.0; im.i=3.0;
Punteros La denici on int *px; dene la variable px como un puntero a entero y no como entero. px puede contener una direcci on a otra zona de memoria que s que puede contener un entero. El operador & permite recuperar la direcci on de una variable que ya existe en memoria. Un puntero puede tomar un valor especial NULL para indicar que no apunta a ning un lugar accesible.
En ejecuci on px x 1
px px px
1 x 2 x 2 x
En px guardamos la direcci on de x. Modicamos x a trav es de px. ERROR: no se puede asignar un entero a px. px toma valor NULL. ERROR: px no apunta a un lugar accesible.
px=NULL; *px=1;
px px
2 x 2 x
Punteros y vectores Una caracter stica importante de los punteros en C es que pueden apuntar a cualquier posici on en una estructura m as compleja como un vector o una struct. De esa manera se permiten operaciones como las siguientes: En el c odigo int *px, v[3]; En ejecuci on px v Comentario px y los elementos de v est an indenidos.
px=&v[0]; *px=1;
px px
v
px apunta a la primera posici on del vector. La primera posici on del vector se modica a trav es de px. px apunta a la segunda posici on del vector.
v 1
px=px+1;
px
v 1 v 1 2
v[1]=v[0]+*(px-1); px
La variable v se puede ver como un puntero a una o m as posiciones de memoria consecutivas. De esa manera son posibles operaciones como las siguientes: En el c odigo int *px, v[3]; En ejecuci on px v Comentario px y los elementos de v est an indenidos. Por comodidad representamos v como antes. px apunta a la primera posici on del vector.
px=v; px[0]=1;
px px
v v 1
Denici on y creaci on de una variable en tiempo de ejecuci on Durante la codicaci on y compilaci on se dene el tipo de la variable. Durante el tiempo de ejecuci on se reserva la cantidad de memoria necesaria. Reserva de memoria: las funciones malloc y calloc permiten reservar memoria din amicamente. La funci on malloc no inicializa la memoria reservada, mientras que calloc s . Liberaci on de memoria: la funci on free permite liberar memoria previamente reservada. Talla de un tipo: sizeof devuelve el n umero de bytes que necesita un tipo.
La sintaxis de malloc y calloc es: void *malloc(size_t size); void *calloc(size_t nmemb, size_t size); malloc recibe como par ametro el n umero de bytes que queremos reservar y devuelve un puntero sin tipo. calloc recibe como par ametros el n umero de elementos que queremos reservar y el n umero de bytes de cada elemento y devuelve un puntero sin tipo. La sintaxis de free es: void free(void *ptr); Recibe como par ametro un puntero a una zona v alida de memoria. La sintaxis de sizeof es: sizeof(type); Recibe como par ametro un tipo.
8
Sea la siguiente denici on: int *v; En el c odigo v=(int *)malloc(n*sizeof(int )); Comentario Reservamos un vector de n enteros. Forzamos a la funci on malloc a devolver un puntero a entero que se guarda en v. Indexamos el vector de la manera habitual. Liberamos la memoria previamente reservada. La informaci on almacenada es a partir de ahora inaccesible. ERROR: v ya no apunta a una zona v alida.
v[0]=1; free(v);
v[0]=1;
Sean las siguientes deniciones: int **v,*pv,i,j; /* v es un puntero a uno o mas punteros a enteros. */ Los siguientes segmentos de c odigo permiten denir una matriz cuadrada. v=(int **)malloc(n*sizeof(int *)); /* Definimos un vector de punteros. */ for (i=0; i<n; i++) { v[i]=(int *)malloc(n*sizeof(int )); /* Definimos un vector de enteros. */ for (j=0; j<n; j++) /* Inicializamos cada fila. */ v[i][j]=0; } v=(int **)malloc(n*sizeof(int *)); /* Definimos un vector de punteros. */ pv=(int *)malloc(n*n*sizeof(int )); /* Definimos un vector de enteros. */ for (i=0; i<n*n; i++) pv[i]=0; /* Inicializamos la matriz. */ for (i=0; i<n; i++) /* Cada componente de v apunta a n posiciones */ v[i]=&pv[i*n]; /* consecutivas de pv. */
10
Sean las siguientes deniciones: typedef struct { int a, b; } tupla; tupla *t, **tt; /* tt es un vector de apuntadores a tupla. */ int *p,i; En el c odigo Comentario
t=(tupla *)malloc(sizeof(tupla)); Reservamos un registro. Forzamos a la funci on malloc a devolver un puntero al tipo deseado. t->a=0; Modicamos un campo del registro. p=&t->b; Asignamos a p la direcci on de un campo del registro, que es una zona v alida de memoria. *p=0; Modicamos un campo del registro. free(t); Liberamos la memoria previamente reservada. *p=0; ERROR: p ya no apunta a una zona v alida.
11
En el c odigo
Comentario
tt=(tupla**)malloc(n*sizeof(tupla*)); Reservamos un vector de punteros a tupla. t=(tupla*)malloc(n*sizeof(tupla)); Reservamos un vector de tuplas. for (i=0;i<n;i++) { Despu es enlazamos cada elemento tt[i]=&t[i]; de tt con un elemento de t. tt[i]->a=0; tt[i]->b=0; }
12
Hay que pasarlos mediante un puntero a un vector. Realizar una copia local del vector cada vez es demasiado costoso. El vector se pasa por referencia. void f(int *v) { ... } ... int main() { int p[n]; ... f(p); ... }
13
Pn+1 Pn+1 Pn . . P2 P1
tope
Pn . . P2 P1
Pn . . P2 P1
Pn Pn1 . . . P1
/
Pn
Pn . . . P2 P1
/
e Pn . . . P2 P1
Pn Pn1 . . . P1
/
Pn . . . P2 P1
tope
/
Pn1 . . . P2 P1
P2
Pn
tope
typedef struct { int v[maxP]; /* Vector definido en tiempo de compilacion. */ /* Trabajamos con pilas de enteros. */ int tope; /* Marcador al tope de la pila. */ } pila;
p = (pila *) malloc(sizeof(pila)); /* Reservamos memoria para la pila. */ p->tope = -1; /* Inicializamos el marcador al tope. */ return(p); /* Devolvemos un puntero a la pila creada. */ } pila *apilar(pila *p, int e) { if (p->tope + 1 == maxP) /* Comprobamos si cabe el elemento. */ tratarPilaLlena(); /* Si no cabe hacemos un tratamiento de error. */ else { /* Si cabe, entonces */ p->tope = p->tope + 1; /* actualizamos el tope e */ p->v[p->tope] = e; /* insertamos el elemento. */ } return(p); /* Devolvemos un puntero a la pila modificada. */ } pila *desapilar(pila *p) { p->tope = p->tope - 1; /* Decrementamos el marcador al tope. */ return(p); /* Devolvemos un puntero a la pila modificada. */ }
4
int vaciap(pila *p) { return(p->tope < 0); /* Devolvemos 0 (falso) si la pila no esta vacia, */ } /* y 1 (cierto) en caso contrario. */
Pn
X $$$ $$
Pn1
X $$$ $$
P2
X $$$ $$
P1
Denici on de tipo
typedef struct _pnodo { int e; /* Variable para almacenar un elemento de la pila. */ struct _pnodo *sig; /* Puntero al siguiente nodo que contiene un elemento } pnodo; /* Tipo nodo. Cada nodo contiene un elemento de la pila. */ typedef pnodo pila; pila *crearp() { return(NULL); /* Devolvemos un valor NULL para inicializar */ } /* el puntero de acceso a la pila. */ int tope(pila *p) { return(p->e); /* Devolvemos el elemento apuntado por p */ }
6
pila *apilar(pila *p, int e) { pnodo *paux; paux = (pnodo *) malloc(sizeof(pnodo)); /* Creamos un nodo. paux->e = e; /* Almacenamos el elemento e. paux->sig = p; /* El nuevo nodo pasa a ser tope de la pila. return(paux); /* Devolvemos un puntero al nuevo tope. } pila *desapilar(pila *p) { pnodo *paux; */ */ */ */
paux = p; /* Guardamos un puntero al nodo a borrar. */ p = p->sig; /* El nuevo tope sera el nodo apuntado por el tope actual. */ free(paux); /* Liberamos la memoria ocupada por el tope actual. */ return(p); /* Devolvemos un puntero al nuevo tope. */ } int vaciap(pila *p) { return(p == NULL); /* Devolvemos 0 (falso) si la pila no esta vacia, */ } /* y 1 (cierto) en caso contrario. */
7
Q1
pcab
Q2 Q2
pcab
Qn Qn Qn Qn Qn+1
pcol
Qn+1
Q1 Q1
pcol
Q2
pcab
Qn+1
pcol
Q2 Aplicaciones
Qn+1
pcol
Q1
Q2
Qn
Q1
Q2
Qn
pcol
Q1
Q2
Qn
Q2
Q3
Qn
Q1
Q2
Qn
Q1
Q1
Q2
Qn
Posibles situaciones
0
Q1
pcab
Q2
Qn
pcol
maxC1
Q1
pcab
Q2
Qn
pcol
maxC1
Qn
pcol
Q1
pcab
Q2
10
maxC-1 0
f f
&% &%
f f
&%
pcol
rr pcab
&%
pcab rr pcol
typedef struct { int v[maxC]; /* Vector definido en tiempo de compilacion. */ int pcab, pcol; /* Marcador a la cabeza y a la cola. */ int talla; /* Numero de elementos. */ } cola;
11
q = (cola *) malloc(sizeof(cola)); /* Reservamos memoria para la cola. */ q->pcab = 0; /* Inicializamos el marcador a la cabeza. */ q->pcol = 0; /* Inicializamos el marcador a la cola. */ q->talla = 0; /* Inicializamos la talla. */ return(q); /* Devolvemos un puntero a la cola creada. */ } cola *encolar(cola *q, int e) { if (q->talla == maxC) /* Comprobamos si cabe el elemento. */ tratarColaLlena(); /* Si no cabe hacemos un tratamiento de error. */ else { /* Si cabe, entonces */ q->v[q->pcol] = e; /* guardamos el elemento, */ q->pcol = (q->pcol + 1) % maxC; /* incrementamos marcador de cola, */ q->talla = q->talla + 1; /* e incrementamos la talla. */ } return(q); /* Devolvemos un puntero a la cola modificada. */ }
12
cola *desencolar(cola *q) { q->pcab = (q->pcab + 1) % maxC; /* Avanzamos el marcador de cabeza. */ q->talla = q->talla - 1; /* Decrementamos la talla. */ return(q); /* Devolvemos un puntero a la cola modificada. */ } int cabeza(cola *q) { return(q->v[q->pcab]); /* Devolvemos el elemento que hay en cabeza. */ } int vaciaq(cola *p) { return(q->talla == 0); /* Devolvemos 0 (falso) si la cola */ /* no esta vacia, y 1 (cierto) en caso contrario.*/ }
13
Q1
X $ $ $$$
Q2
Qn1
X $ $$ $$$ B
Qn
X $$ $$$
Denici on de tipo
typedef struct _cnodo { int e; /* Variable para almacenar un elemento de la cola. */ struct _cnodo *sig; /* Puntero al siguiente nodo que contiene un elemento } cnodo; /* Tipo nodo. Cada nodo contiene un elemento de la cola. */ typedef struct { cnodo *pcab, *pcol; /* Punteros a la cabeza y la cola. */ } cola;
14
cola *crearq() { cola *q; q = (cola*) malloc(sizeof(cola)); /* Creamos una cola. */ q->pcab = NULL; /* Inicializamos a NULL los punteros. */ q->pcol = NULL; return(q); /* Devolvemos un puntero a la cola creada.*/ } cola *encolar(cola *q, int e) { cnodo *qaux;
qaux = (cnodo *) malloc(sizeof(cnodo)); /* Creamos un nodo. */ qaux->e = e; /* Almacenamos el elemento e. */ qaux->sig = NULL; if (q->pcab == NULL) /* Si no hay nigun elemento, entonces */ q->pcab = qaux; /* pcab apunta al nuevo nodo creado, */ else /* y sino, */ q->pcol->seg = qaux; /* el nodo nuevo va despues del que apunta pcol. * q->pcol = qaux; /* El nuevo nodo pasa a estar apuntado por pcol. */ return(q); /* Devolvemos un puntero a la cola modificada. */ }
15
cola *desencolar(cola *q) { cnodo *qaux; qaux = q->pcab; /* Guardamos un puntero al nodo a borrar. q->pcab = q->pcab->sig; /* Actualizamos pcab. if (q->pcab == NULL) /* Si la cola se queda vacia, entonces q->pcol = NULL; /* actualizamos pcol. free(qaux); /* Liberamos la memoria ocupada por el nodo. return(q); /* Devolvemos un puntero a la cola modificada. } int cabeza(cola *q) { return(q->pcab->e); /* Devolvemos el elemento que hay en la cabeza. */ } int vaciaq(cola *q) { return(q->pcab == NULL); /* Devolvemos 0 (falso) si la cola */ } /* no esta vacia, y 1 (cierto) en caso contrario. */ */ */ */ */ */ */
16
insertar(l,e,p): inserta e en la posici on p de la lista l. Los elementos que est an a partir de la posici on p se desplazan una posici on.
1 p n 1
/
p+1
n+1
L1
Lp
Ln
L1
Lp
Ln
n1
L1
Lp
Ln
L1
Lp+1
Ln
L1
Lp
Ln
Lp
17
L1
Ln
Falso si n > 0
L1
Ln
n+1
L1
Ln
L1
Lp
Ln
p+1
18
L2
Ln
u ltimo
typedef int posicion; /* Cada posicion se referencia con un entero. */ typedef struct { int v[maxL]; /* Vector definido en tiempo de compilacion. */ posicion ultimo; /* Posicion del ultimo elemento. */ } lista;
19
lista *crearl() { lista *l l = (lista *) malloc(sizeof(lista)); /* Creamos la lista. */ l->ultimo = -1; /* Inicializamos el marcador al ultimo. */ return(l); /* Devolvemos un puntero a la lista creada. */ } lista *insertar(lista *l, int e, posicion p) { posicion i;
if (l->ultimo == maxL-1) /* Comprobamos si cabe el elemento. */ tratarListaLlena(); /* Si no cabe hacemos un tratamiento de error. */ else { /* Si cabe, entonces */ for (i=l->ultimo; i>=p; i--) /* hacemos un vacio en la posicion p, */ l->v[i+1] = l->v[i]; l->v[p] = e; /* guardamos el elemento, */ l->ultimo = l->ultimo + 1; /* e incrementamos el marcador al ultimo. */ return(l); /* Devolvemos un puntero a la lista modificada. */ } }
20
lista *borrar(lista *l, posicion p) { posicion i; for (i=p; i<l->ultimo; i++) /* Desplazamos los elementos del vector. */ l->v[i] = l->v[i+1]; l->ultimo = l->ultimo - 1; /* Decrementamos el marcador al ultimo. */ return(l); /* Devolvemos un puntero a la lista modificada. */ } int recuperar(lista *l, posicion p) { return(l->v[p]); /* Devolvemos el elemento que hay en la posicion p. */ } int vacial(lista *l) { return(l->ultimo < 0); /* Devolvemos 0 (falso) si la lista */ } /* no esta vacia, y 1 (cierto) en caso contrario. */
posicion principio(lista *l) { return(0); /* Devolvemos la primera posicion. */ } posicion siguiente(lista *l, posicion p) { return(p+1); /* Devolvemos la posicion siguiente a la posicion p. */ }
22
Representaci on enlazada de listas con variable din amica Usamos un nodo centinela al principio de la lista para optimizar las operaciones de actualizaci on.
primero u ltimo
E $$$ X $ $
L1
Ln1
$ $$X $$$ B
Ln
X $$ $$$
Primera posibilidad: dada una posici on p, el elemento Lp est a en el nodo apuntado por p.
p
E
Lp
X $$ $$$
Segunda posiblidad: dada una posici on p, el elemento Lp est a en el nodo apuntado por p->sig.
p
E
Lp1
X $ $$ $$$
Lp
$$$ X $$
23
Denici on de tipo
typedef struct _lnodo { int e; /* Variable para almacenar un elemento de la lista. */ struct _lnodo *sig; /* Puntero al siguiente nodo que contiene un elemento } lnodo typedef lnodo *posicion; /* Cada posicion se referencia con un puntero. */ typedef struct { /* Definimos el tipo lista con un puntero */ posicion primero, ultimo; /* al primero y ultimo nodos. */ } lista; lista *crearl() { lista *l; l = (lista *) malloc(sizeof(lista)); /* Creamos una lista. */ l->primero = (lnodo *) malloc(sizeof(lnodo)); /* Creamos el centinela */ l->primero->sig = NULL; l->ultimo = l->primero; return(l); /* Devolvemos un puntero a la lista creada. */ }
24
lista *insertar(lista *l, int e, posicion p) { posicion q; q = p->sig; /* Dejamos q apuntando al nodo que se desplaza. p->sig = (lnodo *) malloc(sizeof(lnodo)); /* Creamos un nodo. p->sig->e = e; /* Guardamos el elemento. p->sig->sig = q; /* El sucesor del nuevo nodo esta apuntado por q. */ */ */ */
if (p == l->ultimo) /* Si el nodo insertado ha pasaso a ser el ultimo, */ l->ultimo = p->sig; /* actualizamos ultimo. */ return(l); /* Devolvemos un puntero a la lista modificada. */ } lista *borrar(lista *l, posicion p) { posicion q; if (p->sig == l->ultimo) /* Si el nodo que borramos es el ultimo, l->ultimo = p; /* actualizamos ultimo. q = p->sig; /* Dejamos q apuntando al nodo a borrar. p->sig = p->sig->sig; /* p->sig apuntara a su sucesor. free(q); /* Liberamos la memoria ocupada por el nodo a borrar. return(l); /* Devolvemos un puntero a la lista modificada. }
25
*/ */ */ */ */ */
int recuperar(lista *l, posicion p) { return(p->sig->e); /* Devolvemos el elemento que hay en la posicion p. */ } int vacial(lista *l) { return(l->primero->sig == NULL); /* Devolvemos 0 (falso) si la lista */ } /* no esta vacia, y 1 (cierto) en caso contrario. */ posicion fin(lista *l) { return(l->ultimo); } posicion principio(lista *l) { return(l->primero); } /* Devolvemos la ultima posicion. */
...
p2
B B
L1
p1
Lp
...
Bu
L2
B
Ln1
...
Ln
B
...
B
u1
typedef posicion int; /* El tipo posicion se define como un entero. */ typedef struct { int v[maxL]; /* Vector definido en tiempo de compilacion. */ posicion p[maxL]; /* Vector de posiciones creado en tiempo de execucion. posicion p1, /* Marcador al principio de la lista. */ u1, /* Marcador al fin de la lista. */ p2; /* Marcador al principio de la lista de nodos vacios. */ } lista;
27
...
...
Lp
B
...
Lp = l.v [l.p[p]]
lista *crearl() { lista *l; int i; l = (lista *) malloc(sizeof(lista)); /* Creamos la lista. */ l->p1 = 0; /* El nodo 0 es el centinela. */ l->u1 = 0; l->p[0] = -1; l->p2 = 1; /* La lista de nodos vacios comienza en el node 1. */ for (i=1; i<maxL-1; i++) /* Construimos la lista de nodos vacios. */ l->p[i] = i+1; l->p[maxL-1] = -1; /* El ultimo nodo vacio no senyala a ningun lugar. */ return(l); /* Devolvemos un puntero a lista construida. */ }
28
if (l->p2 == -1) /* Si no quedan nodos vacios, */ tratarListaLlena(); /* hacemos un tratamiento de error. */ else { q = l->p2; /* Dejamos un marcador al primer nodo vacio. */ l->p2 = l->p[q]; /* El primer nodo vacio sera el sucesor de q. */ l->v[q] = e; /* Guardamos el elemento en el nodo reservado. */ l->p[q] = l->p[p]; /* Su sucesor pasa a ser el de la pos. p. */ l->p[p] = q; /* El sucesor del nodo apuntado por p pasa a ser q. */ if (p == l->u1) /* Si el nodo que hemos insertado pasa a ser el ultimo, l->u1 = q; /* actualizamos el marcador u1. */ return(l); /* Devolvemos un puntero a la lista modificada. */ }
29
if (l->p[p] == l->u1) /* Si el nodo que borramos es el ultimo, */ l->u1 = p; /* actualizamos u1. */ q = l->p[p]; /* Dejamos q senyalando al nodo a borrar. */ l->p[p] = l->p[q]; /* El sucesor del nodo senyalado por p pasa a ser el sucesor del nodo apuntado por q. */ l->p[q] = l->p2; /* El nodo que borramos sera el primero de los vacios. * l->p2 = q; /* El principio de la lista de nodos vacios comienza en q. */ return(l); }
30
Divide y vencer as
Algoritmos de ordenaci on
Problema: Ordenar de manera no decreciente un conjunto de n enteros almacenado en un vector A.
ordenado
no ordenado
2. Se selecciona el elemento que ocupa la primera posici on en la parte sin ordenar, y se inserta en la posici on que le corresponda por orden de la parte ordenada de tal forma que se mantenga la ordenaci on en dicha parte.
i
ordenado
no ordenado
ordenado
no ordenado
Algoritmo: Argumentos:
Inserci on directa A: vector A[l, . . . , r], l: ndice de la primera posici on del vector, r: ndice de la u ltima posici on del vector
void insercion directa(int *A,int l,int r) { int i,j,aux; for(i=l+1;i<=r;i++){ aux=A[i]; j=i; while ((j>l) && (A[j-1]>aux)) { A[j]=A[j-1]; j--; } A[j]=aux; } }
insercion directa(A,0,4)
0 1 2 3 4
45 14 33 3 56
45 45 33 3 56 aux
j=0
14 45 33 3 56
14 45 45 3 56 aux
j=1
14 33 45 3 56
14 33 45 45 56 14 33 33 45 56 14 14 33 45 56 aux
j=0
3 14 33 45 56
j=4
14 33 45 56
An alisis de la eciencia
Caso peor
n
(i 1) =
i=2
n(n 1) 2 (n ) 2
Caso mejor
n
1 = n 1 (n)
i=2
1 ci = 2(i 1) + i
n n
i2
k
k=1
(i 1)(i + 2) i+1 1 = 2i 2 i n2 + 3 n 2 = Hn (n ) 4
ci =
i=2 i=2
1 i+1 2 i
donde Hn =
n 1 i=1 i (log n)
Algoritmo: Argumentos:
Selecci on directa A: vector A[l, . . . , r], l: ndice de la primera posici on del vector, r: ndice de la u ltima posici on del vector
void seleccion directa(int *A,int l,int r) { int i,j,min,aux; for(i=l;i<r;i++){ min=i; for(j=i+1;j<=r;j++) if (A[j]<A[min]) min=j; aux=A[i]; A[i]=A[min]; A[min]=aux; } }
Ejemplo de funcionamiento:
0 1 2 3 4
45 56 33 14 3
i min
45 56 33 14 3
min
3 56 33 14 45
min
3 14 33 56 45
min
3 14 33 56 45
3 14 33 45 56
An alisis de la eciencia
N umero de comparaciones:
n1
ni=
i=1
n(n 1) (n2) 2
10
2. Se ordenan indepedientemente cada uno de los subvectores. 3. Se mezclan los dos subvectores ordenados de manera que se obtenga un nuevo vector ordenado de talla N .
11
Ejemplo
1 2 3 4 5 6 7 8
5 2 4 6 1 3 2 6 5 2 4 6 5 2 5 2 2 5 4 4 6 6 4 6 1 3 2 6 1 3 1 1 3 3 2 6 2 2 6 6
2 4 5 6
1 2 3 6
1 2 2 3 4 5 6 6
12
... ...
...
ordenado
m m+1
...
ordenado
... ...
...
ordenado
13
Algoritmo: Argumentos:
Merge A: vector A[l, . . . , r ], l: ndice de la primera posici on del vector, m: ndice de la posici on que separa las dos partes ordenadas r: ndice de la u ltima posici on del vector
void merge(int *A, int l, int m, int r){ int i,j,k, *B; B = (int *) malloc((r-l+1) * sizeof(int)); i = l; j = m + 1; k = 0; while ( (i<=m) && (j<=r) ){ if (A[i] <= A[j]){ B[k] = A[i]; i++; }else{ B[k] = A[j]; j++; } k++; }
14
while (i<=m){ B[k] = A[i]; i++; k++; } while (j<=r){ B[k] = A[j]; j++; k++; } for(i=l;i<=r;i++) A[i]=B[i-l]; free(B);
}
Coste temporal del algoritmo de mezcla = (n).
15
Algoritmo Mergesort
Algoritmo: Argumentos: Mergesort A: vector A[l, . . . , r], l: ndice de la primera posici on del vector, r: ndice de la u ltima posici on del vector
void mergesort(int *A,int l,int r) { int m; if (l<r){ m = (int) ((l+r)/2); mergesort(A,l,m); mergesort(A,m+1,r); merge(A,l,m,r); } }
16
0
1
2
3
4
5
6
45 56 47 14 50 8 3
(1) mergesort(A,0,3)
8 3 14 45 47 50 56
(11) mergesort(A,4,6)
(18) merge(A,0,3,6)
45 56 47 14 14 45 47 56
(10) merge(A,0,1,3)
50 8 3
8 3 50
(17) merge(A,4,5,6)
(2) mergesort(A,0,1)
(6) mergesort(A,2,3)
(12) mergesort(A,4,5)
(16) mergesort(A,6,6)
45 56
(3) mergesort(A,0,0) 0
45 56
47 14
14 47
50 8
8 50
(7) mergesort(A,2,2) 1 2 3
(13) mergesort(A,4,4)
45
56
47
14
50
17
An alisis de la eciencia
Supondremos por simplicidad que n es una potencia de 2:
T ( n) =
Resolviendo por sustituci on:
c1 2T ( n 2 ) + c2 n + c3
n=1 n>1
T ( n)
= = = = = =
(p = log2 n)
n 2T ( ) + c2n + c3 2 n n 2(2T ( 2 ) + c2 + c3) + c2n + c3 2 2 n 2 2 T ( 2 ) + 2c2n + c3(2 + 1) 2 n 2 3 2 T ( 3 ) + 3c2n + c3(2 + 2 + 1) 2 p iteraciones . . . n p p1 2 2 T ( p ) + pc2n + c3(2 + . . . + 2 + 2 + 1) 2 nc1 + c2n log2 n + c3(n 1) (n log n)
c1 T (n 1) + c2n + c3
n=1 n>1
= c1 + (n 1)c3 + c2
i=2
i (n 1) (n2) 2
19
= c1 + (n 1)c3 + c2(n + 2)
20
...
1 q
...
N
2. Aplicar el mismo m etodo repetidamente a cada uno de los subvectores hasta obtener subvectores de talla 1, as se obtendr a la ordenaci on del vector original.
...
1 q
...
N
... ...
1 q q
...
q
...
N
. . . ...
21
Algoritmo de partici on
Problema: Dividir un vector en dos de manera que todos los elementos de la primera parte sean menores o iguales que los de la segunda. Funcionamiento: Dado un vector A[1, . . . , N ] 1. Elegir el primer elemento del vector como pivote x = A[1]. 2. Usando un ndice i, recorrer incrementalmente desde la posici on 1 una regi on A[1, . . . , i] hasta encontrar un elemento A[i] x. 3. Usando un ndice j , recorrer decrementalmente desde la posici on N una regi on A[j, . . . , N ] hasta encontrar un elemento A[j ] x. 4. Intercambiar A[i] y A[j ]. 5. Mientras i < j , repetir los pasos (2,3,4) iniciando el recorrido incremental y decremental desde las u ltimas posiciones i j , respectivamente. 6. El ndice j , donde 1 j < N , indicar a la posici on que separa las dos partes del vector A[1, . . . , j ] A[j + 1, . . . , N ], tal que todo elemento de A[1, . . . , j ] ser a menor o igual que todo elemento de A[j + 1, . . . , N ]
22
} }
return(j);
23
5
i
2 6
4 1
3 7
r
x=5
j
5
i
2 6
4 1
3 7
j r
x=5
3
i
2 6
4 1 5 7
j r
x=5
2 6
i
4 1
j
5 7
r
x=5
2 1
i
4 6
j
5 7
r
x=5
2 1
4 6 5 7
j q r i
x=5
2 1
4 6
5 7
x=5
A[l,...,q]
A[q+1,...,r]
24
Algoritmo Quicksort
Algoritmo: Argumentos: Quicksort A: vector A[l, . . . , r], l: ndice de la primera posici on del vector, r: ndice de la u ltima posici on del vector
void quicksort(int *A, int l, int r){ int q; if (l<r){ q = partition(A,l,r); quicksort(A,l,q); quicksort(A,q+1,r); } }
25
5 3 2 6 4 1 3 7
(1) partition(A,0,7)
0 1 2 3 4 5 6 7
3 3 2 1 4 6 5 7
q=4 (2) quicksort(A,0,4)
0 1 2 3 4 5
(15) quicksort(A,5,7)
6 7
3 3 2 1 4
(3) partition(A,0,4)
0 1 2 3 4
6 5 7
(16) partition(A,5,7)
5 6 7
1 2 3 3 4
q=1 (4) quicksort(A,0,1)
0 1
5 6 7
q=5 (18) quicksort(A,6,7)
6
1 2
(5) partition(A,0,1)
0 1
3 3 4
(9) partition(A,2,4)
6 7
5
(19) partition(A,6,7)
6
1 2
q=0 (6) quicksort(A,0,0)
3 3 4
q=2
6 7
q=6
(7) quicksort(A,1,1)
(10) quicksort(A,2,2)
(21) quicksort(A,7,7)
3 4
6
7
(12) partition(A,3,4)
3 4
6
7
3 4
q=3 (13) quicksort(A,3,3)
(14) quicksort(A,4,4)
4
4
26
An alisis de la eciencia
Caso peor T (n) = = T (n) (n2). c1 T (n 1) + c2n + c3 n=1 n>1
27
Caso medio A
1 n1
Probabilidad
1 n 1 n 1 n 1 n
...
1 n1
n1 n1 n2 n3 ... 2 1
...
2 n2
...
3 n3
...
...
n2
...
1 n 1 n
...
n1 1
n2 n1
...
28
T (n) =
1 T (1) + T (n 1) + (T (q ) + T (n q )) + (n) n q =1
n1
Dado que T (1) = (1) y, en el caso peor, T (n 1) = O(n2) , 1 1 (T (1) + T (n 1)) = ((1) + O(n2) = O(n) n n podemos reescribir T (n) como:
T (n) =
1 (T (q ) + T (n q )) + (n) n q=1
n1
29
Para k = 1, 2, . . . , n 1 cada t ermino T (k ) ocurre una vez como T (q ) y otra como T (n q ), por lo tanto:
T (n) =
2 n c1
2 n
n1
T (k ) + (n)
k=1
T (n) =
n1 k=1 T (k )
+ c2n
n1 n>1
Por inducci on n > 1, T (n) c3 n log2 n, donde c3 = 2c2 + c1, y por tanto: = T (n) O(n log n)
30
31
32
...
N
2. Debido a que, una vez ordenado el vector, el k - esimo menor elemento ocupar a la posici on k , si se cumple que 1 k q u nicamente ser a necesario ordenar el subvector A[1, . . . , q ]; mientras que si, por el contrario, q < k N u nicamente ser a necesario ordenar el subvector A[q + 1, . . . , N ].
33
Algoritmo: Argumentos:
int seleccion(int *A, int n, int k){ int l,r,q; l = 0; r = n-1; k = k-1; while (l<r){ q = partition(A,l,r); if (k<=q) r=q; else l=q+1; } return(A[l]); }
34
seleccion(A,10,4)
0 1 2 3 4 5 6 7 8 9
31 23 90 0 77 52 49 87 60 15
partition(A,0,9)
0 1 2 3 4 5 6 7 8
r
9
15 23 0 90 77 52 49 87 60 31
q=2
3 4 5 6 7 8 9
90 77 52 49 87 60 31
r
partition(A,3,9)
3 4 5 6 7 8 9
31 77 52 49 87 60 90
q=8
3 4 5 6 7 8
31 77 52 49 87 60
r
partition(A,3,8)
3 4 5 6 7 8
31 77 52 49 87 60
q=3
3
31
r return(31)
35
An alisis de la eciencia
Caso peor: T (n) = = T (n) (n2) Caso mejor: T (n) = Resolviendo por sustituci on: c1 T (n 2 ) + c2 n + c3 n=1 n>1 c1 T (n 1) + c2n + c3 n=1 n>1
36
n T (n) = T ( ) + c2n + c3 2 n n = T ( 2 ) + (n + )c2 + 2c3 2 2 1 1 n = T ( 3 ) + c2n(1 + + 2 ) + 3c3 2 2 2 = p iteraciones . . . n 1 1 1 = T ( p ) + c2n(1 + + 2 + . . . + p1 ) + pc3 2 2 2 2 n 2(2p 1) = T ( p ) + c2n + pc3 p 2 2 (p = log2 n) = c1 + 2c2(n 1) + c3 log2n O(n) Caso medio: caso mejor = T (n) O(n).
37
B usqueda binaria
Problema: Dado un vector A ordenado por orden no decreciente de n enteros, buscar la posici on correspondiente a un elemento x. Estrategia: Dado un vector A[1. . . n] y un elemento x: Tomar el elemento de la mitad del vector A[q ], con q =n/2. Si x=A[q ] entonces la posici on buscada es q sino: Si x <A[q ] entonces aplicar el mismo criterio de b usqueda en el vector A[1. . . q -1]. Si x >A[q ] entonces aplicar el mismo criterio de b usqueda en el vector A[q +1. . . n].
38
Algoritmo: Argumentos:
B usqueda binaria A: vector A[l, . . . , r], l: ndice de la primera posici on del vector, r: ndice de la u ltima posici on del vector, x: elemento del vector a buscar
int busqueda binaria(int *A, int l, int r, int x){ int q; if (l==r) if (x==A[l]) return(l); else return(-1); else { q = (int) (l+r)/2; if (x == A[q]) return(q); else if (x < A[q]) return(busqueda binaria(A,l,q-1,x)); else return(busqueda binaria(A,q+1,r,x)); } }
39
1 3 7 152233415260 q=4
0 1 2 3
1 3 7 15 q=1
0
1 A[0]=1 = return(0)
40
An alisis de la eciencia
T (n) = Resolviendo por sustituci on: c1 T (n 2 ) + c2 n=1 n>1
41
int potencia(int b, int n){ int res, i; res = 1; for (i=1; i<=n; i++) res = res * b; return(res); } = Coste del algoritmo O(n).
42
bn =
b b b b b
si n es par si n es impar
int potencia(int b, int n){ int res, aux; if (n == 0) res = 1; else{ aux = potencia(b,n/2); if ((n % 2) == 0) res = aux * aux; else res = aux * aux * b; } return(res); }
43
An alisis de la eciencia
T (n) = = T (n) O(log n). c1 T (n 2 ) + c2 n<1 n1
44
45
Arboles
Deniciones
Arbol de tipo base T : 1. Un conjunto vac o es un arbol, 2. Un nodo n de tipo T , junto con un n umero nito de conjuntos disjuntos de elementos de tipo base T , llamados sub arboles, es un arbol. El nodo n se denomina ra z. n es padre de las ra ces de los sub arboles. Las ra ces de los sub arboles son hijos de n.
A B E C F D J
GH I K LM
1
Deniciones (II)
Camino de n1 a nk : sucesi on de nodos de un arbol n1, n2, . . . , nk , en la que ni es padre de ni+1 para 1 i < k . Longitud de un camino: n umero de nodos del camino menos 1. Hay un camino de longitud cero de cualquier nodo a s mismo. Si existe un camino de un nodo ni a otro nj , entonces ni es un antecesor de nj , y nj es un descendiente o sucesor de ni. Antecesor propio o Descendiente propio: un antecesor o un descendiente de un nodo que no sea el mismo. En un camino n1, n2, . . . , nk , ni es antecesor directo de ni+1, y ni+1 es descendiente directo de ni, para 1 i < k .
Deniciones (III)
Hoja o nodo terminal: nodo sin descendientes propios. Nodo interior: nodo con descendientes propios. Grado de un nodo: n umero de descendientes directos que tiene. Grado de un arbol: m aximo de los grados de todos los nodos del arbol. Nivel: 1. La ra z del arbol est a a nivel 1. 2. Si un nodo est a en el nivel i, entonces sus descendientes directos est an al nivel i + 1. Altura de un nodo: longitud del camino m as largo desde ese nodo hasta una hoja. Altura del arbol: altura del nodo ra z. Profundidad de un nodo: longitud del camino u nico desde la ra z hasta ese nodo.
3
Recorrido de arboles
recorrido en orden previo (preorden). recorrido en orden sim etrico (inorden). recorrido en orden posterior (postorden). Dependiendo del tipo de recorrido: si A es vac o no realizar acci on P ; si A contiene un u nico nodo realizar acci on P sobre ese nodo; si A tiene ra z n y sub arboles A1, A2, . . . , Ak Preorden: realizar acci on P sobre n, y, despu es, recorrer en preorden los sub arboles A1, A2, . . . , Ak de izquierda a derecha. Inorden: recorrer en inorden el sub arbol A1, despu es realizar acci on P sobre n, y, despu es, recorrer en inorden los sub arboles A2, . . . , Ak de izquierda a derecha. Postorden: recorrer en postorden los sub arboles A1, A2, . . . , Ak de izquierda a derecha, y despu es realizar acci on P sobre n.
Ejemplo:
A B E C F D J
GH I K LM
Preorden: acci on P se realizar a en este orden: A, B , C , E , G, H , I , F , D, J , K , L, M . Inorden: acci on P se realizar a en este orden: B , A, G, E , H , I , C , F , K , J , L, M , D. Postorden: acci on P se realizar a en este orden: B , G, H , I , E , F , C , K , L, M , J , D, A.
Ejemplo:
Evaluar expresi on artim etica con precedencia de operadores representada mediante un arbol evaluar primero los operandos de cada operador (recorrido postorden).
|| || | || ||
BB BB BB BB B
/
11 11 11
22 22 22
44 44 44
30
44 44 44
+ 2
22 22 22
+ 2
22 22 22
30
/
+ 30 3
/
== == == ==
?? ?? ?? ??
Estructura de datos: 1. Vector v con la informaci on de cada nodo. 2. Cada elemento (nodo) del vector apunta a una lista enlazada de elementos (nodos) que indican cu ales son sus nodos hijos. 3. Un ndice a la ra z.
7 3 1 5 8 12 11
1
/
8 5
3
/ / /
12
4 2 6 9 13 10
9 11
/
13
/
10
...
10
11
A
/
A B E C F D J
B
/
C E F
/ /
D
/
J
/
GH I K LM
G
/
H
/
I
/ /
K
/
L
/
M
/ /
12
A
/
A B E C F D J
B
/
C E F
/
D J I
/
GH I K LM
G
/
H
/
K
/
L
/
M
/
13
14
} }
15
Arboles binarios
Arbol binario: conjunto nito de nodos tal que, o est a vac o, o consiste en un nodo especial llamado ra z. El resto de nodos se agrupan en dos arboles binarios disjuntos llamados sub arbol izquierdo y sub arbol derecho. nodo raiz A
B D G
subarbol izquierdo
C E F
subarbol derecho
A B E C F
17
A B D G E C F
/ / / 5 / 4 / / 7 /
/ F / A D B C G E
. . .
/ / / 6 / 8 1 / / /
0 1 2 3 raiz 4 5 6 7 8 N1
Denici on de tipos en C: #define N ... typedef ... tipo_baseT; typedef struct{ tipo_baseT e; int hizq, hder; } nodo; typedef struct{ int raiz; nodo v[N]; } arbol;
18
19
C E F D
/ /
B E
/
C
/
F
/ /
Denici on de tipos en C: typedef ... tipo_baseT; typedef struct snodo{ tipo_baseT e; struct snodo *hizq, *hder; } arbol;
20
A
/
A B D G G
Denici on de tipos en C:
/ /
C E F D
/ /
B
/
C E
/
F
/ /
typedef ... tipo_baseT; typedef struct snodo{ tipo_baseT e; struct snodo *hizq, *hder, *padre; } arbol;
21
22
24
25
7 10 16 3 11 5
1 4 13 2 19
26
27
28
M aximo nodos por nivel Nivel 1 20 = 1 Nivel 2 21 = 2 Nivel 3 22 = 4 Nivel 4 23 = 8 M aximo nodos en el arbol 24 1 = 15 N umero de hojas (n0) n2 = 7 n0 = n2 + 1 = 7 + 1 = 8 Altura del arbol binario completo n = 15 log2 n = log2 (15) = 3
29
Conjuntos
Conceptos generales
Conjunto: colecci on de elementos distintos; cada elemento puede ser un conjunto, o un atomo. Multiconjunto conjunto con elementos repetidos. Representaci on de conjuntos: Representaci on expl cita. C = {1, 4, 7, 11} Representaci on mediante propiedades. C = {x N | x es par}
Notaci on
Relaci on fundamental: pertenencia () x A, si x es un miembro del conjunto A. x / A, si x no es un miembro de A. Cardinalidad o talla: n umero de elementos que contiene un conjunto. Conjunto vac o o nulo: no tiene miembros, . A B o B A, si todo miembro de A tambi en es miembro de B . Dos conjuntos son iguales sii A B y B A. Subconjunto propio: A = B y A B .
Modicadoras: Insertar(S ,x): A nade x a S . Borrar(S ,x): Elimina x de S . Crear(S ): Crea S vac o.
5
clave
0 1 1 2 2
informacion
0 1 2 3 4 5
5
1 2
3 4 4
6
6
7 8
. . .
M1
M1
. . .
K
k2 k1 k5
3 4 5
k7
h(k1)
6 7 8
h(k5)
h(k7)
. . .
M1
10
K
k9
2 3
k2 k1 k5 k7 k8 k1 k8
L
k3
k6
4 5
k4
6 7 8
k5
k4
k7
k3
. . .
M1
11
12
Borrar (1 + ) O(1)
13
Funciones de dispersi on
Funci on ideal satisface la dispersi on uniforme simple: cada elemento con igual probabilidad de dispersarse en las m cubetas. Dicultad de encontrar funci on con esta condici on. Usamos funciones que dispersen de forma aceptable los elementos entre las cubetas. Universo de claves conjunto de n umeros naturales N = {0, 1, 2, . . . }. Representaci on de claves como n umeros naturales. Ej: cadena de caracteres combinar la representaci on ASCII de sus caracteres.
14
15
16
h(x) = (
i=0
xi) mod m
Inconvenientes: m , mala distribuci on de las claves. Ej: m = 10007, cadenas de longitud 10 m aximo valor de x: 255 10 = 2550. Cubetas desde 2551 a 10006 vac as. El orden de los caracteres no se tiene en cuenta. h(cosa)=h(saco).
17
h(x) = (
i=0
xi 256i) mod m
Inconvenientes: Cadenas con tres primeros caracteres iguales misma cubeta. h(clase)=h(clarinete)=h(clan). Funci on 3: Similar a funci on 2, considerando toda la cadena.
n1
h(x) = (
i=0
xi 256((n1)i)) mod m
h(x) =
m (((
i=0
xi 2((n1)i)) A) mod 1)
19
34 32 30 28 26 24 22 elemento por cubeta 20 18 16 14 12 10 8 6 4 2 0 0 250 500 750 1000 cubeta 1250 1500 1750 2000 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 numero de elementos 1 numero de cubetas
100
10
20
1000
numero de cubetas
150
10
100 1 50
0 0 250 500 750 1000 cubeta 1250 1500 1750 2000 0 25 50 75 100 125 150 175 numero de elementos 200 225 250 275 300
21
10 1000 9 8 7 elementos por cubeta 6 5 4 3 1 2 1 0 0 250 500 750 1000 cubeta 1250 1500 1750 2000 0 1 2 3 4 5 numero de elementos 6 7 8 9 numero de cubetas
100
10
22
15 1000 14 13 12 11 10 elementos por cubeta 9 8 7 6 5 4 3 2 1 0 0 250 500 750 1000 cubeta 1250 1500 1750 2000 0 1 2 3 4 5 6 7 8 numero de elementos 9 10 11 12 13 14 1 numero de cubetas
100
10
23
100
10
m = 2000
50 alfa: 1.987; desv.tip: 7.83 45 40 35 elementos por cubeta 30 25 20 15 1 10 5 0 0 250 500 750 1000 cubeta 1250 1500 1750 2000 0 5 10 15 20 25 numero de elementos 30 35 40 45 numero de cubetas
1000
100
10
24
100
10
m = 2000
16 alfa: 1.987; desv.tip: 1.8 14 1000 12 100 elementos por cubeta numero de cubetas
10
10
0 0 250 500 750 1000 cubeta 1250 1500 1750 2000 0 1 2 3 4 5 6 7 8 9 numero de elementos 10 11 12 13 14 15
25
26
27
28
18
10
21
8
14
SI
15 18 21
NO
29
15 7 3 11 9 18
/
21
/ /
/ /
30
15 7 3 11 9 18
/
21
/ /
/ /
/ /
31
15 7
18
/
3
/ /
11
/
/ /
21
9
/ /
32
logn
. . .
...
. . .
. .
Altura m axima
Altura m nima Notaci on: Altura del arbol = h. Normalmente, altura de un abb aleatorio O(log n)
33
abb *abb_buscar(abb *T, tipo_baseT x){ while ( (T != NULL) && (x != T->clave) ) if (x < T->clave) T = T->hizq; else T = T->hder; return(T); } Coste: O(h).
35
36
T 7 3
15
T
15 18
/
15 18
/
7 21
/ /
7 21
/ /
18
/
/ /
11 9
/ /
11 9
/ /
11 9
21
/ /
/ /
/ /
/ /
T=T>hizq;
T=T>hder;
return(T);
37
T 7 3
15 18
/
15
T
15 18
/
15 18
/
7 21
/ /
7 21
/ /
7 3 11 9
18
/
/ /
11 9
/ /
11 9
/ /
11 9
21
/ /
21
/ /
/ /
T=NULL
/ /
/ /
/ /
/ /
T=T>hder;
T=T>hder;
T=T>hizq;
return(T);
38
15 18
/
15 18
/
7 21
/ /
7 11 9
18
/
M nimo:
/ /
11 9
/ /
11 9
21
/ /
/ /
21
/ /
/ /
/ /
/ /
T=T>hizq;
T 7 15 18
/
T=T>hizq;
15
T
return(T);
15
7 21
/ /
18
/
7 21
/ /
18
/
M aximo:
/ /
11 9
/ /
11 9
/ /
11 9
21
/ /
/ /
/ /
/ /
T=T>hder;
T=T>hder;
return(T);
40
41
}
42
aux_padre aux 7
15
T 18
/
aux_padre 7
21
/ /
15
aux 18 / 11 9 21
/ / /
21
/ /
/ /
/ /
11 9
/ /
/ /
/ /
/ /
18
/
/ /
11 9
21
/ /
21
/ /
aux_padre
/
/ /
aux
/ /
aux_padre
aux=null
10
/ /
nodo
44
15
aux
aux_padre=null
T=NULL; free(aux); return(T);
15 18
/
7
21
/
/ /
/ /
11
/
21
/
aux_padre aux
20
/ /
/ /
20
/ /
return(T);
45
T 7 3
15
aux_padre 18
/
T 7
15 18 11 9
/ /
/ /
11 9
21
/ /
/ /
aux
/ /
/ /
return(T);
46
15
aux 18
/
aux_padre=null
T
21
/ /
18
/
21
/ /
T=aux->hder; free(aux);
T aux 7
/
return(T);
Borrar x = 7. Nodo interno que es hijo izquierdo y tiene un u nico hijo derecho.
15 18
/
aux_padre
T
21
/ /
15 18
/
11 9
11 9
21
/ /
/ /
/ /
return(T);
47
15
aux_padre 18 aux 21
/
/
T 7
/
15 18 16 25
3 5
16
/ /
3 5
/ /
/ /
25
/ /
/ /
/ /
return(T);
Borrar x = 15. Nodo interno que es ra z del arbol y tiene un u nico hijo izquierdo.
aux aux_padre=null
T 3
7 11 9
/ /
/ /
/ /
/ /
T=aux->hizq; free(aux);
return(T);
48
T 7
15 18
/
21
/ /
1
/ /
11 9
21
/ /
/ /
/ /
/ /
return(T);
T 7
/
Borrar x = 19. Nodo interno que es hijo derecho y tiene un u nico hijo izquierdo.
15 19 17
/
aux_padre aux
/
15 17
/
3 5
3 5
18
/ /
18
/ /
/ /
/ /
return(T);
49
T 7
/
15 18 17
aux_padre aux p1 25
/
T 7
/
15 25 17 31
/
3 5
p2=null 31
/
/ /
/ /
3 5
/ /
26
/ /
26
/ /
/ /
return(T);
50
10
aux aux_padre=null 18
T 7
12 18 16
/
p2
/
16
/
25
/
p1
12 15
/
31
/
25
/
26
/ /
15
/
31
/
13
/ /
13
/ /
26
/ /
return(T);
51
typedef ... tipo_baseT; typedef struct snodo{ tipo_baseT clave; struct snodo *hizq, *hder; }abb; abb *T;
Coste: O(n).
52
53
54
16 14 10 8 7
3 2 4
16 14 10 8 7
3 2 4
...
tamanyo
talla_Heap
55
56
funci on heapify: mantiene propiedad de mont culo. Transformar sub arbol de un mont culo. Sub arboles izquierdo y derecho de i son mont culos.
57
3 10 5 6 9 3 7 M
1 2 3 4 5 6 7 8 9 10 tamanyo
16 4 10 14 7 i hizq hder
3 2 8
...
talla_Heap
3
tamanyo
16 4 10 14 7 i mayor
3 2 8
...
talla_Heap
59
3
tamanyo
16 14 10 4 7 i
3 2 8 1
...
1 16 2 14 4 i 4 8 9 10 2 1 8 mayor 5 7 6 9 3 10 7 M
1 2 3 4 5 6 7 8 9 10
3
tamanyo
16 14 10 4 i
3 2 8 mayor
...
talla_Heap
60
3
tamanyo
16 14 10 8 7
3 2 4 i mayor
...
9 10 2 4 i 1 mayor
talla_Heap
61
build Heap(M,10);
63
Heapify(M,5);
1 4 2 1 4 2 8 14 1 4 2 1 9 10 7 8 3 3 4 2 5 16 6 9 7 10 8 14 9 8 10 7 talla_Heap 16 5 6 9 10 3 7 3
Heapify(M,5); //
64
Heapify(M,4);
1 4 2 1 4 14 i 8 2 1 4 2 1 9 10 8 7 3 3 4 14 5 16 6 9 7 10 8 2 9 8 10 7 talla_Heap 16 5 6 9 10 3 7 3
Heapify(M,4); //
65
Heapify(M,3);
1 4 2 1 4 14 8 2 1 4 2 1 9 10 7 8 3 4 10 14 5 6 16 9 7 3 8 2 9 8 10 7 talla_Heap 16 5 6 9 3 3 10 7
Heapify(M,3); //
66
1 4 2 i 1 4 14 8 2 1 4 2 1 i 9 10 8 7 3 4 10 14 5 6 16 9 mayor 7 3 8 2 9 8 10 7 talla_Heap 5 6 3 3 10 7
9 16 mayor
Heapify(M,2);
1 4 2 16 4 14 8 2 1 4 2 16 9 10 8 7 3 10 4 14 5 1 6 9 7 3 8 2 9 8 10 7 talla_Heap 1 5 6 9 3 3 10 7
heapify(M,2); heapify(M,5);
67
heapify(M,5);
1 4 2 16 4 14 8 2 M 1 4 2 16 9 10 1 8 3 10 4 14 5 7 6 9 7 3 8 2 9 8 10 1 talla_Heap 7 5 6 9 3 3 10 7
heapify(M,5); // heapify(M,2); //
68
1 i 4 2 mayor 16 4 14 8 2 9 10 1 8 4 14 5 7 6 9 7 3 8 2 9 8 10 1 talla_Heap 7 5 6 9 3 3 10 7
1 2 3 M 4 16 10 i mayor
heapify(M,1);
1 16 2 4 4 14 8 2 1 M 16 2 4 9 10 8 1 3 10 4 14 5 7 6 9 7 3 8 2 9 8 10 1 talla_Heap 7 5 6 9 3 3 10 7
heapify(M,1); Heapify(M,2);
69
heapify(M,2);
1 16 2 14 4 4 8 2 1 M 16 2 14 9 10 8 1 3 10 4 4 5 7 6 9 7 3 8 2 9 8 10 1 talla_Heap 7 5 6 9 3 3 10 7
heapify(M,2); Heapify(M,4);
70
1 16 2 14 4 i 4 8 2 1 M 16 7 5 6 9 3 3 10 7
10 9 8 1 mayor 3 4 5 2 14 10 4 7 i
6 9
7 3
talla_Heap 8 9 10 2 8 1 mayor
heapify(M,4);
1 16 2 14 4 8 8 2 1 M 16 2 14 9 4 8 7 10 5 7 6 9 7 3 8 2 9 4 10 1 talla_Heap 5 6 9 3 3 10 7
4 3 10
1 0
. . .
...
Nh 2
. . .
log2 n h
[log(n)] [log(n)]+1
[log(n)]1
[log(n)]
log2 n
2h
72
log2 n
log2 n
T (n) =
h=0
NhO(h)
h=0
log2 n
log2 n
2h
h
h=0
h 2log2n h = n 2
log2 n
h
h=0
1 2
Como
h h=0 hx
log2 n
n
h=0
1 2
1/2 n (1 1/2)2
= 2n O(n)
73
M
1 2
n2 n1 n
tallaH
n2 n1 n
<=
n2 n1
tallaH
M tallaH
M heapify
1 2
n1
tallaH
n2 n1 n
M
1 2
tallaH
n2 n1 n
M heapify
1 2
tallaH
n3 n2 n1 n
...
1 2
tallaH
M tallaH heapify
1 2 3
M tallaH
1 2 3
M tallaH heapify
1 2 3
M tallaH
1
75
76
1 1 3 10 7
4 4 9 7 2 8 5 14
1 3 10 6 9 3 7
i 8 3 4 1 2 5 6 7 9 10 16 14 10 8 7 9 3 2 4 1 tallaH
1 2 3 4 5 6 7 8 1 14 10 8 7 9 3 2
1 2 3 4 5 6 7 8 14 8 10 4 7 9 3 2
9 10 1 16 tallaH
M[1] M[i];
heapify(M,1);
n iteraci on i = 10;
77
1 14 2 8 4 4 8 2 9 1 i 7 5 6 9 3 3 10 7
1 1 2 8 4 4 8 2
i 9 10 1 16 tallaH
1 10 3 10 2 8 7 4 4 8 2 1 2 3 4 5 6 7 8 9 10 10 8 9 4 7 1 3 2 14 16 tallaH 7 5 6 1 3 9 7 3
5 7
6 9 3
1 2 3 4 5 6 7 8 14 8 10 4 7 9 3 2
1 2 3 4 5 6 7 8 9 10 1 8 10 4 7 9 3 2 14 16 tallaH
M[1] M[i];
1 10 2 8 4 4 8 i 2 i 1 2 3 4 5 6 7 8 9 10 10 8 9 4 7 1 3 2 14 16 tallaH 7 5 6 1 3 9 7 4 4 3
heapify(M,1);
1 2 2 8 5 7 6 1 3 9 7 4 4 3
n iteraci on i = 9;
1 9 2 8 5 7 6 1 2 3 7 3
1 2 3 4 5 6 7 8 9 10 2 8 9 4 7 1 3 10 14 16 tallaH
1 2 3 4 5 6 7 8 9 10 9 8 3 4 7 1 2 10 14 16 tallaH
M[1] M[i];
heapify(M,1);
n iteraci on i = 8;
78
1 9 2 8 4 4 7 5 6 1 3 i 2 7 4 4 7 3 2 8 5 2
1 8 3 3 6 1 4 4 2 2 7 5
1 3 3 6 1
i 1 2 3 4 5 6 7 8 9 10 9 8 3 4 7 1 2 10 14 16 tallaH
1 2 3 4 5 6 7 8 9 10 2 8 3 4 7 1 9 10 14 16 tallaH
1 2 3 4 5 6 7 8 9 10 8 7 3 4 2 1 9 10 14 16 tallaH
M[1] M[i];
1 8 2 7 4 4 2 5 6 1 i 3 3
heapify(M,1);
1 1 2 7 4 4 2 5 3 4 1 3
n iteraci on i = 7;
1 7 2 4 5 2 3 3
i 1 2 3 4 5 6 7 8 9 10 8 7 3 4 2 1 9 10 14 16 tallaH
1 2 3 4 5 6 7 8 9 10 1 7 3 4 2 8 9 10 14 16 tallaH
1 2 3 4 5 6 7 8 9 10 7 4 3 1 2 8 9 10 14 16 tallaH
M[1] M[i];
heapify(M,1);
n iteraci on i = 6;
79
1 7 2 4 4 1 i 5 2 3 4 1 3 2 4 2
1 4 3 3 4 1 2 2
1 3 3
i 1 2 3 4 5 6 7 8 9 10 7 4 3 1 2 8 9 10 14 16 tallaH
1 2 3 4 5 6 7 8 9 10 2 4 3 1 7 8 9 10 14 16 tallaH
1 2 3 4 5 6 7 8 9 10 4 2 3 1 7 8 9 10 14 16 tallaH
M[1] M[i];
1 4 2 2 4 1 i 1 2 3 4 5 6 7 8 9 10 4 2 3 1 7 8 9 10 14 16 tallaH i 3 3 2
heapify(M,1);
1 1 3 2 3
n iteraci on i = 5;
1 3 2 2 1 3
1 2 3 4 5 6 7 8 9 10 1 2 3 4 7 8 9 10 14 16 tallaH
1 2 3 4 5 6 7 8 9 10 3 2 1 4 7 8 9 10 14 16 tallaH
M[1] M[i];
heapify(M,1);
n iteraci on i = 4;
80
1 3 2 3 2 2 2 1 i i 1 2 3 4 5 6 7 8 9 10 3 2 1 4 7 8 9 10 14 16 tallaH 1
1 2 2 1
1 2 3 4 5 6 7 8 9 10 1 2 3 4 7 8 9 10 14 16 tallaH
1 2 3 4 5 6 7 8 9 10 2 1 3 4 7 8 9 10 14 16 tallaH
M[1] M[i];
1 2 2 i i 1 2 3 4 5 6 7 8 9 10 2 1 3 4 7 8 9 10 14 16 tallaH 1
heapify(M,1);
1 1
n iteraci on i = 3;
1 2 3 4 5 6 7 8 9 10 1 2 3 4 7 8 9 10 14 16 tallaH
1 2 3 4 5 6 7 8 9 10 1 2 3 4 7 8 9 10 14 16
M[1] M[i];
heapify(M,1);
81
82
Colas de prioridad
Aplicaci on usual de mont culos. Cola de prioridad conjunto S de elementos, cada uno de los cuales tiene asociado una clave (prioridad). Operaciones asociadas: Insert(S,x): inserta x en el conjunto S . Extract Max(S): borra y devuelve el elemento de S con clave mayor. Maximum(S): devuelve el elemento de S con clave mayor. planicaci on de procesos en un sistema compartido.
83
84
85
1
16
3 10 7
4 8
2 14 5 7 9 10 4 1 i 6 9
3 10 7 3
1 2 3 4 5 6 7 8 9 10 16 14 10 8 7 9 3 2 4 1 tallaH
i 8 1 2 3 4 5 6 7 9 10 11 16 14 10 8 7 9 3 2 4 1 tallaH
arbol inicial
86
1 16 2 14 4 8 8 2 i 9 10 4 1 5 6 9 3 8 2 3 10 7 4 8 9 10 4 1 14 2 i 5 16
1 16 3 10 6 9 3 8 2 7 4 8 9 10 4 1 14 2 i 15 5
1 3 10 6 9 3 7
1 2 3 4 5 6 7 8 9 10 11 16 14 10 8 7 9 3 2 4 1 7 i tallaH
1 2 3 4 5 6 7 8 9 10 11 16 14 10 8 14 9 3 2 4 1 7 i tallaH
1 2 3 4 5 6 7 8 9 10 11 16 15 10 8 14 9 3 2 4 1 7 i tallaH
M[i]=M[i/2]; i=i/2;
M[i]=M[i/2]; i=i/2;
M[i]=x;
87
88
89
tipo_baseT extract_max(tipo_baseT *M){ tipo_baseT max; if (talla_Heap == 0){ fprintf(stderr,"Mont culo vac o"); exit(-1); } max = M[1]; M[1] = M[talla_Heap]; talla_Heap--; heapify(M,1); return(max); }
90
1 2 3 4 5 6 7 8 9 10 16 14 10 8 7 9 3 2 4 1 tallaH
1 2 3 4 5 6 7 8 9 10 16 14 10 8 7 9 3 2 4 1 tallaH
max=M[1];
91
1 1 2 14 4 8 8 2 9 7 5 6 9 3 8 2 3 10 7 4 4 9 7 2 8 5 14
1 3 10 6 9 3 7
1 2 3 4 5 6 7 8 9 1 14 10 8 7 9 3 2 4 tallaH
1 2 3 4 5 6 7 8 9 14 8 10 4 7 9 3 2 1 tallaH
return(max);
92
mont culo que representa una cola de prioridad: operaciones O(log n).
93
94
MF-set (II)
MF-set (Merge-Find set): estructura de n elementos (jos). No se pueden borrar ni a nadir elementos. Elementos organizados en clases de equivalencia. Subconjuntos identicados por representante: - elemento menor del subconjunto. - no importa el elemento. Si un subconjunto no es modicado mismo representante.
C
5 7 3 10 12 8
4 1 2 6
9 11
95
MF-set (III)
Operaciones: Union(x,y) (Merge): x Sx y y Sy uni on de Sx con Sy . El representante del nuevo subconjunto creado es alguno de sus miembros, normalmente se escoge al representante de Sx o al representante de Sy . Se eliminan los subconjuntos Sx y Sy . Buscar(x) (Find): devuelve el representante de la clase de equivalencia a la que pertenece x.
Aplicaciones: inferencia de gram aticas, equivalencias de aut omatas nitos, c alculo del arbol de expansi on de coste m nimo en un grafo no dirigido, etc.
96
Representaci on de MF-sets
Cada subconjunto un arbol: Nodo: informaci on del elemento. La ra z es el representante. Representaci on de arboles mediante apuntadores al padre: el que apunte a s mismo ser a ra z. MF-set: colecci on de arboles (bosque). Cada elemento n umero de 1 a n + vector M : posici on i ndice del padre de i.
1 4 12 10
11
1 2 3 4 5 6 7 8 9 10 11 12 M 1 1 2 4 4 4 9 10 8 10 9 12
97
11
1 2 3 M 1 1 2
4 5 6 7 8 9 10 11 12 10 4 4 9 10 8 10 9 12
98
1 2 3 M 1 1 2
4 5 6 7 8 9 10 11 12 10 4 4 9 10 8 10 9 12
11
99
100
10
6 10
4
8
5
9
11
11
101
Compresi on de caminos
Estrategia: Cuando se busca un elemento, hacer que todos los nodos del camino de b usqueda se enlacen directamente con la ra z. Combinando ambos heur sticos, coste de m operaciones de b usqueda: O(m(m, n)), con (m, n) inversa de la funci on de Ackerman, (crecimiento lento). Normalmente, (m, n) 4. En la pr actica, con ambos heur sticos hacer m operaciones de b usqueda tiene un coste casi lineal en m.
10
10
8
8
9
11
11
102
Tries
Tipo de arbol de b usqueda. Aplicaci on: diccionarios. Palabras con prejos comunes usan la misma memoria para dichos prejos. Compactaci on de prejos comunes ahorro de espacio.
103
Tries (II)
Ej: conjunto {pool, prize, preview, prepare, produce, progress}
104
105
Tries: Representaci on
Trie un tipo de aut omata nito determinista (AFD). Representaci on: matriz de transici on. Filas = estados. Columnas = etiquetas. Cada posici on de la matriz almacena el siguiente estado al que transicionar. Coste temporal muy eciente. La mayor a de nodos tendr an pocas aristas = gran cantidad de memoria desperdiciada.
106
Arboles Balanceados
Estructuras de datos para almacenar elementos. Permiten una b usqueda eciente.
Arbol balanceado: arbol donde ninguna hoja est a m as alejada de la ra z que cualquier otra hoja. Varios esquemas de balanceo (denici on diferente de m as lejos ). Diferentes algoritmos para actualizar el arbol.
107
Arboles AVL
Arbol AVL: arbol binario de b usqueda que cumple 1. Las alturas de los sub arboles de cada nodo dieren como mucho en 1. 2. Cada sub arbol es un arbol AVL. Inventores: Adelsson, Velskii y Landis. No est an balanceados perfectamente. Buscar, insertar y borrar un elemento O(log n).
12
11 5
18
17
11
17
12
18
108
Arboles 2-3
Arbol 2-3: arbol vac o (si tiene 0 nodos) o un nodo simple (si tiene un u nico nodo) o un arbol con m ultiples nodos que cumplen: 1. Cada nodo interior tiene 2 o tres hijos. 2. Cada camino desde la ra z a una hoja tiene la misma longitud. Nodos internos: p1 k1 p2 k2 p3 p1 : p2 : p3 : k1: k2: puntero al primer hijo. puntero al segundo hijo. puntero al tercer hijo (si existe). clave m as peque na descendiente del segundo hijo. clave m as peque na descendiente del tercer hijo.
109
110
111
B- arboles
Generalizaci on de los arboles 2-3. Aplicaciones: Almacenamiento externo de datos. Organizaci on de ndices en sistemas de bases de datos. Permite minimizar los accesos a disco para consultas a bases de datos.
112
B- arboles (II)
Arbol B de orden n: arbol de b usqueda n-ario que cumple La ra z es una hoja o tiene por lo menos dos hijos. Cada nodo, excepto el ra z y las hojas. tiene entre
n 2
y n hijos.
Cada camino desde la ra z a una hoja tiene la misma longitud. Cada nodo interno tiene hasta (n 1) valores de claves y hasta m punteros a sus hijos. Los elementos se almacenan en los nodos internos y en las hojas. Un B- arbol puede verse como un ndice jer arquico. La ra z ser a el primer nivel de indizado.
113
B- arboles (III)
Nodos internos: p1 k1 p2 k2 . . . . . . kn1 pn
pi es un puntero al i- esimo hijo, 1 i n. ki son los valores de las claves, (k1 < k2 < . . . < kn1 ) de manera que: todas las claves en el sub arbol p1 son menores que k1. Para 2 i n 1, todas las claves en el sub arbol pi son mayores o iguales que ki1 y menores que ki. Todas las claves en el sub arbol pn son mayores o iguales que kn1.
114
B- arboles +
Arbol B+: arbol B en el que las claves almacenadas en los nodos internos no son u tiles (s olo se usan para b usquedas). Todas las claves de nodos internos est an duplicadas en las hojas. Ventaja: las hojas est an enlazadas secuencialmente y se puede acceder a la informaci on de los elementos sin visitar nodos internos. Mejora la eciencia de determinados m etodos de b usqueda.
115
Grafos
Deniciones
Grafo modelo para representar relaciones entre elementos de un conjunto. Grafo: (V ,E ), V es un conjunto de v ertices o nodos, con una relaci on entre ellos; E es un conjunto de pares (u,v ), u,v V , llamados aristas o arcos. Grafo dirigido: la relaci on sobre V no es sim etrica. Arista par ordenado (u,v ). Grafo no dirigido la relaci on sobre V s es sim etrica. Arista par no ordenado {u,v }, u,v V y u=v
1 2 3
2 3
Deniciones (II)
Camino desde u V a v V : secuencia v1, v2, . . . , vk tal que u = v1, v = vk , y (vi1,vi) E , para i =2,. . . ,k . Ej: camino desde 3 a 2 <3,5,4,2>.
1 2 3
Longitud de un camino: n umero de arcos del camino. Camino simple: camino en el que todos sus v ertices, excepto, tal vez, el primero y el u ltimo, son distintos.
Deniciones (III)
Ciclo: camino simple v1, v2, . . . , vk tal que v1 = vk . Ej: <2,5,4,2> es un ciclo de longitud 3.
1 2 3
Deniciones (IV)
v es adyacente a u si existe una arista (u,v ) E . En un grafo no dirigido, (u,v ) E incide en los nodos u, v . En un grafo dirigido, (u,v ) E incide en v , y parte de u. Grado de un nodo: n umero de arcos que inciden en el. En grafos dirigidos existen el grado de salida y el grado de entrada. El grado del v ertice ser a la suma de los grados de entrada y de salida. Grado de un grafo: m aximo grado de sus v ertices.
Deniciones (V)
G = (V , E ) es un subgrafo de G = (V , E ) si V V y E E . Subgrafo inducido por V V : G = (V ,E ) tal que E = {(u,v ) E | u,v V }. Ejemplos de subgrafos del grafo de la transparencia 1:
V = {1,2,4,5} E = {(1,2),(1,4),(2,5),(5,4)}
Deniciones (VI)
v es alcanzable desde u, si existe un camino de u a v . Un grafo no dirigido es conexo si existe un camino desde cualquier v ertice a cualquier otro. Un grafo dirigido con esta propiedad se denomina fuertemente conexo: 2 1
Si un grafo dirigido no es fuertemente conexo, pero el grafo subyacente (sin sentido en los arcos) es conexo, el grafo es d ebilmente conexo.
Deniciones (VII)
En un grafo no dirigido, las componentes conexas son las clases de equivalencia seg un la relaci on ser alcanzable desde. Un grafo no dirigido es no conexo si est a formado por varias componentes conexas. En un grafo dirigido, las componentes fuertemente conexas, son las clases de equivalencia seg un la relaci on ser mutuamente alcanzable. Un grafo dirigido es no fuertemente conexo si est a formado por varias componentes fuertemente conexas.
1 2 3
Deniciones (VIII)
Grafo ponderado o etiquetado: cada arco, o cada v ertice, o los dos, tienen asociada una etiqueta.
1
8
10 12 7 9
2
1
3
15
10
11
Traducci on a grafos: representar islas y orillas con puntos. transformar puentes en l neas que enlacen los puntos.
A C
Nuevo problema: se puede dibujar la gura a partir de un punto y volver a el, sin repasar l neas y sin levantar el l apiz?
12
GRADO 3 3 5 3
5 5 4 5 2 3 4 3 4
2 3
2 3 4
5
1
2 3 4 5
14
15
1 2
2 10 5 7 5 1 2 12 4 9 6 9
4 8
1
8
10 12 7 9
2
1
3
15
3 4 5
6 15
16
17
2 3
1 0 1 0 0 1
1 0 0 0 0 0 0
2 1 0 1 1 1
2 1 0 0 1 0 0
3 0 1 0 1 0
3 0 0 0 0 0 0 4 1 0
4 0 1 1 0 1
5 0 1 1 0 0 0
5 1 1 0 1 0
6 0 0 1 0 0 1
0 0 1 0
18
19
1
8
10 12 7 9
2
1
3
15
1 2 3 4 5 6
1 0 0 0 0 0 0
2 10 0 0 12 0 0
3 0 0 0 0 0 0
4 8 0
5 6 0 0 0 7 0 1 15 0 0 0 0 9 0 0 0 9
20
21
22
23
5 7
2 3 4 5 6
OJO!: el recorrido depende del orden en que aparecen los v ertices en las listas de adyacencia.
25
5 7
u
5 7
Rec en profund(G)
2 5 7
u
Visita nodo(1)
2 5 7
u
color[1]=AMARILLO
2 5 7
u
Visita nodo(4)
color[4]=AMARILLO
Visita nodo(6)
26
2
u
7 1 4 6 1 4 6
color[6]=AMARILLO
2 5 7 1 4 6 1
Visita nodo(7)
2 5 7 4 6
1
color[7]=AMARILLO
u
5 7
Visita nodo(3)
color[3]=AMARILLO
Visita nodo(5)
27
5 7
5 7
5 7
color[5]=AMARILLO
Visita nodo(2)
color[2]=AMARILLO
28
A nadir coste asociado a los bucles de Recorrido en profundidad: O(|V |). coste del recorrido en profundidad es O(|V | + |E |).
29
3
30
31
33
5 7
u
5 7
Orden topologico(G)
Visita nodo(1) P = {}
2 7 5
u
Visita nodo(4) P = {}
2 7 5
u
5
u
7 1 4 6
Visita nodo(6) P = {}
Visita nodo(7) P = {}
apilar(P,7) P = {7}
34
5 7
5 7
5 7
apilar(P,5) P = {5,7}
u
5 7
apilar(P,3) P = {3,5,7}
apilar(P,6) P = {6,3,5,7}
5 7
u
5 7
apilar(P,2) P = {2,6,3,5,7}
apilar(P,4) P = {4,2,6,3,5,7}
apilar(P,1) P = {1,4,2,6,3,5,7}
Ordenaci on de los v ertices en una l nea horizontal, con todos los arcos de izquierda a derecha:
2 5 7 1 4 6
36
w(p) =
i=1
w(vi1, vi)
Camino de m nimo peso desde u a v : camino que tiene un peso menor entre todos los caminos de u a v , o si no existe camino de u a v . Longitud de un camino de u a v : peso de un camino de u a v . Camino m as corto de u a v : camino de m nimo peso de u a v .
37
1
100 20
50 30
2
5
5
10
50
Camino
1
30 50
50
2
1
30
3
50
35
2
3
100
4
20
20
100 120
1
10
4
10
2
20
40
38
39
Algoritmo de Dijkstra
Problema: G = (V , E ) grafo dirigido y ponderado con pesos no negativos; dado un v ertice origen s, obtener los caminos m as cortos al resto de v ertices de V . Si existen aristas con pesos negativos, la soluci on podr a ser err onea. Otros algoritmos permiten pesos negativos, siempre que no existan ciclos de peso negativo. Idea: explotar la propiedad de que el camino m as corto entre dos v ertices contiene caminos m as cortos entre los v ertices que forman el camino.
40
41
42
Algoritmo Dijkstra(G, w, s) { para cada v ertice v V hacer D[v ] = ; P [v ] = N U LO; n para D[s] = 0; S = ; Q = V ; mientras Q = hacer u = extract min(Q); / seg un D / S = S {u}; para cada v ertice v V adyacente a u hacer si D[v ] > D[u] + w(u,v ) entonces D[v ] = D[u] + w(u,v ); P [v ] = u; n si n para n mientras }
43
44
s 5
1
10
20 40
2
10 5
6
10
3
5
20
S {}
Q {1,2,3,4,5,6}
D P
1 0 N U LO
s 5
2 N U LO
3 N U LO
4 N U LO
5 N U LO
6 N U LO
1
10
20 40
2
10 5
6
10
3
5
5
D P
20
4
2 N U LO
S {1}
Q {2,3,4,5,6}
u 1
1 0 N U LO
3 40 1
4 N U LO
5 10 1
6 5 1
45
s 5
1
10
20 40
2
10 5
6
10
3
5
5
D P
s
20
4
2 25 6
S {1,6}
Q {2,3,4,5}
u 6
1 0 N U LO
3 40 1
4 N U LO
5 10 1
6 5 1
1
10
20 40
2
10 5
6
10
3
5
5
u 5 D P
20
4
2 25 6
S {1,6,5}
Q {2,3,4}
1 0 N U LO
3 40 1
4 30 5
5 10 1
6 5 1
46
s 5
1
10
20 40
2
10 5
6
10
3
5
5
u 2
s
20
4
2 25 6
S {1,6,5,2}
Q {3,4}
D P
1 0 N U LO
3 40 1
4 30 5
5 10 1
6 5 1
1
10
20 40
2
10 5
6
10
3
5
5
u 4 D P
20
4
2 25 6
S {1,6,5,2,4}
Q {3}
1 0 N U LO
3 35 4
4 30 5
5 10 1
6 5 1
47
s 5
1
10
20 40
2
10 5
6
10
3
5
5
u 3 D P
20
4
2 25 6
S {1,6,5,2,4,3}
Q {}
1 0 N U LO
3 35 4
4 30 5
5 10 1
6 5 1
48
50
Arbol de expansi on
51
w(u, v )
Un arbol de expansi on ser a de coste m nimo, si se cumple que su coste es el menor posible respecto al coste de cada uno de los posibles arboles de expansi on del grafo.
1
6 5 1 5 6 6
1
5 1 1 5 4
1 2
3 5
2
3
4
2
2
6
3
4
4 6
3
4 2
4 6
Coste 22
Coste m nimo: 15
Problema: Sea G = (V , E ) un grafo no dirigido, conexo y ponderado; obtener G = (V ,E ) donde E E tal que G sea un arbol de expansi on de coste m nimo de G.
52
Algoritmo de Kruskal
El algoritmo mantiene estas estructuras: Un conjunto A que mantiene las aristas que ya han sido seleccionadas como pertenecientes al arbol de expansi on de coste m nimo. Al nal A contendr a el subconjunto de aristas que forman el arbol de expansi on decoste m nimo. Un MF-set que se usa para saber qu e v ertices est an unidos entre s en el bosque (conjunto de arboles) que se va obteniendo durante el proceso de construcci on del arbol de expansi on de coste m nimo: Conforme se a naden aristas al conjunto A, se unen v ertices entre s formando arboles. Estos arboles se enlazar an entre s hasta obtener un u nico arbol que ser a el arbol de expansi on de coste m nimo.
53
54
1
45 30
10 40
2
35 55 25
50
5 4
20
15
56
{}
{{1},{2},{3},{4},{5},{6}}
10
10
2 3 6
{(1,2)}
{{1,2},{3},{4},{5},{6}}
57
10
2 3
15
{(1,2),(6,3)}
{{1,2},{6,3},{4},{5}}
58
10
2 3
15
{(1,2),(6,3),(4,6)}
{{1,2},{4,6,3},{5}}
20
59
10
2
25 15
{(1,2),(6,3),(4,6),(2,6)}
{{1,2,4,6,3},{5}}
20
60
Buscar(1) = Buscar(4)
35
10
2
35 25
{(1,2),(6,3),(4,6),(2,6),(5,3)}
{{5,1,2,4,6,3}}
15 20
61
62
Algoritmo de Prim
El algoritmo de Prim utiliza las siguientes estructuras durante la ejecuci on del algoritmo: Un conjunto A en el que se guardan aquellas aristas que ya forman parte del arbol de expansi on de coste m nimo. Un conjunto S inicialmente vac o, y al que se ir an a nadiendo los v ertices de V conforme se vayan recorriendo para formar el arbol de expansi on de coste m nimo.
63
64
65
66
1
45 30
10 40
2
35 55 25
50
5 4
20
15
67
{}
{}
1 5
2 3 6
{}
{1}
68
S
1
10
2 3 6
{(1,2)}
{1,2}
69
S
2
25
10
2
25
{(1,2),(2,6)}
{1,2,6}
70
S
3 6
15
10
2
25 15
{(1,2),(2,6),(6,3)}
{1,2,6,3}
71
A
4
S
20
10
2
25 15
{(1,2),(2,6),(6,3),(6,4)}
{1,2,6,3,4}
20
72
A
5
35
S
3
10
2
35 25
{(1,2),(2,6),(6,3),(6,4),(3,5)}
{1,2,6,3,4,5}
15 20
73
74
Algoritmos Voraces
Introducci on
Objetivos: Estudiar el dise no de algoritmos voraces. Estudiar algunos problemas cl asicos.
Aplicaci on:
Problemas de optimizaci on b usqueda del valor optimo de una funci on objetivo.
Introducci on (II)
Soluci on = secuencia de decisiones. Toma de decisiones: En base a una medida local de optimizaci on. Irreversibles. Soluci on sub optima. Coste computacional bajo. Estrategia voraz: realizar la elecci on que es mejor en ese momento. Criterio de manejo de datos.
Ejemplo:
Cantidad solicitada M = 1100 Euros. Billetes disponibles: {100, 200, 500}. Posibles soluciones: 11 100 (11 billetes). 5 200 + 1 100 (6 billetes). 2 500 + 1 100 (3 billetes).
Tama no del chero 300 Kbits. Codicaci on variable: caracter C odigo Variable a 0 b 101 c 100 d 111 e 1101 f 1100
abc
variable
0101100
La codicaci on variable cumple la propiedad de prejo: ning un c odigo es prejo de otro. Cada caracter queda determinado por su secuencia de bits asociada.
0 c
1 b 0 f
1 d 1 e
10
Algoritmo Human(C , F ) { for (x C , fx F ) { crear hoja(x,fx); } Q F ; build heap(Q); for (i=1;i< |C |;i++) { z = crear nodo(); z .hizq = minimo(Q); extract min(Q); z .hder = minimo(Q); extract min(Q); z .frec = z .hizq.frec + z .hder.frec; insertar(Q, z ); } return(minimo(Q)); } Coste O(n log n), n talla del vocabulario.
12
12
12
13
16
45
13
45
16
12
12
13 0 f 5
14 1 e 9
16
45
13
16
45
14
13
14 0 f 5 1 e 9
16 0 c 12
25 1 b 13
45
25
16
45
25 0 c 12 1 b 13 0 f 5 0 14
30 1 d 1 e 9 16
45
25 45
30
14
15
16
17
La soluci on optima deber a llenar la mochila al completo. Estrategia voraz: aplicamos criterio de optimizaci on local. Podemos denir tres criterios de selecci on de objetos: Escoger el elemento de mayor benecio. Escoger el elemento de menor peso. Escoger el elemento de mayor relaci on benecio/peso.
18
19
Algoritmo Mochila-fraccional(p, b, M, N ) { C = {1, 2, . . . , N}; for (i = 1; i <= N ; i + +) solucion[i] = 0; while ((C = ) && (M > 0)) { /* i = elemento de C con m aximo benecio b[i]; */ /* i = elemento de C con m nimo peso p[i]; */ i = elemento de C con m axima relaci on b[i]/p[i]; C = C - {i}; if (p[i] M ) { solucion[i] = 1; M = M p[i]; } else { solucion[i] = M/p[i]; M = 0; } } return(solucion); }
20
0 1 1 1
0 0 0 0
21
2. Criterio: seleccionar objeto de menor peso pi. Iteraci on 1 2 3 4 M 50 40 25 7 0 C {1,2,3,4} {1,2,3} {1,2} {1} Soluci on 0 0 0 0 0 0 0 0 1 0 1 1 7/30 1 1 0 1 1 1 1
Benecio = (7/30) 25 + 13 + 12 + 10 = 40.83 3. Criterio: seleccionar objeto de mayor benecio unitario bi/pi = (5/30, 13/18, 12/15, 10/10). Iteraci on 1 2 3 M 50 40 10 0 C {1,2,3,4} {1,2,3} {2,3} {2} 0 0 1 1 Soluci on 0 0 0 0 0 0 0 10/15 0 1 1 1