Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Cas980 en 17 Mayo 2014, 19:50 pm



Título: Problemas listas
Publicado por: Cas980 en 17 Mayo 2014, 19:50 pm
Estoy trabajando con listas dobles circulares, espero puedan ayudarme.
Lo que intento hacer es que al ir agregando se vayan ordenando los datos
Pero tengo problemas con el ultimo caso, como hago la comparacion y como voy avanzando si lo tengo que hacer de forma recursiva??


Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #define SALIR 0
  6.  
  7. typedef struct nodo
  8. {
  9.    int dato;
  10.    struct nodo *sig;
  11.    struct nodo *ant;
  12. }NODO;
  13.  
  14. typedef struct punteros
  15. {
  16.    struct nodo *inicio;
  17.    struct nodo *fin;
  18. }LISTA;
  19.  
  20. int agregar_ordenado(LISTA *aux, int dato)
  21. {
  22.    if(aux->inicio==NULL)//LISTA VACIA
  23.    {
  24.        NODO *nuevo=(NODO *)malloc(sizeof(NODO));
  25.        nuevo->dato=dato;
  26.        nuevo->ant=nuevo;
  27.        nuevo->sig=nuevo;
  28.        aux->fin=nuevo;
  29.        aux->inicio=nuevo;
  30.        return 1;
  31.    }
  32.    if(dato > aux->inicio->dato)//ES MAYOR AL INICIO
  33.    {
  34.        NODO *nuevo=(NODO *)malloc(sizeof(NODO));
  35.        nuevo->dato=dato;
  36.        nuevo->sig=aux->inicio;
  37.        aux->inicio->ant=nuevo;
  38.        aux->inicio=nuevo;
  39.        nuevo->ant=aux->fin;
  40.        aux->fin->sig=aux->inicio;
  41.        return 1;
  42.    }
  43.    if(dato < aux->fin->dato)//ES MENOR AL FIN
  44.    {
  45.        NODO *nuevo=(NODO *)malloc(sizeof(NODO));
  46.        nuevo->dato=dato;
  47.        nuevo->ant=aux->fin;in        aux->fin->sig=nuevo;
  48.        nuevo->sig=aux->inicio;
  49.        aux->inicio->ant=nuevo;
  50.        return 1;
  51.    }
  52.    if()//EN MEDIO DE LA LISTA
  53.    {
  54.  
  55.    }
  56.  
  57.    agregar_ordenado(aux->inicio->sig)
  58.  
  59. }
  60.  
  61.  
  62.  
  63. void imprimir(LISTA *aux)//DEL ULTIMO AREGADO AL PRIMERO
  64. {
  65. NODO *actual;
  66. actual = aux->inicio;
  67. while(actual != aux->fin)
  68.    {
  69. printf(" %i ",actual->dato);
  70. actual = actual->sig;
  71. }
  72. printf(" %i ",actual->dato);
  73. printf("\n");
  74. }
  75.  
  76.  
  77. int main()
  78. {
  79.    NODO *lista =NULL;
  80.    LISTA *aux=(LISTA *)malloc(sizeof(LISTA));
  81.    int op,dat,num;
  82.  
  83.    aux->inicio = NULL;
  84.    aux->fin = NULL;
  85.    do
  86.    {
  87.        printf("\n 1.Agregar elemento");
  88.        printf("\n 2.Imprimir lista");
  89.        printf("\n 0.salir");
  90.        scanf(" %d",&op);
  91.        switch(op)
  92.        {
  93.        case 0:
  94.            exit(0);
  95.        case 1:
  96.            printf("\n Ingrese dato: ");
  97.            scanf(" %d",&dat);
  98.            agregar_ordenado(aux,dat);
  99.            break;
  100.        case 2:
  101.            imprimir(aux);
  102.            break;
  103.        }
  104.  
  105.  
  106.    }while(op!=SALIR);
  107.    return 0;
  108. }
  109.  

    


Título: Re: Problemas listas dobles
Publicado por: eferion en 19 Mayo 2014, 09:21 am
Una lista doblemente enlazada se caracteriza porque puedes recorrerla hacia adelante o hacia atrás indiferentemente.

La norma general para añadir un elemento es, una vez localizada la posición en la que se ha de insertar, realizar las siguientes operaciones:

1. nuevo_nodo->puntero_anterior = nodo_anterior;
2. nuevo_nodo->puntero_siguiente = nodo_siguiente;
3. nodo_anterior->puntero_siguiente = nuevo_nodo;
4. nodo_siguiente->puntero_anterior = nuevo_nodo;

Esta norma general tiene 2 excepciones:

* Si el nodo va en primer lugar, se omite el paso 3 y el 1 apunta a null.
* Si el nodo va al final, se omite el paso 4 y el 2 apunta a null.

Si resulta que la lista está vacía, se dan a la vez las dos circunstancias anteriores... basta con aplicarlas.

En tu caso concreto, hablando sobre el "cuarto caso", lo que tienes que hacer es seguir los 4 puntos que te he indicado. No tiene pérdida.

Por cierto, si la lista va a ser SIEMPRE ordenada, agregar_principio y agregar_ordenado colisionan entre sí, deberías eliminar una de las dos funciones para evitar código duplicado.

Es más, si tu idea es recorrer la lista para ubicar un elemento, no puedes usar un puntero a tipo "LISTA"... tienes que usar uno a tipo "NODO", para poder recorrer de forma recursiva la lista:

Código
  1. void agregar_elemento( LISTA* lista, NODO* nodo_ant, int dato )
  2. {
  3.  if (lista->inicio == NULL)
  4.  {
  5.    // Este caso se da cuando la lista esta vacia
  6.    NODO *nuevo=(NODO *)calloc(1, sizeof(NODO));
  7.    nuevo->dato = dato;
  8.    lista->inicio = nuevo;
  9.    lista->fin = nuevo;
  10.  }
  11.  else if ( nodo_ant->dato < dato )
  12.  {
  13.    // el nuevo nodo va "antes" que nodo_ant
  14.    NODO *nuevo=(NODO *)malloc(sizeof(NODO));
  15.    nuevo->dato = dato;
  16.    nuevo->ant = nodo_ant->ant;
  17.    nuevo->sig = nodo_ant;
  18.    nodo_ant->sig = nuevo;
  19.  
  20.    if ( nodo_ant->ant )
  21.      nodo_ant->ant->sig = nuevo;
  22.    else
  23.      lista->inicio = nuevo;
  24.  }
  25.  else if ( nodo_ant->dato > dato )
  26.  {
  27.    // El nuevo nodo va despues que "nodo_ant"
  28.    // Hay que comprobar si hemos llegado al final de la lista
  29.  
  30.    if ( nodo_ant->sig )
  31.      agregar_elemento( nodo_ant->sig );
  32.    else
  33.    {
  34.      // nodo_ant es el ultimo elemento de la lista, el nuevo tiene que ir despues
  35.      NODO *nuevo=(NODO *)calloc(1, sizeof(NODO));
  36.      nuevo->dato = dato;
  37.      nuevo->ant = nodo_ant;
  38.      nodo_ant->sig = nuevo;
  39.      lista->fin = nuevo;
  40.    }
  41.  }
  42. }

Incluso se podría optimizar más el código usando dos funciones ( una para localizar la ubicación del nuevo nodo y otra para insertarlo ), pero eso ya te lo dejo a ti.