Está en la página 1de 27

1 QUICSORT

1.1 ALGORITMO QUICSORT



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--;
}

while ((left < right) && (array[left] <= pivot)) {
left++;
}

// 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);
}
}

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include "quicksort.cpp"

using namespace std;

int main()
{
int const MAX = 100;
int arraySize;

clock_t start_time;
clock_t final_time;
double total_time;
start_time = clock();

cout << "Ingresa tamanyo: " << endl;
cin >> arraySize;

int a[arraySize];

// Para que el rand no genere siempre los mismos nmeros, utilizando la
hora del sistema
srand(time(0));

// Para generar enteros aleatorios usamos rand()
for (int i = 0; i < arraySize; i++) {
a[i] = rand() % MAX;
}

cout << "Array antes de ordenarse: " << endl;
for (int i = 0; i < arraySize; i++) {
cout << a[i] << " ";
}

cout << endl << endl;

quicksort(a, 0, arraySize - 1);

final_time = clock();
total_time = ((double)(final_time - start_time)) / CLOCKS_PER_SEC;

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;

while (first <= last) {
middle = (first + last) / 2;

if (searched == array[middle]) {
cout << "Se encuentra en la posicin " << middle + 1 << endl;
return array[middle];
} else {
if (array[middle] > searched) {
last = middle - 1;
} else {
first = middle + 1;
}
}
}
return -1;
}

void print(int *array, int arraySize)
{
for (int i = 0; i < arraySize; i++) {
cout << array[i] << " ";
}
cout << endl << endl;
}

int main()
{
int arraySize;
int searched;
cout << "Ingresa el tamanyo del array" << endl;
cin >> arraySize;

int array[arraySize];

srand(time(NULL));
for (int i = 0; i < arraySize; i++) {
array[i] = rand() % 100;
}

cout << endl;
cout << "Array al inicio: " << endl;
print(array, arraySize);

cout << "Busqueda lineal -> Ingresa el elemento a buscar: ";
cin >> searched;
lineal_search(array, searched, arraySize);

cout << "Array ordenado: " << endl;
quicksort(array, 0, arraySize);
print(array, arraySize);

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;

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.3 EXPLICACION DE PARALELISMO












































4 RBOL ROJO NEGRO

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);
}
}

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(++conter<esp) cprintf("%c ",179);
if(node){
if(node->color=='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 KRUSKAL
5.1 ALGORITMO DE KRUSKAL

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");
}


int main(){
int E , origen, destino , peso , inicial;
scanf("%d %d" , &V , &E );
while( E-- ){
scanf("%d %d %d" , &origen , &destino , &peso );
ady[ origen ].push_back( Node( destino , peso ) ); //consideremos
grafo dirigido
//ady[ destino ].push_back( Node( origen , peso ) ); //grafo no
dirigido
}
printf("Ingrese el vertice inicial: ");
scanf("%d" , &inicial );
dijkstra( inicial );
return 0;
}

6.3 EXPLICACION DE PARALELISMO























7 CONVOLUCION

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