Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - AlbertoBSD

#1401
Programación C/C++ / Re: Ejercicios de C++
31 Mayo 2016, 13:51 PM
Quieres los archivos? o quieres los cursos?, si es lo ultimo en internet hay muchos recursos.

Por ejemplo  :rolleyes: :rolleyes: mi canal de youtube tengo varios videos y estoy subiendo al menos uno cada 2 dias

Videos de Programacion en C
#1402
 ;-) ;-) ;-)

CitarSe trata de un nodo rama: en ese caso no podemos eliminarlo, puesto que perderíamos todos los elementos del árbol de que el nodo actual es padre. En su lugar buscamos el nodo más a la izquierda del subárbol derecho, o el más a la derecha del subárbol izquierdo e intercambiamos sus valores. A continuación eliminamos el nodo hoja.

El mas izquierdo del subarbol derecho o el mas derecho del subarbol izquierdo Tiene mucha logica no se por que no se me ocurrio antes.

Esta genial!!!



Solucion

Como comentan en la lectura  del vinculo que puso MAFUS,

Ellos abordan el problema de 2 maneras.


  • Es un nodo hoja (No tiene hijos)
  • Es un nodo rama (tiene almenos un hijo)

Buscan el nodo mas izquierdo del subarbol derecho o buscan el nodo mas derecho del subarbol izquierdo, intercambian los valores con el nodo a eliminar y eliminan el ultimo nodo que ahora contiene el valor que queriamos eliminar en un principio.

Decidi por abordando el problema como lo plantee en un principio

  • Es un nodo hoja
  • Es un nodo rama (Con un solo hijo)
  • Es un nodo rama (Con los 2 hijos)

Ya que cuando el nodo a eliminar tiene solo un hijo es mas facil solo revincular a el padre del nodo a eliminar con ese unico hijo.

Ahora en el tercer caso cuando el nodo a eliminar tiene 2 hijos lo que decidi a hacer es intercambiar el valor del nodo a eliminar con el de alguno de lo hijos y ahora evaluar iterativamente si este nuevo nodo tiene hijos o no esperando que llegue al caso 1 o 2.

if(n->derecho != NULL && n->izquierdo != NULL) {
if((rand() % 2) == 1) {
printf("Elijiendo derecho\n");
derecho = n->derecho;
temp = n->valor;
n->valor = derecho->valor;
derecho->valor = temp;
temp = NULL;
n=derecho;
}
else {
printf("Elijiendo izquierdo\n");
izquierdo = n->izquierdo;
temp = n->valor;
n->valor = izquierdo->valor;
izquierdo->valor = temp;
temp = NULL;
n=izquierdo;
}
}


ventajas y desventajas de esta implementacion.

Dependiendo de la profundidad del arbol esta implementacion podria ser mas rapida.

En el peor de los casos todos los subarboles siguientes tienen 2 hijos cada uno hasta llegar al ultimo nivel del arbol... ahi si es mas rapido el metodo descrito en el link

Ya que es muy rapido llegar al subnodo mas derecho del hijo izquierdo o al subnodo mas izquierdo del hijo derecho e intercambiar valores con el nodo a eliminar y posteriormente eliminado el nodo deseado.

Saludos
#1403
Nunca lo he usado asi pero puedes empalmar las lineas:


switch (caracter){
  case 'a':
  case 'b':
//hacer algo en caso de a o b
  break;
}
#1404
No necesariamente depende del uso que le estes dando al arbol. En este caso simplemente lo estoy usando como un contenedor de datos.

Por ejemplo en este lo estoy usando para contener un lista de libros muy grande.

Ver http://foro.elhacker.net/foro_libre/lista_de_libros_para_usar_en_programa-t452891.0.html

Y por ejemplo para agregar un nodo "libro" solo le toma log n operaciones encontrar su lugar en el arbol.

Y para buscar un nodo igualmente le toma solo log n operaciones.

Entonces si por casualidad queremos quitar un nodo y este nodo tiene hijos hay que reorganizar el arbol.

Claro que como dices tambien tengo que tener alguna funcion que elimine un subarbol pero... para los fines de mi programa ahorita no necesito esa función.

Saludos.
#1405
Tengo un detalle al momento de eliminar un nodo del arbol binario.

Dada la estructura:

struct nodo {
struct nodo *padre;
struct nodo *izquierdo;
struct nodo *derecho;
char *valor;
};


Ya puedo agregar y buscar nodos sin problema y al momento de eliminar nodos hay varios casos ya aborde la mayoria de ellos solo tengo un detalle con el ultimo.

Casos:

  • El Nodo a eliminar no tiene hijos (Listo)
  • El Nodo a eliminar solo tiene un hijo derecho o izquierdo (Listo)
  • El Nodo a eliminar tiene ambos hijos (Pendiente)

El detalles es el decidir como reconectar los nodos cuando el noda eliminar tiene 2 hijos... (Si es un problema de algoritmo pero lo pongo aqui por que esta en C)

Si esos 2 hijos no tienen hijos no hay problema simplemente selecciono uno y lo pongo en el lugar del nodo eliminado. Pero el peor de los casos es cuando ambos nodos tienes 2 hijos cada uno mas o menos asi:


      p
      |
->     n
    /   \
   d     i
  / \   / \
 d   i d   i



La pregunta que tengo aqui seria la siguiente...

Tengo que hacer una funcion que reconecte y reorganize los nodos del arbol ¿Que recomendarian ustedes una funcion iterativa o una recursiva?

La otra solucion que tengo es manejar el nodo a eliminar como un arbol independiente desvincularlo del arbol principal y recorrer este nuevo subarbol de izquierda a derecha o viceversa y agregar cada nodo del subarbol al arbol principal, con excepcion de nodo a eliminar que seria la raiz del subarbol.

¿Que recomiendan ustedes?

La funcion que tengo es la siguiente:

void eliminar_nodo(struct nodo *arbol,char *valor) {
struct nodo *n;
struct nodo *padre;
struct nodo *derecho;
struct nodo *izquierdo;
if(debug_arbol)
debug_arbol = 0;
n = buscar_valor(arbol,valor);
if(n) {

if(n->derecho == NULL && n->izquierdo == NULL) {
//No tiene hijos, hay que determinar si es el hijo derecho o izquierdo de su padre y desvincularlo
padre = n->padre;
if(padre->derecho == n) {
padre->derecho = NULL;
free_nodo(n);
}
else {
padre->izquierdo = NULL;
free_nodo(n);
}
}
else {
if(n->derecho != NULL && n->izquierdo != NULL) {
// Tiene 2 Hijos
padre = n->padre;
// Detalle aqui.....

}
else {
if(n->derecho != NULL) { //Solo tiene al hijo derecho
derecho = n->derecho;
padre = n->padre;
if(padre->derecho == n) { //hay que determinar si es el hijo derecho o izquierdo de su padre y vincular dicho nodo, con el nodo derecho del n actual y liberar n despues de eso
padre->derecho = derecho;
free_nodo(n);
}
else {
padre->izquierdo = derecho;
free_nodo(n);
}
}
else { //Solo tiene al hijo izquierdo
izquierdo = n->izquierdo;
padre = n->padre;
if(padre->derecho == n) { //hay que determinar si es el hijo derecho o izquierdo de su padre y vincular dicho nodo, con el nodo izquierdo del n actual y liberar n despues de eso
padre->derecho = izquierdo;
free_nodo(n);
}
else {
padre->izquierdo = izquierdo;
free_nodo(n);
}
}
}
}
}
else {
printf("No existe un nodo con el valor \"%s\" en el arbol\n",valor);
}
}





Solucion en : http://foro.elhacker.net/programacion_cc/c_eliminando_nodo_de_arbol_binario-t453185.0.html;msg2072953#msg2072953
#1406
 :silbar: :silbar: Reconozco ese codigo   ;-) ;-)

Sobre el exec necesitas:

#include <unistd.h>

Y mas info al respecto de esas funciones en: http://linux.die.net/man/3/exec


Cita de: ccsponcer3 en 30 Mayo 2016, 04:37 AM
Lo que no tengo idea mucho es como proceder y especificamente que me esta diciendo. Gracias!

Citarignoring return value of 'fgets', declared with attribute warn_unused_result [-Wunused-result]

Te esta diciendo que se esta ignorando el resultado que devuelven esas funciones cada una devuelve algun valor con el cual puedes validar que la funciones tuvo exito o no..

Sobre el warning de fscanf  y fgets son omitibles solo si realmente quieres validar si hay o no error por ejemplo fgets devuelve:


Citargets() and fgets() return s on success, and NULL on error or when end of file occurs while no characters have been read.

Mas info en http://linux.die.net/man/3/fgets

Lo que quiere decir es que realmente tendrias que agregar esto:

dd = fgets(dd,1000,conf);
if(dd == NULL){
 printf("Error\n");
 exit(0);
}


Eso fue para el fgets y para el fscanf tenemos

http://linux.die.net/man/3/fscanf

CitarThese functions return the number of input items successfully matched and assigned, which can be fewer than provided for, or even zero in the event of an early matching failure.

Dice que tienes que tener:

int err;
err =  fscanf(conf,"NOMBRE_SWAP=%s\n\r",nombre_swap);
if(err == 0){
 printf("Error\n");
 exit(0);
}
//Asi con todos y cada uno de los fscanf



Pero repito realemente es omitible el warning

Saludos!
#1407
En teoria eso depende totalmente del sistema operativo.

Cuando ejecutas el programa el sistema le asigna recursos y al final los recicla.

Si te fijas cuando inicias el programa las variables pueden estar o no estar inicializadas y si te pones a ejecutar un programa y pides un poco de memoria dinamica. puedes imprimir X cantidad de bytes mas y tal vez veas datos de programas viejos.

#1408
Tienes que pasarla a hexadecimal byte por byte, en un ciclo:


i = 0;
l = 20;
while(i < l) {
printf("%.2x",hash[i++]);
}


Aun asi creo que debe de existir otra implementacion que ya te lo pase en hecadecimal...

Saludos
#1409
Por la aritmetica de apuntadores....

Si sumas el indice mas el valor de la direccion a la que apunta apuntador estaras llegando a la misma posicion ya sea con

indice[arr]
o con
arr[indice]

Es como si tienes

*(indice + arr)

o

*(arr + indice)

Ya que la suma es conmutativa.

Saludos
#1410
Antes de cerrar el programa tienes que guardarlo en un archivo y posteiormente cuando habras el programa determinar si el archivo existe y si es asi abrirlo y cargar los datos.

Te dejo un video de como hacerlo en un Arbol Binario, solo tendrias que cambiar el arbol por la lista y seria practicamente lo mismo.

[youtube=640,360]https://www.youtube.com/watch?v=b-rnszAiQgc[/youtube]

Saludos!