ALGORITMO QUICSORT

  • Upload
    reneac8

  • View
    15

  • Download
    0

Embed Size (px)

Citation preview

1 QUICSORT1.1 ALGORITMO QUICSORT

El algoritmo trabaja de la siguiente forma: Elegir un elemento de la lista de elementos a ordenar, al que llamaremospivote. 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 esO(nlog n). En el peor caso, el pivote termina en un extremo de la lista. El orden de complejidad del algoritmo es entonces deO(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 delarray, 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 esO(nlog n). No es extrao, pues, que la mayora de optimizaciones que se aplican al algoritmo se centren en la eleccin delpivote.

1.3CODIGO C++ QUICSORT// CODIGO Quicsort c++// Funcin para dividir el array y hacer los intercambiosint 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 ndiceswhile (left < right) {while (array[right] > pivot) {right--;}

while ((left < right) && (array[left] 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;in; i++) printf("\t%d",ptr->arreglo_claves[i]); printf("\n"); for (i=0; i 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;

for (i=pos+1; i < n; i++) { key_arr[i-1] = key_arr[i]; p[i] = p[i+1]; } return --ptr->n >= (ptr==root ? 1 : min) ? Exacto : LessKeys; }

if (pos < n && clave == key_arr[pos]) { struct nodo *qp = p[pos], *qp1; int nkey; while(1) { nkey = qp->n; qp1 = qp->p[nkey]; if (qp1 == NULL) break; qp = qp1; } key_arr[pos] = qp->arreglo_claves[nkey-1]; qp->arreglo_claves[nkey - 1] = clave; } value = del(p[pos], clave); if (value != LessKeys) return value; if (pos > 0 && p[pos-1]->n > min) { pivot = pos - 1; //pivote para nodo izquierda y derecha lptr = p[pivot]; rptr = p[pos]; //Asignar valores al nodo derecho rptr->p[rptr->n + 1] = rptr->p[rptr->n]; for (i=rptr->n; i>0; i--) { rptr->arreglo_claves[i] = rptr->arreglo_claves[i-1]; rptr->p[i] = rptr->p[i-1]; } rptr->n++; rptr->arreglo_claves[0] = key_arr[pivot]; rptr->p[0] = lptr->p[lptr->n]; key_arr[pivot] = lptr->arreglo_claves[--lptr->n]; return Exacto; } if (pos > min) { pivot = pos;//pivote para nodo izquierda y derecha lptr = p[pivot]; rptr = p[pivot+1]; //Asignar valores al nodo izquierdo lptr->arreglo_claves[lptr->n] = key_arr[pivot]; lptr->p[lptr->n + 1] = rptr->p[0]; key_arr[pivot] = rptr->arreglo_claves[0]; lptr->n++; rptr->n--; for (i=0; i < rptr->n; i++) { rptr->arreglo_claves[i] = rptr->arreglo_claves[i+1]; rptr->p[i] = rptr->p[i+1]; } rptr->p[rptr->n] = rptr->p[rptr->n + 1]; return Exacto; }

if(pos == n) pivot = pos-1; else pivot = pos; lptr = p[pivot]; rptr = p[pivot+1]; //mezclar nodo derecho con nodo izquierdo lptr->arreglo_claves[lptr->n] = key_arr[pivot]; lptr->p[lptr->n + 1] = rptr->p[0]; for (i=0; i < rptr->n; i++) { lptr->arreglo_claves[lptr->n + 1 + i] = rptr->arreglo_claves[i]; lptr->p[lptr->n + 2 + i] = rptr->p[i+1]; } lptr->n = lptr->n + rptr->n +1; free(rptr);//Remover nodo derecho for (i=pos+1; i < n; i++) { key_arr[i-1] = key_arr[i]; p[i] = p[i+1]; } return --ptr->n >= (ptr == root ? 1 : min) ? Exacto : LessKeys; }

void SetColor(int i) { if(hCon == NULL) hCon = GetStdHandle(STD_OUTPUT_HANDLE);

SetConsoleTextAttribute(hCon, i); }

3.3EXPLICACION DE PARALELISMO

4 RBOL ROJO NEGRO

4.1ALGORITMO DE ARBOL ROJO - NEGROrbol 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 denominannodos 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 losnodos externosson 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. Despusde 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#include#include// variables globalesstruc nodo//los nodos del arbolint 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 utilizarvoidinsercion(int key, char cad[32];//para insertar un numero en el arbolvoid solucionarRojoRojo(nodo *node,int h); //para solucionar un hijo rojo en un nodo rojonodo *buscar(int key); //para buscar un numero en el arbolitovoid ver(nodo *node, int esp, int h); //ver arbolint menus(int n_opciones, int x, int y); //para manejar menu con las teclas de las flechasvoid 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(keyllave){ if(keyizquierdo=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); } }

nodo *buscar(int key){

nodo *ayudante; ayudante=inicio; if(!ayudante) return NULL; do{ if(key==ayudante->llave) ayudante=ayudante->izquierdo; else if(key>ayudante->llave) ayudante->derecho; }while(ayuidante); return NULL;}

void ver(nodo *node,int esp, int h){

int conter=-1; char descripcion[15]; if(!node && node==inicio){ gotoxy(4,6); cprintf("El arbol esta vacio"); return; } textcolor(10); cprintf(" \n\r"); if(node==inicio) strcpy(descripcion, "Hijo izquierdo"); while(++contercolor=='n') textcolor(16); else textcolor(12); } else textcolor(14); if(node) cprintf("Llave=%d cadena=[%s]",node->llave,node->cadena,descripcion); else cprintf("[NULL] [%s]",descripcion); if(node && (node->izquierdo || node->derecho)){ ver(node->izquierdo, esp+1, 2); } textcolor(16); }

4.3 EXPLICACION DE PARALELISMO

5 KRUSKAL5.1 ALGORITMO DE KRUSKAL

1. mtodo Kruskal(Grafo):2. Inicializamos rbol de Expansin Mnima(MST) como vaco3. 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: 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. 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 delalgoritmo 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 mayor5. Para cada arista e que une los vrtices u y v6. Si u y v no estn en la misma componente7. Agregamos la arista e al MST8. Realizamos la unin de las componentes de u y v5.2 CODIGO C++ KRUSKAL

//Algoritmo de Kruskal#include #include #include

#define MAX 1005 //maximo numero de vrtices

///UNION-FINDint padre[ MAX ]; //Este arreglo contiene el padre del i-esimo nodo

//Mtodo de inicializacinvoid MakeSet( int n ){ for( int i = 1 ; i para obtener el arbol de expansion maxima bool operator //definimos el nodo como un par( first , second ) donde first es el vertice adyacente y second el peso de la arista#define INF 1 ady[ MAX ]; //lista de adyacenciaint distancia[ MAX ]; //distancia[ u ] distancia de vrtice inicial a vrtice con ID = ubool visitado[ MAX ]; //para vrtices visitadospriority_queue< Node , vector , cmp > Q; //priority queue propia del c++, usamos el comparador definido para que el de menor valor este en el topeint V; //numero de verticesint previo[ MAX ]; //para la impresion de caminos

//funcin de inicializacinvoid init(){ for( int i = 0 ; i