Ver Mensaje Individual
  #2 (permalink)  
Antiguo 30/09/2014, 05:11
vosk
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Generar un numero variable de nodos para una lista

Puede que no me quede clara tu duda, pero me parece que lo que buscas es ir añadiendo los nuevos nodos como siguiente del anterior. Algo asi:

- creas un nodo inicial
- creas un segundo nodo y lo añades como siguiente del primero
- creas un tercer nodo y lo añades como siguiente del segundo
- etc

Es lo que sería una lista simple; en tu codigo tienes una lista doble, es decir, que cada nodo apunta a su anterior y a su siguiente; si el anterior el primero apunta al ultimo y el siguiente del ultimo apunta al primero entonces tienes una lista circular. No se si ya te suena de algo todo esto.

Te propongo un ejemplo de lista simple para ver como añadir nodos al final:

Código C++:
Ver original
  1. class COSA {
  2. public:
  3.     void set_name(string name) {
  4.         this->name = name;
  5.     }
  6.     string get_name() {
  7.         return this->name;
  8.     }
  9.  
  10. private:
  11.     string name;
  12. };
  13.  
  14.  
  15. typedef struct tagNodo{
  16.     class COSA *cosa;
  17.     struct tagNodo *sig;
  18. } Nodo;
  19.  
  20.  
  21. class COSA *crea_cosa(string nombre) {
  22.     class COSA *cosa = 0;
  23.  
  24.     if((cosa = new(nothrow) class COSA)) {
  25.         cosa->set_name(nombre);
  26.     }
  27.  
  28.     return cosa;
  29. }
  30.  
  31.  
  32. void add_cosa(Nodo **lista, class COSA *cosa) {
  33.     Nodo *nuevo_nodo, *ptr;
  34.  
  35.     if((nuevo_nodo = new(nothrow) Nodo)) {
  36.         nuevo_nodo->cosa = cosa;
  37.         nuevo_nodo->sig = 0;
  38.  
  39.         if(!(ptr = *lista)) {
  40.             *lista = nuevo_nodo;
  41.         }
  42.         else {
  43.             while(ptr->sig) {
  44.                 ptr = ptr->sig;
  45.             }
  46.             ptr->sig = nuevo_nodo;
  47.         }
  48.     }
  49. }
  50.  
  51.  
  52. void muestra_cosas(Nodo *lista) {
  53.     Nodo *ptr;
  54.  
  55.     ptr = lista;
  56.     while(ptr) {
  57.         cout << ptr->cosa->get_name() << endl;
  58.         ptr = ptr->sig;
  59.     }
  60. }
  61.  
  62.  
  63. void libera_cosas(Nodo **lista) {
  64.     Nodo *ptr, *sig;
  65.  
  66.     ptr = *lista;
  67.     while(ptr) {
  68.         sig = ptr->sig;
  69.         delete ptr->cosa;
  70.         delete ptr;
  71.  
  72.         ptr = sig;
  73.     }
  74.     *lista = 0;
  75. }
  76.  
  77.  
  78. int main() {
  79.     Nodo *lista_de_cosas;
  80.     COSA *ptr;
  81.  
  82.     lista_de_cosas = 0;
  83.  
  84.     ptr = crea_cosa("una");
  85.     add_cosa(&lista_de_cosas, ptr);
  86.     ptr = crea_cosa("prueba");
  87.     add_cosa(&lista_de_cosas, ptr);
  88.     ptr = crea_cosa("de");
  89.     add_cosa(&lista_de_cosas, ptr);
  90.     ptr = crea_cosa("texto");
  91.     add_cosa(&lista_de_cosas, ptr);
  92.  
  93.     muestra_cosas(lista_de_cosas);
  94.     libera_cosas(&lista_de_cosas);
  95.  
  96.     return 0;
  97. }

Tal como ves puedo seguir añadiendo hasta que se agote la memoria. Hay algunas cosas importantes a tener en cuenta: hacer las comprovaciones de error para el caso de que no haya memoria disponible. En el ejemplo estoy usando new(nothrow) para que no me arroje excepciones y validar directamente el retorno contra nulo (nulo si no hay memoria disponible). Otra cosa importante es iniciar los elementos nulos como nulos (no recuerdo si c++ no hace por defecto, pero es mejor asegurarse), es el caso de la lista_de_cosas, quiero que inicialmente sea nula para que la funcion de añadir entienda que a la primera llamada le envio una lista nula; lo mismo para los punteros 'sig' que hay en la estructura, que antes de ser rellenados con un nodo siguiente quiero que sean nulos. Una ultima cosa, para cada new necesitas un delete, es lo que hago en la funcion de liberar_cosas; en los pc actuales esto de liberar la memoria dinamica solo tiene sentido cuando quieres reutilizar en la misma ejecucion la misma variable para mas de una lista, pero es una buena practica liberar la memoria reservada y por eso te lo pongo.

Otra cosa, ya que estas en c++ porque no usas un contenedor tipo vector o list para hacer estas listas? Te resultará mas fácil y seguramente tendras menos fallos. COn eso te ahorras el trabajo con structs, que en tu ejemplo parece ser que solo las usas para soportar los punteros siguiente y anterior. Tambien puedes separar el manejador de listas en una nueva clase: una clase que se encargará de manejar la lista.

Saludos
vosk