El algoritmo trabaja de la siguiente forma: Elegir un elemento de la lista de elementos a ordenar, al que llamaremos pivote. Resituar los dems elementos de la lista a cada lado del pivote, de manera que a un lado queden todos los menores que l, y al otro los mayores. Los elementos iguales al pivote pueden ser colocados tanto a su derecha como a su izquierda, dependiendo de la implementacin deseada. En este momento, el pivote ocupa exactamente el lugar que le corresponder en la lista ordenada. La lista queda separada en dos sub listas, una formada por los elementos a la izquierda del pivote, y otra por los elementos a su derecha. Repetir este proceso de forma recursiva para cada sub lista mientras stas contengan ms de un elemento. Una vez terminado este proceso todos los elementos estarn ordenados. Como se puede suponer, la eficiencia del algoritmo depende de la posicin en la que termine el pivote elegido. En el mejor caso, el pivote termina en el centro de la lista, dividindola en dos sub listas de igual tamao. En este caso, el orden de complejidad del algoritmo es O(nlog n). En el peor caso, el pivote termina en un extremo de la lista. El orden de complejidad del algoritmo es entonces de O(n). El peor caso depender de la implementacin del algoritmo, aunque habitualmente ocurre en listas que se encuentran ordenadas, o casi ordenadas. Pero principalmente depende del pivote, si por ejemplo el algoritmo implementado toma como pivote siempre el primer elemento del array, y el array que le pasamos est ordenado, siempre va a generar a su izquierda un array vaco, lo que es ineficiente. En el caso promedio, el orden es O(nlog n). No es extrao, pues, que la mayora de optimizaciones que se aplican al algoritmo se centren en la eleccin del pivote.
1.3 CODIGO C++ QUICSORT // CODIGO Quicsort c++ // Funcin para dividir el array y hacer los intercambios int divide(int *array, int start, int end) { int left; int right; int pivot; int temp;
pivot = array[start]; left = start; right = end;
// Mientras no se cruzen los ndices while (left < right) { while (array[right] > pivot) { right--; }
// Si todava no se cruzan los indices seguimos intercambiando if (left < right) { temp = array[left]; array[left] = array[right]; array[right] = temp; } }
// Los ndices ya se han cruzado, ponemos el pivot en el lugar que le corresponde temp = array[right]; array[right] = array[start]; array[start] = temp;
// La nueva posicin del pivot return right; }
// Funcin recursiva para hacer el ordenamiento void quicksort(int *array, int start, int end) { int pivot;
if (start < end) { pivot = divide(array, start, end);
// Ordeno la lista de los menores quicksort(array, start, pivot - 1);
// Ordeno la lista de los mayores quicksort(array, pivot + 1, end); } }
printf("Tiempo de ejecucin : %lf segundos \n", total_time);
cout << "Array ordenado " << endl; for (int i = 0; i < arraySize; i++){ cout << a[i] << "-"; }
cout << endl << endl;
return 0; }
6.1 EXPLICACION DE PARALELISMO
2 BUSQUEDA LINEAL
2.1 ALGORITMO BUSQUEDA LINEAL
La bsqueda lineal probablemente es sencilla de implementar e intuitiva. Bsicamente consiste en buscar de manera secuencial un elemento, es decir, preguntar si el elemento buscado es igual al primero, segundo, tercero y as sucesivamente hasta encontrar el deseado. Entonces este algoritmo tiene una complejidad de O(n). 2.2 CODIGO DE BUSQUEDA LINEAL
//CODIGO C++ BUSQUEDA LINEAL Y BINARIA #include <iostream> #include <stdlib.h> #include "quicksort.cpp"
using namespace std;
int lineal_search(int *array, int searched, int arraySize) { for (int i = 0; i< arraySize; i++) { if (searched == array[i]) { cout << "Se encuentra en la posicion " << i + 1 << endl; } } }
int binary_search(int *array, int searched, int arraySize) { int first = 0; int middle; int last = arraySize - 1;
cout << "Busqueda binaria -> Ingresa el elemento a buscar: "; cin >> searched; binary_search(array, searched, arraySize); }
2.3 EXPLICACION DE PARALELISMO
3. ARBOLES B
3.1 ALGORITMO ARBOLES B
Los B-rboles son rboles cuyos nodos pueden tener un nmero mltiple de hijos.
Un B-rbol se dice que es de orden m si sus nodos pueden contener hasta un mximo de m hijos. El conjunto de claves que se sitan en un nodo cumplen la condicin:
BSQUEDA EN UN RBOL B. 1. Seleccionar como nodo actual la raz del rbol. 2. Comprobar si la clave se encuentra en el nodo actual: 1. Si la clave est, fin. 2. Si la clave no est: Si estamos en una hoja, no se encuentra la clave. Fin. Si no estamos en una hoja, hacer nodo actual igual al hijo que corresponde segn el valor de la clave a buscar y los valores de las claves del nodo actual (i buscamos la clave K en un nodo con n claves: el hijo izquierdo si K<K 1 , el hijo derecho si K>K n y el hijo i-simo si K i <K<K i+1 )y volver al segundo paso. INSERCIN EN UN RBOL B Para insertar una nueva clave usaremos un algoritmo que consiste en dos pasos recursivos: 1. Buscamos la hoja donde debiramos encontrar el valor de la clave de una forma totalmente paralela a la bsqueda, encontramos en algn lugar del rbol la clave a insertar, el algoritmo no debe hacer nada ms. Si la clave no se encuentra en el rbol habremos llegado a una hoja que es justamente el lugar donde debemos realizar esa insercin. 2. Situados en un nodo donde realizar la insercin si no est completo, es decir, si el nmero de claves que existen es menor que el orden menos 1 del rbol, el elemento puede ser insertado y el algoritmo termina. En caso de que el nodo est completo insertamos la clave en su posicin y puesto que no caben en un nico nodo dividimos en dos nuevos nodos conteniendo cada uno de ellos la mitad de las claves y tomando una de stas para insertarla en el padre (se usar la mediana).Si el padre est tambin completo, habr que repetir el proceso hasta llegar a la raz. En caso de que la raz est completa, la altura del rbol aumenta en uno creando un nuevo nodo raz con una nica clave. 3.2 CODIGO C++ ARBOL B.
//Programa de busqueda, insercion y borrado #include <stdio.h> #include <stdlib.h> #include <windows.h> #define MAX_LONG 90 #define ARRIBA 72 #define ABAJO 80 #define ENTER 13 #define M 5 HANDLE hCon; struct nodo { int n; // n < M n de claves en el nodo siempre ser menor que el orden del B tree int arreglo_claves[M-1]; //arreglo de claves struct nodo *p[M]; // (n+1 punteros que van a ser usados }*root=NULL;//la raiz lo inicializamos en NULL
enum Estado_Clave { Duplicado,SearchFailure,Exacto,Insertado,LessKeys };//estados de las claves void Insertar_Nodo(int clave); void Imprimir_ArbolB(struct nodo *root,int); void Borrar_Nodo(int x); void Buscar_Nodo(int x); enum Estado_Clave ins(struct nodo *r, int x, int* y, struct nodo** u); int BuscarPosicion(int x,int *key_arr, int n); enum Estado_Clave del(struct nodo *r, int x); void SetColor(int i);
int menu(char (*text)[MAX_LONG], int max) { int tecla, op=0, i; while(tecla!=ENTER) { system("CLS"); for(i=0;i<max;i++) { if(op==i)//si es igual coloreo la opcin SetColor(10); printf("\t%s\n",text[i]); SetColor(15); } do { tecla=getch();//capturo la tecla mientras se presione //diferente a arriba,abajo o enter }while(tecla!=ARRIBA && tecla!= ABAJO && tecla!= ENTER); switch(tecla) { case ARRIBA:{ (op==0)? op=max-1 : op--; break; }
case ABAJO: { (op==max-1)? op=0 : op++; break; } } } op+=1; return op; //retorna la opcion +1 }
int main() { int clave,op,band=0; system("title ARBOL B DOCTORADO UNA PUNO "); char text[8][MAX_LONG]={ {"\t "}, {"\t Implementacion de un Arbol B "}, {"\t \n"}, {"[1] Insertar clave"}, {"[2] Eliminar clave"}, {"[3] Buscar clave"}, {"[4] Mostrar Arbol B"}, {"[5] Salir"}};//se inicializan while(op!=8) { switch(op=menu(text,8)) { case 4: { band=1; SetColor(11);printf("\n Insertar clave : ");SetColor(14);scanf("%d",&clave); Insertar_Nodo(clave); getch(); break; } case 5: { if(band==1) { SetColor(11);printf("\n Insertar clave a eliminar : ");SetColor(14);scanf("%d",&clave); Borrar_Nodo(clave); } else printf(" El arbol esta vacio "); getch(); break; } case 6: { if(band==1) { SetColor(11);printf(" Insertar clave a buscar : ");SetColor(14);scanf("%d",&clave); Buscar_Nodo(clave); } else printf(" El arbol esta vacio "); getch(); break; } case 7: { if(band==1) { SetColor(11);printf("\t\t\t El Arbol B es : ");SetColor(14); printf("\n"); Imprimir_ArbolB(root,0); } else printf("\t\t\t El arbol esta vacio "); getch(); break; } case 8: { SetColor(11);printf("\t\t Gracias por usar esta aplicacion "); getch(); exit(1); break; } } } return 0; }
void Insertar_Nodo(int clave) { struct nodo *newnodo; int upKey; enum Estado_Clave value; value = ins(root, clave, &upKey, &newnodo); if (value == Duplicado)//si ingresamos un valor duplicado printf("La clave ya esta insertada\n"); if (value == Insertado)//si es nuevo,asigno memoria y creo la clave { struct nodo *uproot = root; root=malloc(sizeof(struct nodo)); root->n = 1; root->arreglo_claves[0] = upKey; root->p[0] = uproot; root->p[1] = newnodo; } }
//le asignamos un estado a la clave(ya sea que esta duplicada,etc) enum Estado_Clave ins(struct nodo *ptr, int clave, int *upKey,struct nodo**newnodo) { struct nodo *newPtr, *lastPtr; int pos, i, n,splitPos; int nueva_clave, ultima_clave; enum Estado_Clave value; if (ptr == NULL) { *newnodo = NULL; *upKey = clave; return Insertado; } n = ptr->n; pos = BuscarPosicion(clave, ptr->arreglo_claves, n); if (pos < n && clave == ptr->arreglo_claves[pos]) return Duplicado; value = ins(ptr->p[pos], clave, &nueva_clave, &newPtr); if (value != Insertado) return value;
//Si la clave en el nodo es menor que M-1 donde M es el orden de B tree if (n < M - 1) { pos = BuscarPosicion(nueva_clave, ptr->arreglo_claves, n); //Desplazamiento de una clave y puntero(derecha) inserta una nueva clave for (i=n; i>pos; i--) { ptr->arreglo_claves[i] = ptr->arreglo_claves[i-1]; ptr->p[i+1] = ptr->p[i]; } //La clave es insertada en su puesto exacto ptr->arreglo_claves[pos] = nueva_clave; ptr->p[pos+1] = newPtr; ++ptr->n;//incrementamos el numero de claves en el nodo return Exacto;//exact0 } //Si la clave es la mayor,la posicin del nodo es insertada al final if (pos == M - 1) { ultima_clave = nueva_clave; lastPtr = newPtr; } else /*If keys in node are maximum and position of node to be inserted is not last*/ { ultima_clave = ptr->arreglo_claves[M-2]; lastPtr = ptr->p[M-1]; for (i=M-2; i>pos; i--) { ptr->arreglo_claves[i] = ptr->arreglo_claves[i-1]; ptr->p[i+1] = ptr->p[i]; } ptr->arreglo_claves[pos] = nueva_clave; ptr->p[pos+1] = newPtr; } splitPos = (M - 1)/2;//Dividimos (*upKey) = ptr->arreglo_claves[splitPos]; (*newnodo)=malloc(sizeof(struct nodo));/*Nodo a la derecha despus de dividir*/ ptr->n = splitPos; /*N de teclas para el nodo dividido a la izquierda*/ (*newnodo)->n = M -1-splitPos;/*No. of keys for right splitted node*/ for (i=0; i < (*newnodo)->n; i++) { (*newnodo)->p[i] = ptr->p[i + splitPos + 1]; if(i < (*newnodo)->n - 1) (*newnodo)->arreglo_claves[i] = ptr->arreglo_claves[i + splitPos + 1]; else (*newnodo)->arreglo_claves[i] = ultima_clave; } (*newnodo)->p[(*newnodo)->n] = lastPtr; return Insertado; }
void Imprimir_ArbolB(struct nodo *ptr, int blanks) { if (ptr) { int i; for(i=1;i<=blanks;i++) printf(""); for (i=0; i < ptr->n; i++) printf("\t%d",ptr->arreglo_claves[i]); printf("\n"); for (i=0; i <= ptr->n; i++) Imprimir_ArbolB(ptr->p[i], blanks+10); } }
void Buscar_Nodo(int clave) { int pos, i, n; struct nodo *ptr = root; printf(" El camino del arbol:\n"); while (ptr) { n = ptr->n; for (i=0; i < ptr->n; i++) printf("\t%d",ptr->arreglo_claves[i]); printf("\n"); pos = BuscarPosicion(clave, ptr->arreglo_claves, n); if (pos < n && clave == ptr->arreglo_claves[pos]) { printf("\t\t\t La clave %d fue encontrada\n",clave,i); return; } ptr = ptr->p[pos]; } printf("\t\t\t La clave No %d fue encontrada\n",clave); }
int BuscarPosicion(int clave, int *key_arr, int n) { int pos=0; while (pos < n && clave > key_arr[pos]) pos++; return pos; }
void Borrar_Nodo(int clave) { struct nodo *uproot; enum Estado_Clave value; value = del(root,clave); switch (value) { case SearchFailure: printf("La clave %d no esta disponible\n",clave); break; case LessKeys: uproot = root; root = root->p[0]; free(uproot); break; } }
enum Estado_Clave del(struct nodo *ptr, int clave) { int pos, i, pivot, n ,min; int *key_arr; enum Estado_Clave value; struct nodo **p,*lptr,*rptr;
if (ptr == NULL) return SearchFailure; //Asigna valores del nodo
n=ptr->n; key_arr = ptr->arreglo_claves; p = ptr->p; min = (M - 1)/2;//minimo numero de claves
pos = BuscarPosicion(clave, key_arr, n); if (p[0] == NULL) { if (pos == n || clave < key_arr[pos]) return SearchFailure;
4.1 ALGORITMO DE ARBOL ROJO - NEGRO rbol binario de bsqueda restringido en altura al igual que el AVL. Su diferencia es la forma de controlar la altura y mantener el equilibrio. Una particularidad de estos rboles es que se incluyen a los null como nodos del rbol, y los denominan nodos externos. 1. Todo rbol Rojo-Negro est formado por nodos rojos y negros. 2. Nodos rojos: un nodo es rojo cuando sus dos hijos son nodos negros. 3. Todos los nodos externos son nodos negros. 4. Todos los caminos desde un nodo, hasta cada uno de sus nodos externos descendientes deben contener el mismo nmero de nodos negros. 5. En un camino, no pueden haber ms de dos nodos rojos consecutivos, pero si pueden haber n nodos negros consecutivos. Esto significa que un nodo rojo no puede tener ningn hijo rojo. 6. La altura negra de un nodo es el nmero de nodos negros que hay desde dicho nodo sin contarlo, hasta cualquiera de sus nodos externos.
Insertar un nodo en el rbol Rojo-Negro. El proceso de ingreso de un nodo en el rbol es inicialmente el que se realiza con los rboles binarios de bsqueda. El nuevo nodo es un nodo Rojo con dos hijos nodos externos y se coloca en reemplazo de uno de los nodos externos existentes en el rbol. Despus de la insercin se pueden presentar tres casos, que el rbol siga balanceado, que se necesite cambiar de color a algn nodo (recolorar) o que sea necesario algn proceso de rotacin para cumplir las reglas del rbol. Cuando un padre y un hijo, ambos son del mismo color rojo, se necesita balancear el rbol, para lo cual se necesitan saber dos cosas: la primera es la localizacin del nodo hijo con respecto a su abuelo y el color del hermano de su padre. En los casos en los cuales el nodo hermano del padre es rojo, se solucionan con cambio de color. El caso en el cual el hermano es de color negro se solucionan con rotacin. Suponiendo que el padre del nodo a insertar es la raz de todo el rbol Rojo-Negro, simplemente se cambia su color a negro. Esto dado que la raz de todo rbol rojo negro debe ser un nodo Negro. En forma general el padre no va a ser negro, por tanto, el color del nodo hermano es el que va a determinar si es necesaria una recoloracin, rotacin simple con recoloracin asociada o rotacin doble con recoloracin asociada.
4.2 CODIGO C++ DE ALGORITMO ROJO NEGRO.
//CODIGO C++ ALGORITMO ROJO-NEGRO //Funcin para dividir el array y hacer los intercambios #include <stdio.h> #include <conio.h> #include <string.h> // variables globales struc nodo//los nodos del arbol int llave char color //donde r es rojo y n es negro struct nodo *izquierdo; struct nodo *derecho; struct nodo *padre; char cadena[32];
nodo *inicio // el inicio del arbol //funciones a utilizar void insercion(int key, char cad[32]; //para insertar un numero en el arbol void solucionarRojoRojo(nodo *node,int h); //para solucionar un hijo rojo en un nodo rojo nodo *buscar(int key); //para buscar un numero en el arbolito void ver(nodo *node, int esp, int h); //ver arbol int menus(int n_opciones, int x, int y); //para manejar menu con las teclas de las flechas void liberar(nodo *node); //para liberar la memoria cuando salir del programa
void main(void){
int opcion, numero; nodo *ayudante; char cadenalocal[32]; inicio=NULL; textbackground(15); do{ clrscr(); fflush(stdin); textcolor(16); cprintf(" Arbol rojo negro\n\r"); cpritf(" Insertar un numero \n\r Buscar un numero\n\r Ver el arbol\n\r Terminar"); opcion=menus(4, 2, 2); switch(opcion){ case 1: gotoxy(4,6), cprintf("teclea el numero a insertar "); scanf("%d",&numero); gotoxy(4,7), cprintf("teclea la cadena a insertar "); scanf("%s",cadenalocal); insercion(numero,cadenalocal); gotoxy(6,9), cprintf("presiona una tecla para continuar..."); break; caso 2: gotoxy(4,6), cprintf("teclea el numero a buscar "); scanf("%d",&numero); ayudante=buscar(numero); if(ayudante) cprintf("Se encontro ese numero su cadena es:\n\r %s",ayudante- >cadena); else cprintf(" No se encontro ese numero en el arbol"); cprintf("\n\r presiona una tecla para continuar..."); break; caso 3; clrscr(); ver(inicio, 0, 0); cprintf("\n\n\r Presiona una tecla para continuar..."); break; } void insercion(int key, char cad[32]) { int ladohijo; nodo *hijo; nodo *ayudante; int bandera; if (!inicio){// el arbol esta vacio cargando como raiz inicio = new nodo; inicio->llave=key; strcpy(inicio->cadena,cad); inicio->padre=NULL; inicio->izquierdo=NULL; inicio->derecho=NULL; inicio->color='n'; } else{ // el arbol no esta vacio buscando su lugar hijo = new nodo; hijo->llave=key; strcpy(hijo->cadena,cad); hijo->color='r'; ayudante=inicio; do{ hijo->padre=ayudante, bandera=1; if(key<ayudante->llave){ if(key<ayudantne->izquierdo=hijo, bandera=0, ladohijo=1; else ayudante->izquierdo=hijo, bandera=0, ladohijo=1; } else{ if(ayudante->derecha) ayudante->derecho; else ayudante->derecho=hijo, bandera=0, ladohijo=2; } }while(bandera==1); if(ayudante->color=='r') solucionarRojoRojo(ayudante, ladohijo); } }
1. mtodo Kruskal(Grafo): 2. Inicializamos rbol de Expansin Mnima (MST) como vaco 3. Inicializamos estructura unin-find Union Find es una estructura de datos que modela una coleccin de conjuntos disjuntos (disjoint-sets) y esta basado en 2 operaciones: o Find( A ): Determina a cual conjunto pertenece el elemento A. Esta operacin puede ser usada para determinar si 2 elementos estn o no en el mismo conjunto. o Union( A, B ): Une todo el conjunto al que pertenece A con todo el conjunto al que pertenece B, dando como resultado un nuevo conjunto basado en los elementos tanto de A como de B. Estas operaciones me servirn para la implementacin del algoritmo de Kruskalo problemas que involucran particionamiento como encontrar las componentes conexas en un grafo. 4. Ordenamos las aristas del grafo por peso de menor a mayor 5. Para cada arista e que une los vrtices u y v 6. Si u y v no estn en la misma componente 7. Agregamos la arista e al MST 8. Realizamos la unin de las componentes de u y v 5.2 CODIGO C++ KRUSKAL
//Algoritmo de Kruskal #include <stdio.h> #include <algorithm> #include <cstring>
#define MAX 1005 //maximo numero de vrtices
///UNION-FIND int padre[ MAX ]; //Este arreglo contiene el padre del i-esimo nodo
//Mtodo de inicializacin void MakeSet( int n ){ for( int i = 1 ; i <= n ; ++i ) padre[ i ] = i; }
//Mtodo para encontrar la raiz del vrtice actual X int Find( int x ){ return ( x == padre[ x ] ) ? x : padre[ x ] = Find( padre[ x ] ); }
//Mtodo para unir 2 componentes conexas void Union( int x , int y ){ padre[ Find( x ) ] = Find( y ); }
//Mtodo que me determina si 2 vrtices estan o no en la misma componente conexa bool sameComponent( int x , int y ){ if( Find( x ) == Find( y ) ) return true; return false; } ///FIN UNION-FIND
int V , E; //numero de vertices y aristas //Estructura arista( edge ) struct Edge{ int origen; //Vrtice origen int destino; //Vrtice destino int peso; //Peso entre el vrtice origen y destino Edge(){} //Comparador por peso, me servira al momento de ordenar lo realizara en orden ascendente //Cambiar signo a > para obtener el arbol de expansion maxima bool operator<( const Edge &e ) const { return peso < e.peso; } }arista[ MAX ]; //Arreglo de aristas para el uso en kruskal Edge MST[ MAX ]; //Arreglo de aristas del MST encontrado
void Kruskal(){ int origen , destino , peso; int total = 0; //Peso total del MST int numAristas = 0; //Numero de Aristas del MST
MakeSet( V ); //Inicializamos cada componente std::sort( arista , arista + E ); //Ordenamos las aristas por su comparador
for( int i = 0 ; i < E ; ++i ){ //Recorremos las aristas ya ordenadas por peso origen = arista[ i ].origen; //Vrtice origen de la arista actual destino = arista[ i ].destino; //Vrtice destino de la arista actual peso = arista[ i ].peso; //Peso de la arista actual
//Verificamos si estan o no en la misma componente conexa if( !sameComponent( origen , destino ) ){ //Evito ciclos total += peso; //Incremento el peso total del MST MST[ numAristas++ ] = arista[ i ]; //Agrego al MST la arista actual Union( origen , destino ); //Union de ambas componentes en una sola } }
//Si el MST encontrado no posee todos los vrtices mostramos mensaje de error //Para saber si contiene o no todos los vrtices basta con que el numero //de aristas sea igual al numero de vertices - 1 if( V - 1 != numAristas ){ puts("No existe MST valido para el grafo ingresado, el grafo debe ser conexo."); return; } puts( "-----El MST encontrado contiene las siguientes aristas-----"); for( int i = 0 ; i < numAristas ; ++i ) printf("( %d , %d ) : %d\n" , MST[ i ].origen , MST[ i ].destino , MST[ i ].peso ); //( vertice u , vertice v ) : peso
printf( "El costo minimo de todas las aristas del MST es : %d\n" , total ); }
int main(){ int mst;
scanf("%d %d" , &V , &E );
//Realizamos el ingreso del grafo, almacenando las aristas en un arreglo con los datos respectivos for( int i = 0 ; i < E ; ++i ) scanf("%d %d %d" , &arista[ i ].origen , &arista[ i ].destino , &arista[ i ].peso );
Kruskal();
return 0; }
5.3 EXPLICACION DE PARALELISMO
6 DIJSKTRA 6.1 ALGORITMO DIJKTRA 1. Mtodo Dijkstra(Grafo,origen): 2. Creamos una cola de prioridad Q 3. Agregamos origen a la cola de prioridad Q 4. Mientras Q no este vaco: 5. Sacamos un elemento de la cola Q llamado u 6. Si u ya fue visitado continuo sacando elementos de Q 7. Marcamos como visitado u 8. Para cada vrtice v adyacente a u en el Grafo: 9. Sea w el peso entre vrtices ( u , v ) 10. Si v no ah sido visitado: 11. Relajacion( u , v , w ) 12. Mtodo Relajacion( actual , adyacente , peso ): 13. Si distancia[ actual ] + peso < distancia[ adyacente ] 14. Distancia[ adyacente ] = distancia[ actual ] + peso 15. Agregamos adyacente a la cola de prioridad Q
6.2 CODIGO C++ DIJKTRA
// ALGORITMO DIJKTRA EN C++ #include <stdio.h> #include <vector> #include <queue> using namespace std; #define MAX 10005 //maximo numero de vrtices #define Node pair< int , int > //definimos el nodo como un par( first , second ) donde first es el vertice adyacente y second el peso de la arista #define INF 1<<30 //definimos un valor grande que represente la distancia infinita inicial, basta conque sea superior al maximo valor del peso en alguna de las aristas
//La cola de prioridad de C++ por default es un max-Heap (elemento de mayor valor en el tope) //por ello es necesario realizar nuestro comparador para que sea un min-Heap struct cmp { bool operator() ( const Node &a , const Node &b ) { return a.second > b.second; } }; vector< Node > ady[ MAX ]; //lista de adyacencia int distancia[ MAX ]; //distancia[ u ] distancia de vrtice inicial a vrtice con ID = u bool visitado[ MAX ]; //para vrtices visitados priority_queue< Node , vector<Node> , cmp > Q; //priority queue propia del c++, usamos el comparador definido para que el de menor valor este en el tope int V; //numero de vertices int previo[ MAX ]; //para la impresion de caminos
//funcin de inicializacin void init(){ for( int i = 0 ; i <= V ; ++i ){ distancia[ i ] = INF; //inicializamos todas las distancias con valor infinito visitado[ i ] = false; //inicializamos todos los vrtices como no visitados previo[ i ] = -1; //inicializamos el previo del vertice i con -1 } }
//Paso de relajacion void relajacion( int actual , int adyacente , int peso ){ //Si la distancia del origen al vertice actual + peso de su arista es menor a la distancia del origen al vertice adyacente if( distancia[ actual ] + peso < distancia[ adyacente ] ){ distancia[ adyacente ] = distancia[ actual ] + peso; //relajamos el vertice actualizando la distancia previo[ adyacente ] = actual; //a su vez actualizamos el vertice previo Q.push( Node( adyacente , distancia[ adyacente ] ) ); //agregamos adyacente a la cola de prioridad } }
//Impresion del camino mas corto desde el vertice inicial y final ingresados void print( int destino ){ if( previo[ destino ] != -1 ) //si aun poseo un vertice previo print( previo[ destino ] ); //recursivamente sigo explorando printf("%d " , destino ); //terminada la recursion imprimo los vertices recorridos }
void dijkstra( int inicial ){ init(); //inicializamos nuestros arreglos Q.push( Node( inicial , 0 ) ); //Insertamos el vrtice inicial en la Cola de Prioridad distancia[ inicial ] = 0; //Este paso es importante, inicializamos la distancia del inicial como 0 int actual , adyacente , peso; while( !Q.empty() ){ //Mientras cola no este vacia actual = Q.top().first; //Obtengo de la cola el nodo con menor peso, en un comienzo ser el inicial Q.pop(); //Sacamos el elemento de la cola if( visitado[ actual ] ) continue; //Si el vrtice actual ya fue visitado entonces sigo sacando elementos de la cola visitado[ actual ] = true; //Marco como visitado el vrtice actual
for( int i = 0 ; i < ady[ actual ].size() ; ++i ){ //reviso sus adyacentes del vertice actual adyacente = ady[ actual ][ i ].first; //id del vertice adyacente peso = ady[ actual ][ i ].second; //peso de la arista que une actual con adyacente ( actual , adyacente ) if( !visitado[ adyacente ] ){ //si el vertice adyacente no fue visitado relajacion( actual , adyacente , peso ); //realizamos el paso de relajacion } } }
printf( "Distancias mas cortas iniciando en vertice %d\n" , inicial ); for( int i = 1 ; i <= V ; ++i ){ printf("Vertice %d , distancia mas corta = %d\n" , i , distancia[ i ] ); }
puts("\n**************Impresion de camino mas corto**************"); printf("Ingrese vertice destino: "); int destino; scanf("%d" , &destino ); print( destino ); printf("\n"); }
7.1 ALGORITMO DE CONVOLUCION Es un dominio de matemticos. La mayora de los filtros usan una matriz de convolucin. Con el filtro matriz de convolucin, si tiene imaginacin, puede crear filtros personalizados Qu es una matriz de convolucin? Es posible hacerse una idea sin usar las herramientas matemticas que solo conocen unos pocos. Convolucin es el tratamiento de una matriz por otra que se llama kernel El filtro matriz de convolucin usa una primera matriz que es la imagen que ser tratada. La imagen es una coleccin bidimensional de pxeles en coordenada rectangular. El kernel usado depende del efecto deseado. Se considerarn slo las matrices 3x3, son las ms usadas y son suficiente para los efectos deseados. Si todos los valores del borde de un kernel se seleccionan a cero, el sistema la considerar como una matriz 3x3 El filtro examina, sucesivamente, cada pxel de la imagen. Para cada uno de ellos, que se llamar pxel inicial, se multiplica el valor de este pxel y los valores de los 8 circundantes por el valor correspondiente del kernel. Entonces se aade el resultado, y el pxel inicial se regula en este valor resultante final Un ejemplo simple
A la izquierda, la imagen de la matriz: cada pxel est marcado con su valor. El pxel inicial tiene un borde rojo. El rea de accin del kernel tiene un borde verde. En el medio, el kernel, y a la derecha, el resultado de convolucin Lo que sucede aqu: el filtro lee sucesivamente, de izquierda a derecha y de arriba a abajo, todos los pxeles del rea de accin del kernel. Se multiplica el valor de cada uno de ellos por el valor correspondiente del kernel y se suman los resultados. El pxel inicial llega a 42: (40*0)+(42*1)+(46*0) + (46*0)+(50*0)+(55*0) + (52*0)+(56*0)+(58*0) = 42. (el filtro no trabaja sobre la imagen sino sobre una copia). Como resultado grfico, el pxel inicial se movi un pxel hacia abaj 7.2 CODIGO DE CONVOLUCION