elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Introducción a Git (Primera Parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  ¿Mejor algoritmo? Problema con aproximaciones de Grafos
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: 1 [2] Ir Abajo Respuesta Imprimir
Autor Tema: ¿Mejor algoritmo? Problema con aproximaciones de Grafos  (Leído 6,470 veces)
AlbertoBSD
Programador y
Moderador Global
***
Desconectado Desconectado

Mensajes: 3.696


🏴 Libertad!!!!!


Ver Perfil WWW
Re: ¿Mejor algoritmo? Problema con aproximaciones de Grafos
« Respuesta #10 en: 28 Julio 2016, 15:41 pm »

La raiz es el primer nodo que se inserta..

Su padre es null.

Tus funciones de inOrden o preorden son recursivas y no necesitan saber quien es el padre, aun asi gastan mas memoria. En funciones iterativas es mecesario saber quien es el podre y gastan menos memoria.

En ocasiones es necesario separar subarboles o eliminar arboles completos, y tambien facilita mucho tener una referencia al padre.

Basicamente es una facilidad tener esa referencia en fumciones iterarivas.

Como reto deberias de hacer tu funcion inOrden y preOrden de forma iterativa, Esto es sin llamar a las funciones dichas desde si mismas.

Saludos!



En línea

do-while


Desconectado Desconectado

Mensajes: 1.276


¿Habra que sacarla de paseo?


Ver Perfil
Re: ¿Mejor algoritmo? Problema con aproximaciones de Grafos
« Respuesta #11 en: 29 Julio 2016, 09:58 am »

Interesante ejercicio.

Se trata de crear particiones sobre el conjunto de personas (tenemos una relación de equivalencia en un conjunto->la equivalencia crea una partición del conjunto (un conjunto de subconjuntos disjuntos)).

Se me ocurre que se puede tener un vector (mejor árbol, que así no hay que estar desplazando valores para mantener el orden después de una inserción) con pares del tipo numero_persona-clase. Así la cuestión de decidir si dos personas son amigos se reduce a realizar la búsqueda de las dos personas y ver si pertenecen a la misma clase, y la inserción se podría hacer en un vector (sabemos que el máximo numero de parejas es 100.000 / 2) en el que cada componente sea un vector de punteros a los nodos del árbol que formen parte de la misma clase. Así, a través de los punteros de la tabla, si hubiese que fusionar dos clases sería muy fácil corregir directamente en cada nodo del árbol la clase a la que pertenece el par persona-clase. La tabla mantiene una lista de todas las personas relacionadas entre sí y soluciona el problema de buscar en el árbol todas las personas que pertenecen a la misma clase.

A ver que sale de esta idea.

¡Saludos!


Con el planteamiento anterior, cambiando la idea de un vector de vectores por la de un vector de árboles, en mi ordenador, el tiempo de ejecución en el caso de la entrada de mayor dimensión se pasa del segundo por poco. Entre 1'2 y 1'3 segundos.

Alberto, te mando el código por MP, como los planteamientos son distintos me gustaría ver tu código.

¡Saludos!


« Última modificación: 29 Julio 2016, 12:35 pm por do-while » En línea

- Doctor, confundo los números y los colores.
- Vaya marrón.
- ¿Marrón? ¡Por el culo te la hinco!
AlbertoBSD
Programador y
Moderador Global
***
Desconectado Desconectado

Mensajes: 3.696


🏴 Libertad!!!!!


Ver Perfil WWW
Re: ¿Mejor algoritmo? Problema con aproximaciones de Grafos
« Respuesta #12 en: 29 Julio 2016, 14:52 pm »

 ;-) ;-)  ;-)

Excelente aproximacion. Aun no veo tu codigo pero.... la idea es genial y de hecho es mas rápido que un Grafo con Disjktra...

Fucionar arboles seria mas rapido y las consultas prácticamente ya están hechas al tener un valor que nos indiqué a que conjunto o "arbol" pertenece un nodo facilmente se puede saber si existe ese lazo o no.

En lo que llegue al trabajo te pado mi codigo.

Saludos
« Última modificación: 29 Julio 2016, 15:55 pm por AlbertoBSD » En línea

do-while


Desconectado Desconectado

Mensajes: 1.276


¿Habra que sacarla de paseo?


Ver Perfil
Re: ¿Mejor algoritmo? Problema con aproximaciones de Grafos
« Respuesta #13 en: 29 Julio 2016, 21:38 pm »

Bueno... hoy estoy muy tonto. Pensaba que en los códigos anteriores discutíais sobre opciones para resolver el problema. Veo que ya hay alguna solución, así que dejo la mía también. main está al final y justo antes están las funciones problema_interactivo y problema_aleatorio. La primera solicita los datos desde el teclado, la segunda genera 100.000 casos aleatorios y los procesa.
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <time.h>
  5.  
  6. #define DIM 100000
  7.  
  8. struct Persona
  9. {
  10. int valor;
  11. int clase;
  12. };
  13. typedef struct Persona Persona;
  14.  
  15. struct NodoArbolPersona
  16. {
  17. Persona *persona;
  18.  
  19. struct NodoArbolPersona *menores, *mayores;
  20. };
  21. typedef struct NodoArbolPersona NodoArbolPersona;
  22.  
  23. void insertar(NodoArbolPersona **arbol, Persona *persona)
  24. {
  25. if(!(*arbol))
  26. {
  27. (*arbol) = malloc(sizeof(NodoArbolPersona));
  28. (*arbol)->persona = persona;
  29. (*arbol)->menores = NULL;
  30. (*arbol)->mayores = NULL;
  31.  
  32. return;
  33. }
  34.  
  35. if(persona->valor < (*arbol)->persona->valor)
  36. insertar(&((*arbol)->menores), persona);
  37. else
  38. insertar(&((*arbol)->mayores), persona);
  39. }
  40.  
  41. Persona* buscar(NodoArbolPersona *arbol, int valor)
  42. {
  43. if(!arbol)
  44. return NULL;
  45.  
  46. if(arbol->persona->valor == valor)
  47. return arbol->persona;
  48.  
  49. if(valor < arbol->persona->valor)
  50. return buscar(arbol->menores, valor);
  51.  
  52. return buscar(arbol->mayores,valor);
  53. }
  54.  
  55. void cambiar_clase(NodoArbolPersona *amigos, int nueva_clase)
  56. {
  57. if(!amigos)
  58. return;
  59.  
  60. amigos->persona->clase = nueva_clase;
  61.  
  62. cambiar_clase(amigos->menores, nueva_clase);
  63. cambiar_clase(amigos->mayores, nueva_clase);
  64. }
  65.  
  66. void fusionar_arboles(NodoArbolPersona **destino, NodoArbolPersona *origen)
  67. {
  68. if(!(*destino))
  69. *destino = origen;
  70.  
  71. if((*destino)->persona->valor == origen->persona->valor)
  72. return;
  73.  
  74. if(origen->persona->valor < (*destino)->persona->valor)
  75. fusionar_arboles(&((*destino)->menores),origen);
  76. else
  77. fusionar_arboles(&((*destino)->mayores),origen);
  78.  
  79. }
  80.  
  81. void insertar_amigos(NodoArbolPersona *amigos[DIM/2], NodoArbolPersona **personas, int a, int b)
  82. {
  83. Persona *persona1,*persona2, *aux;
  84. int i,clase_aux;
  85.  
  86. if((persona1 = buscar(*personas,a)))
  87. {
  88. if((persona2 = buscar(*personas,b))) //ambas personas existen
  89. {
  90. if(persona1->clase != persona2->clase)
  91. {
  92. //pertenecen a distintas clases y hay que fusionarlas
  93. if(persona1->clase > persona2->clase)
  94. {
  95. aux = persona2;
  96. persona2 = persona1;
  97. persona1 = aux;
  98. }
  99.  
  100. clase_aux = persona2->clase;
  101. cambiar_clase(amigos[persona2->clase],persona1->clase); //cambiamos toda la clase b para que apunte a a.
  102. fusionar_arboles(&(amigos[persona1->clase]),amigos[clase_aux]); //añadimos toda el arbol b a a.
  103. amigos[clase_aux] = NULL;
  104. }
  105. }
  106. else //existe p1, pero no p2
  107. {
  108. persona2 = malloc(sizeof(Persona));
  109.  
  110. persona2->valor = b;
  111. persona2->clase = persona1->clase;
  112.  
  113. insertar(personas, persona2);
  114. insertar(&(amigos[persona1->clase]), persona2);
  115. }
  116. }
  117. else //persona1 no existe
  118. {
  119. if((persona2 = buscar(*personas,b)))
  120. {
  121. //existe p2 pero no p1
  122. persona1 = malloc(sizeof(Persona));
  123.  
  124. persona1->valor = a;
  125. persona1->clase = persona2->clase;
  126.  
  127. insertar(personas, persona1);
  128. insertar(&(amigos[persona2->clase]), persona1);
  129. }
  130. else //no existen ninguna de las dos personas
  131. {
  132. //buscamos la primera clase que este vacia
  133. for(i = 0 ; amigos[i] ; i++);
  134.  
  135. //creamos las personas:
  136. persona1 = malloc(sizeof(Persona));
  137. persona2 = malloc(sizeof(Persona));
  138.  
  139. persona1->valor = a;
  140. persona2->valor = b;
  141. persona1->clase = persona2->clase = i;
  142.  
  143. insertar(personas,persona1);
  144. insertar(personas,persona2);
  145.  
  146. insertar(&(amigos[i]),persona1);
  147. insertar(&(amigos[i]),persona2);
  148.  
  149. }
  150. }
  151.  
  152. return;
  153. }
  154.  
  155. //tenemos dos funciones para liberar la memoria de los arboles
  156. //la unica diferencia es que la primera libera el dato "persona"
  157. //y la segunda no.
  158. void destruir_personas(NodoArbolPersona **personas)
  159. {
  160. if(!(*personas))
  161. return;
  162.  
  163. destruir_personas(&((*personas)->menores));
  164. destruir_personas(&((*personas)->mayores));
  165.  
  166. free((*personas)->persona);
  167. free(*personas);
  168.  
  169. *personas = NULL;
  170. }
  171.  
  172. void destruir_clase(NodoArbolPersona **amigos)
  173. {
  174. if(!(*amigos))
  175. return;
  176.  
  177. destruir_personas(&((*amigos)->menores));
  178. destruir_personas(&((*amigos)->mayores));
  179.  
  180. free(*amigos);
  181.  
  182. *amigos = NULL;
  183. }
  184.  
  185. void problema_interactivo()
  186. {
  187. //cada componente del vector es un arbol que relaciona los amigos que forman una "clase"
  188. NodoArbolPersona *clases[DIM / 2], *personas = NULL; //personas: arbol de elementos valor-clase
  189. Persona *persona1, *persona2;
  190. int num_personas, num_casos, amigo1, amigo2;
  191. char operador;
  192.  
  193. for(num_personas = 0 ; num_personas < DIM / 2 ; num_personas++)
  194. clases[num_personas] = NULL;
  195.  
  196. scanf("%d", &num_personas);
  197. scanf("%d", &num_casos);
  198. while(getchar() != '\n');
  199.  
  200. while(num_casos--)
  201. {
  202. scanf("%c%d%d", &operador, &amigo1, &amigo2);
  203. while(getchar() != '\n');
  204.  
  205. switch(operador)
  206. {
  207. case 'S':
  208. insertar_amigos(clases, &personas,amigo1, amigo2);
  209. break;
  210.  
  211. case 'P':
  212. if((persona1 = buscar(personas,amigo1)) && (persona2 = buscar(personas,amigo2)))
  213. {
  214. if(persona1->clase == persona2->clase)
  215. printf("1\n");
  216. else
  217. printf("0\n");
  218. }
  219. else
  220. printf("0\n");
  221. }
  222. }
  223.  
  224. destruir_personas(&personas);
  225.  
  226. for(num_personas = 0 ; num_personas < DIM / 2 ; num_personas++)
  227. destruir_clase(&(clases[num_personas]));
  228. }
  229.  
  230. void problema_aleatorio()
  231. {
  232. //cada componente del vector es un arbol que relaciona los amigos que forman una "clase"
  233. NodoArbolPersona *clases[DIM / 2], *personas = NULL; //personas: arbol de elementos valor-clase
  234. Persona *persona1, *persona2;
  235. int num_personas, num_casos = DIM, amigo1, amigo2;
  236. char operador;
  237. char entrada[20];
  238.  
  239. srand(time(NULL));
  240.  
  241. for(num_personas = 0 ; num_personas < DIM / 2 ; num_personas++)
  242. clases[num_personas] = NULL;
  243.  
  244. while(num_casos--)
  245. {
  246. //vamos a forzar a que, aproximadamente, el 60% de los casos sean saludos
  247. sprintf(entrada,"%c %d %d",rand() % 10 < 6 ? 'S' : 'P', rand() % (DIM + 1), rand() % (DIM + 1));
  248. sscanf(entrada,"%c%d%d", &operador, &amigo1, &amigo2);
  249.  
  250. switch(operador)
  251. {
  252. case 'S':
  253. insertar_amigos(clases, &personas,amigo1, amigo2);
  254. break;
  255.  
  256. case 'P':
  257. if((persona1 = buscar(personas,amigo1)) && (persona2 = buscar(personas,amigo2)))
  258. {
  259. if(persona1->clase == persona2->clase)
  260. printf("1\n");
  261. else
  262. printf("0\n");
  263. }
  264. else
  265. printf("0\n");
  266. }
  267. }
  268.  
  269. destruir_personas(&personas);
  270.  
  271. for(num_personas = 0 ; num_personas < DIM / 2 ; num_personas++)
  272. destruir_clase(&(clases[num_personas]));
  273. }
  274.  
  275. int main(int argc, char *argv[])
  276. {
  277. //problema_interactivo();
  278. problema_aleatorio();
  279.  
  280. return 0;
  281. }
  282.  
« Última modificación: 29 Julio 2016, 21:44 pm por do-while » En línea

- Doctor, confundo los números y los colores.
- Vaya marrón.
- ¿Marrón? ¡Por el culo te la hinco!
AlbertoBSD
Programador y
Moderador Global
***
Desconectado Desconectado

Mensajes: 3.696


🏴 Libertad!!!!!


Ver Perfil WWW
Re: ¿Mejor algoritmo? Problema con aproximaciones de Grafos
« Respuesta #14 en: 30 Julio 2016, 18:04 pm »

Hola!

Dejo aqui mis 2 implementaciones

La primera con Un Grafo y Disjktra simplificado

Y la segunda como lo sugirio do-while con un arbol y una referencia a que arbol/clase/conjunto pertenece cada nodo (Esta última es la mas rapida)

Código
  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<stdlib.h>
  4. #include<stdbool.h>
  5. #include<time.h>
  6.  
  7.  
  8. #define MAXLINE 40
  9.  
  10. struct nodo_arbol {
  11. struct nodo_arbol *padre,*derecho,*izquierdo; // 12 u 24 bytes
  12. int valor; // 4 bytes
  13. }; //Total 16 u 28 bytes por Nodo
  14. //peor Caso 28 bytes * 100,000 nodos = ~2.8 MB
  15.  
  16. struct nodo {
  17. int id; //4 bytes
  18. int *relations; //4 ú 8 bytes
  19. int total; //4 bytes
  20. struct nodo_arbol *arbol; //4 ú 8 bytes
  21. int offset;
  22. int visitado;
  23. }; //Total 16 u 24 bytes por Nodo
  24. ///peor Caso 24 bytes * 100,000 nodos = ~2.40 MB
  25.  
  26. struct nodo **todos = NULL; //Futuro arreglo de todos los nodos existente
  27. //4 y 8 bytes
  28. //Peor caso 8 bytes * 100,000   = ~800 KB
  29.  
  30. void add_relation(int A,int B);
  31. bool existe_salto(int A,int B);
  32.  
  33. struct nodo_arbol *crear_nodo_arbol(struct nodo_arbol *padre,int valor);
  34. struct nodo_arbol *buscar_nodo_arbol(struct nodo_arbol *arbol,int valorAbuscar);
  35. struct nodo_arbol *agregar_valor_arbol(struct nodo_arbol *arbol,int valor);
  36.  
  37.  
  38. int main() {
  39. FILE *in = NULL;
  40. char *line = NULL;
  41. char *delim = " \n";
  42. char *token;
  43. char caso;
  44. int N,M,i,A,B;
  45. in = fopen("amistad.in","r"); //Archivo ¬¬
  46. srand(time(NULL)); // Para los nodos visitados...
  47. line = calloc(MAXLINE,1);
  48. //Leemos la primera linea
  49. fgets(line,MAXLINE,in);
  50. token = strtok(line,delim);
  51. N = strtol(token,NULL,10);
  52. todos = calloc(sizeof(struct nodo*),N); //Reservamos espacio para al menos N apuntadores a los nodos
  53. token = strtok(NULL,delim);
  54. M = strtol(token,NULL,10);
  55. //Leemos las siguientes M lineas y evaluamos
  56. i = 0;
  57. while(i < M) {
  58. memset(line,0,MAXLINE);
  59. //Leemos la M,esima linea
  60. fgets(line,MAXLINE,in);
  61. token = strtok(line,delim);
  62. caso = token[0];
  63. token = strtok(NULL,delim);
  64. A = strtol(token,NULL,10);
  65. A--;
  66. token = strtok(NULL,delim);
  67. B = strtol(token,NULL,10);
  68. B--;
  69. //Evaluamos
  70. switch(caso){
  71. case 'P':
  72. //printf("P %i %i\n",A+1,B+1);
  73. if(todos[A] && todos[B]) { // Ambos nodos son Validos, entonces hay que buscar si existe al menos un camino de a A a B
  74. if(existe_salto(A,B)) {
  75. printf("1\n");
  76. }
  77. else {
  78. printf("0\n");
  79. }
  80. }
  81. else { // Uno de los nodos es NULL entonces no existe camino de A a B
  82. //printf("Un nodo es invalido\n");
  83. printf("0\n");
  84. }
  85. break;
  86. case 'S':
  87. //printf("S %i %i\n",A+1,B+1);
  88. add_relation(A,B);
  89. break;
  90. }
  91. i++;
  92. }
  93. fclose(in);
  94. return 0;
  95. }
  96.  
  97. void add_relation(int A,int B) {
  98. if(todos[A] != NULL) {
  99. //Nodo ya inicializado;
  100. todos[A]->relations = realloc(todos[A]->relations,sizeof(int)*(todos[A]->total+1));
  101. todos[A]->relations[todos[A]->total] = B;
  102. todos[A]->arbol = agregar_valor_arbol(todos[A]->arbol,B);
  103. todos[A]->total++; //incrementamos el numero total de relaciones que tiene este nodo
  104. }
  105. else {
  106. //Nodo no inicializado
  107. todos[A] = calloc(sizeof(struct nodo),1);
  108. todos[A]->id  = A; //Esto es mera formalidad, ya que actualmente el indice del arreglo ya es el mismo "id"
  109. todos[A]->relations = realloc(todos[A]->relations,sizeof(int)*(todos[A]->total+1));
  110. todos[A]->relations[todos[A]->total] = B;
  111. todos[A]->arbol = agregar_valor_arbol(todos[A]->arbol,B);
  112. todos[A]->total++; //incrementamos el numero total de relaciones que tiene este nodo
  113. todos[A]->visitado = 0;
  114. todos[A]->offset = 0;
  115. }
  116. if(todos[B] != NULL) {
  117. //Nodo ya inicializado;
  118. todos[B]->relations = realloc(todos[B]->relations,sizeof(int)*(todos[B]->total+1));
  119. todos[B]->relations[todos[B]->total] = A;
  120. todos[B]->arbol = agregar_valor_arbol(todos[B]->arbol,A);
  121. todos[B]->total++; //incrementamos el numero total de relaciones que tiene este nodo
  122.  
  123. }
  124. else {
  125. //Nodo no inicializado
  126. todos[B] = calloc(sizeof(struct nodo),1);
  127. todos[B]->id  = B; //Esto es mera formalidad, ya que actualmente el indice del arreglo ya es el mismo "id"
  128. todos[B]->relations = realloc(todos[B]->relations,sizeof(int)*(todos[B]->total+1));
  129. todos[B]->relations[todos[B]->total] = A;
  130. todos[B]->arbol = agregar_valor_arbol(todos[B]->arbol,A);
  131. todos[B]->total++; //incrementamos el numero total de relaciones que tiene este nodo
  132. todos[B]->visitado = 0;
  133. todos[B]->offset = 0;
  134. }
  135. }
  136.  
  137. //A.k.a diskjtra simplificado a aristas de valor 1 y solo valida que exista la union
  138. bool existe_salto(int A,int B) {
  139. bool r = false,outs = false;
  140. struct nodo *nodo_a = NULL,*nodo_b =NULL,*inicio =NULL,*pivote = NULL;
  141. struct nodo_arbol *busqueda = NULL;
  142. struct nodo **pendientes = NULL;
  143. register int i,j,buscar,total = 0;
  144. int visitado;
  145. visitado = rand();
  146. nodo_a = todos[A];
  147. nodo_b = todos[B];
  148. if(nodo_a->total < nodo_b->total) {
  149. inicio = nodo_a;
  150. buscar = B;
  151. //printf("Menor A %i\n",inicio->id+1);
  152. }
  153. else {
  154. inicio = nodo_b;
  155. buscar = A;
  156. //printf("Menor B %i\n",inicio->id+1);
  157. }
  158. //printf("Nodos: ");
  159. i = 0;
  160. pendientes = realloc(pendientes,sizeof(struct nodo*)*(total+1));
  161. pendientes[total] = inicio;
  162. total++;
  163. while(!r && i < total) {
  164. pivote = pendientes[i];
  165. pivote->visitado = visitado;
  166. //printf("Visitando %i\n",pivote->id+1);
  167. busqueda = buscar_nodo_arbol(pivote->arbol,buscar);
  168. if(!busqueda) {
  169. //printf("El nodo %i no tiene el nodo buscado %i\n",pivote->id+1,buscar+1);
  170. j = 0;
  171. while(j < pivote->total ) {
  172. if(todos[pivote->relations[j]]->visitado != visitado) {
  173. //printf("Anexando el nodo %i para su posterior visita\n",todos[pivote->relations[j]]->id+1);
  174. pendientes = realloc(pendientes,sizeof(struct nodo*)*(total+1));
  175. pendientes[total] = todos[pivote->relations[j]];
  176. total++;
  177. }
  178. j++;
  179. }
  180. }
  181. else {
  182. //printf("El nodo %i SI tiene el nodo buscado %i\n",pivote->id+1,buscar+1);
  183. r = true;
  184. }
  185. i++;
  186. }
  187. free(pendientes);
  188. return r;
  189. }
  190.  
  191. //Funciones de Arbol (Solo como almacenamiento y busqueda rapida)
  192.  
  193. struct nodo_arbol *crear_nodo_arbol(struct nodo_arbol *padre,int valor) {
  194. struct nodo_arbol *n = calloc(sizeof(struct nodo_arbol),1);
  195. if(n == NULL) {
  196. printf("Error de Memoria\n");
  197. exit(0);
  198. }
  199. n->padre = padre;
  200. n->valor = valor;
  201. return n;
  202. }
  203.  
  204. struct nodo_arbol *agregar_valor_arbol(struct nodo_arbol *arbol,int valor) {
  205. struct nodo_arbol *temp,*pivote;
  206. int derecho = 0;
  207. if(arbol) {
  208. temp =arbol;
  209. while(temp != NULL) {
  210. pivote = temp;
  211. if(valor > temp->valor) {
  212. temp = temp->derecho;
  213. derecho = 1;
  214. }
  215. else {
  216. temp = temp->izquierdo;
  217. derecho = 0;
  218. }
  219. }
  220. temp = crear_nodo_arbol(pivote,valor);
  221. if(derecho) {
  222. pivote->derecho = temp;
  223. }
  224. else {
  225. pivote->izquierdo = temp;
  226. }
  227. return arbol;
  228. }
  229. else {
  230. temp = crear_nodo_arbol(NULL,valor);
  231. return temp;
  232. }
  233. }
  234.  
  235. struct nodo_arbol *buscar_nodo_arbol(struct nodo_arbol *arbol,int valorAbuscar) {
  236. struct nodo_arbol *temp = NULL,*pivote = NULL;
  237. int entrar = 1;
  238. temp =arbol;
  239. while(entrar == 1  && temp != NULL) {
  240. pivote = temp;
  241. if(valorAbuscar == temp->valor){
  242. entrar = 0;
  243. }
  244. else {
  245. if(valorAbuscar > temp->valor) {
  246. temp = temp->derecho;
  247. }
  248. else {
  249. temp = temp->izquierdo;
  250. }
  251. }
  252. }
  253. return temp;
  254. }


Código
  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<stdlib.h>
  4. #include<stdbool.h>
  5. #include<time.h>
  6.  
  7. #define MAXLINE 40
  8.  
  9. struct nodo_arbol {
  10. struct nodo_arbol *padre,*derecho,*izquierdo;
  11. struct nodo *valor;
  12. };
  13.  
  14. struct arbol {
  15. struct nodo_arbol *raiz;
  16. struct nodo_arbol **nodos;
  17. int total;
  18. };
  19.  
  20. struct nodo {
  21. int id;
  22. struct arbol *arbol;
  23. };
  24.  
  25. struct nodo **todos = NULL;
  26.  
  27. void add_relation(int A,int B);
  28. bool existe_salto(int A,int B);
  29. struct arbol *funciona_arbol(struct arbol *A,struct arbol *B);
  30.  
  31. struct nodo_arbol *crear_nodo_arbol(struct nodo_arbol *padre,struct nodo *valor);
  32. struct arbol *agregar_valor_arbol(struct arbol *arbol,struct nodo *valor);
  33.  
  34. int main() {
  35. FILE *in = NULL;
  36. char *line = NULL;
  37. char *delim = " \n";
  38. char *token;
  39. char caso;
  40. int N,M,i,A,B;
  41. in = fopen("amistad.in","r"); //Archivo ¬¬
  42. srand(time(NULL)); // Para los nodos visitados...
  43. line = calloc(MAXLINE,1);
  44. //Leemos la primera linea
  45. fgets(line,MAXLINE,in);
  46. token = strtok(line,delim);
  47. N = strtol(token,NULL,10);
  48. todos = calloc(sizeof(struct nodo*),N); //Reservamos espacio para al menos N apuntadores a los nodos
  49. token = strtok(NULL,delim);
  50. M = strtol(token,NULL,10);
  51. //Leemos las siguientes M lineas y evaluamos
  52. i = 0;
  53. while(i < M) {
  54. memset(line,0,MAXLINE);
  55. //Leemos la M,esima linea
  56. fgets(line,MAXLINE,in);
  57. token = strtok(line,delim);
  58. caso = token[0];
  59. token = strtok(NULL,delim);
  60. A = strtol(token,NULL,10);
  61. A--;
  62. token = strtok(NULL,delim);
  63. B = strtol(token,NULL,10);
  64. B--;
  65. //Evaluamos
  66. switch(caso){
  67. case 'P':
  68. //printf("P %i %i\n",A+1,B+1);
  69. if(todos[A] && todos[B]) { // Ambos nodos son Validos, entonces hay que buscar si existe al menos un camino de a A a B
  70. if(existe_salto(A,B)) {
  71. printf("1\n");
  72. }
  73. else {
  74. printf("0\n");
  75. }
  76. }
  77. else { // Uno de los nodos es NULL entonces no existe camino de A a B
  78. //printf("Un nodo es invalido\n");
  79. printf("0\n");
  80. }
  81. break;
  82. case 'S':
  83. //printf("S %i %i\n",A+1,B+1);
  84. add_relation(A,B);
  85. break;
  86. }
  87. i++;
  88. }
  89. fclose(in);
  90. return 0;
  91. }
  92.  
  93. void add_relation(int A,int B) {
  94. struct nodo *nodo_a,*nodo_b;
  95. if(todos[A] == NULL) { // Si no existe A lo inicializamos
  96. todos[A] = calloc(sizeof(struct nodo),1);
  97. todos[A]->id  = A;
  98. }
  99. if(todos[B] == NULL) { // Si no existe B lo inicializamos
  100. todos[B] = calloc(sizeof(struct nodo),1);
  101. todos[B]->id  = B;
  102. }
  103. nodo_a = todos[A];
  104. nodo_b = todos[B];
  105. if(!nodo_a->arbol && !nodo_b->arbol){ // Si ambos arboles son NULL los inicializamos
  106. nodo_a->arbol = agregar_valor_arbol(nodo_a->arbol,nodo_a);
  107. nodo_a->arbol = agregar_valor_arbol(nodo_a->arbol,nodo_b);
  108. }
  109. else {
  110. if(nodo_a->arbol && !nodo_b->arbol) { //Si el arbol de A es valido y el de B no, agregamos B al arbol de A
  111. nodo_a->arbol =agregar_valor_arbol(nodo_a->arbol,nodo_b);
  112. }
  113. else {
  114. if(!nodo_a->arbol && nodo_b->arbol){ //Si el arbol de B es valid y el de A no, agregamo A al arbol de B
  115. nodo_b->arbol =agregar_valor_arbol(nodo_b->arbol,nodo_a);
  116. }
  117. else{// En este punto ambos arboles son validos
  118. if(nodo_a->arbol != nodo_b->arbol) { //Validamos si ambos arboles son distintos
  119. if(nodo_a->arbol->total < nodo_b->arbol->total) { // Evaluamos cual es el arbol con mejor coste de fusion
  120. nodo_b->arbol = funciona_arbol(nodo_b->arbol,nodo_a->arbol); //Fucionamos el arbol de A en el arbol de B
  121. }
  122. else {
  123. nodo_a->arbol = funciona_arbol(nodo_a->arbol,nodo_b->arbol); //Fucionamos el arbol de B en el arbol de A
  124. }
  125. }
  126. }
  127. }
  128. }
  129. }
  130.  
  131. //Fucinamos el arbol B en el arbol A, y eliminamos B nodo por nodo y finalmente liberamos la estructura Arbol que usamos
  132. struct arbol *funciona_arbol(struct arbol *A,struct arbol *B) {
  133. int i = 0;
  134. while(i<B->total) {
  135. B->nodos[i];
  136. A = agregar_valor_arbol(A,B->nodos[i]->valor);
  137. free(B->nodos[i]);
  138. i++;
  139. }
  140. free(B);
  141. return A;
  142. }
  143.  
  144.  
  145. //Evaluar si existe un camino valido de A a B, se reduce a validar si estan en el mismo Arbol o no
  146. bool existe_salto(int A,int B) {
  147. struct nodo *nodo_a = NULL,*nodo_b =NULL;
  148. nodo_a = todos[A];
  149. nodo_b = todos[B];
  150. return (nodo_a->arbol == nodo_b->arbol);
  151. }
  152.  
  153.  
  154. //Funcion auxiliar para crear un nodo de arbol
  155. struct nodo_arbol *crear_nodo_arbol(struct nodo_arbol *padre,struct nodo *valor) {
  156. struct nodo_arbol *n = calloc(sizeof(struct nodo_arbol),1);
  157. if(n == NULL) {
  158. printf("Error de Memoria\n");
  159. exit(0);
  160. }
  161. n->padre = padre;
  162. n->valor = valor;
  163. return n;
  164. }
  165.  
  166. //Agregamos un valor al arbol
  167. struct arbol *agregar_valor_arbol(struct arbol *arbol,struct nodo *valor) {
  168. struct nodo_arbol *temp,*pivote;
  169. int derecho = 0;
  170. if(arbol) {
  171. temp =arbol->raiz;
  172. while(temp != NULL) {
  173. pivote = temp;
  174. if(valor->id > temp->valor->id) {
  175. temp = temp->derecho;
  176. derecho = 1;
  177. }
  178. else {
  179. temp = temp->izquierdo;
  180. derecho = 0;
  181. }
  182. }
  183. temp = crear_nodo_arbol(pivote,valor);
  184. if(derecho) {
  185. pivote->derecho = temp;
  186. }
  187. else {
  188. pivote->izquierdo = temp;
  189. }
  190. valor->arbol = arbol;
  191. arbol->nodos = realloc(arbol->nodos,sizeof(struct nodo*)*(arbol->total+1));
  192. arbol->nodos[arbol->total] = temp;
  193. }
  194. else {
  195. arbol = calloc(sizeof(struct arbol),1);
  196. arbol->raiz = crear_nodo_arbol(NULL,valor);
  197. arbol->nodos = realloc(arbol->nodos,sizeof(struct nodo_arbol*)*(arbol->total+1));
  198. arbol->nodos[arbol->total] = arbol->raiz;
  199. valor->arbol = arbol;
  200. }
  201. arbol->total++;
  202. return arbol;
  203. }

En línea

Páginas: 1 [2] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Cual es el mejor algoritmo de encriptacion de truecrypt
Criptografía
AALD666 4 9,459 Último mensaje 3 Enero 2014, 03:47 am
por QuemoZem
Problema con grafos
Java
Puma93 1 1,594 Último mensaje 20 Junio 2013, 22:50 pm
por kasuki92
Un algoritmo determina mejor la relevancia de una película que crítica y público
Noticias
wolfbcn 0 1,271 Último mensaje 20 Enero 2015, 01:42 am
por wolfbcn
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines