Estoy trabajando en los ejercicios del capítulo "Punteros" de "Programación en C" de Kochan.

He escrito un programa que crea una lista doblemente enlazada. Primero imprime los valores. Luego procede a llamar a una función para eliminar una entrada. Los valores se vuelven a imprimir.

Finalmente, se llama a una función adicional para AGREGAR una entrada, seguida de una impresión nuevamente.

Ahora mismo, mi código funciona. Puedes verlo aqui:

#include <stdio.h>


struct entry
    {
        int value;
        struct entry *next;
        struct entry *previous;
    };

void removeEntry(struct entry *start);
void insertEntry(struct entry *addOn, struct entry *element);

int main (void)
{

    //declarations
    struct entry n1, n2, n3, addOn;
    struct entry *list_pointer = &n1;


    //creates list values and links
    n1.value = 100;
    n1.next = &n2;
    n1.previous = list_pointer;

    n2.value = 200;
    n2.next = &n3;
    n2.previous = &n1;

    n3.value = 300;
    n3.next = (struct entry *) 0;
    n3.previous = &n2;

    //prints out all list values
    while(list_pointer != (struct entry *) 0)
    {
        printf("%i\n", list_pointer->value);
        list_pointer = list_pointer->next;
    }

    printf("\n");

    //resets list_pointer back to start
    list_pointer = &n1;

    //calls function and removes n2 from list by directly linking n1 to n3
    removeEntry(&n2);

    //print out amended list
    while(list_pointer != (struct entry *) 0)
    {
        printf("%i\n", list_pointer->value);
        list_pointer = list_pointer->next;
    }

    printf("\n");

    list_pointer = &n1;
    insertEntry(&addOn, &n3);

    //print out amended list
    while(list_pointer != (struct entry *) 0)
    {
        printf("%i\n", list_pointer->value);
        list_pointer = list_pointer->next;
    }

    return 0;
}

void removeEntry(struct entry *start)
{
    start->previous->next = start->next;
}

void insertEntry(struct entry *addOn, struct entry *element)
{
    element->next = addOn;
    addOn->value = 400;
    addOn->next = (struct entry *) 0;
}

SIN EMBARGO, una vez hecho esto, quería verificar si se habían publicado otras soluciones en línea, por si me faltaba algo.

Bueno, encontré una pregunta y respuesta AQUÍ y existen diferencias considerables.

Ignorando la diferencia en el formato de cómo se imprimen los valores, puede ver que hay mucho más código escrito, especialmente en las funciones. Esta es mi función de eliminación de nuevo:

void removeEntry(struct entry *start)
{
    start->previous->next = start->next;
}

Y este es de ellos:

void RemoveEntry(struct Entry *EntryToRemove)
{
    if (EntryToRemove->Previous != NULL)
    {
        EntryToRemove->Previous->Next = EntryToRemove->Next;
    }
    if (EntryToRemove->Next != NULL)
    {
        EntryToRemove->Next->Previous = EntryToRemove->Previous;
    }
    EntryToRemove->Previous = NULL;
    EntryToRemove->Next = NULL;
}

Ahora puedo ver que hay una verificación para NULL, pero aparte de eso, están trabajando con los valores Previous y Next y tienen una declaración if para cada uno.

Del mismo modo, puede ver mi función insert aquí:

void insertEntry(struct entry *addOn, struct entry *element)
{

    element->next = addOn;
    addOn->value = 400;
    addOn->next = (struct entry *) 0;
}

Y los de ellos:

void InsertEntry(struct Entry *InsertPosition, struct Entry *EntryToInsert)
{
    EntryToInsert->Previous = InsertPosition->Previous;
    EntryToInsert->Next = InsertPosition;
    if (InsertPosition->Previous != NULL)
    {
        InsertPosition->Previous->Next = EntryToInsert;
    }
    InsertPosition->Previous = EntryToInsert;
}

Tenga en cuenta que mi código hace exactamente lo que estaba tratando de hacer, mi salida impresa es:

100
200
300

100
300

100
300
400

¿Puedes intentar explicarme esto? Me siento como un idiota por no ser capaz de entender esto.

Este es su código completo:

#include <stdio.h>vv

struct Entry
{
    int Value;
    struct Entry *Previous;
    struct Entry *Next;
};

void InsertEntry(struct Entry *InsertPosition, struct Entry *EntryToInsert);
void RemoveEntry(struct Entry *EntryToRemove);

int main()
{
    struct Entry N1, N2, N3, N4, N5, Insert, *Start = &N1;

    //set initial values
    N1.Value = 10;
    N2.Value = 20;
    N3.Value = 20;
    N4.Value = 30;
    N5.Value = 40;
    Insert.Value = 35;

    //link the list

    N1.Next = &N2;
    N2.Next = &N3;
    N3.Next = &N4;
    N4.Next = &N5;
    N5.Next = NULL;
    //Link again

    N1.Previous = NULL;
    N2.Previous = &N1;
    N3.Previous = &N2;
    N4.Previous = &N3;
    N5.Previous = &N4;

    InsertEntry(&N4, &Insert);
    RemoveEntry(&N2);

    //Display the Lists
    while (Start != (struct Entry *) 0)
    {
        printf("Previous: ");
        if (Start->Previous != NULL)
        {
            printf("%i", Start->Previous->Value);
        }
        else
        {
            printf("NULL");
        }
        printf(", Current: %i, Next: ", Start->Value);
        if (Start->Next != NULL)
        {
            printf("%i", Start->Next->Value);
        }
        else
        {
            printf("NULL");
        }
        printf("\n");
        Start = Start->Next;
    }

    return 0;
}

void InsertEntry(struct Entry *InsertPosition, struct Entry *EntryToInsert)
{
    EntryToInsert->Previous = InsertPosition->Previous;
    EntryToInsert->Next = InsertPosition;
    if (InsertPosition->Previous != NULL)
    {
        InsertPosition->Previous->Next = EntryToInsert;
    }
    InsertPosition->Previous = EntryToInsert;

}

void RemoveEntry(struct Entry *EntryToRemove)
{
    if (EntryToRemove->Previous != NULL)
    {
        EntryToRemove->Previous->Next = EntryToRemove->Next;
    }
    if (EntryToRemove->Next != NULL)
    {
        EntryToRemove->Next->Previous = EntryToRemove->Previous;
    }
    EntryToRemove->Previous = NULL;
    EntryToRemove->Next = NULL;
}

Gracias por su tiempo.

-1
gloopit 28 jul. 2016 a las 01:05

2 respuestas

La mejor respuesta

El código es diferente porque su código no implementa con éxito una lista de doble enlace. Por ejemplo, intente insertar una entrada en el medio de la lista y luego imprímala desde el final hasta el principio, encontrará que el código vinculado funciona, pero el suyo no.

2
Fantastic Mr Fox 27 jul. 2016 a las 22:30

Tenga en cuenta que mi código hace exactamente lo que estaba tratando de hacer, mi salida impresa es: ....

Esto es lo más peligroso e ingenuo que dicen los nuevos programadores. No nos dice absolutamente nada. Programar no es una cuestión de que los fines justifiquen los medios. Puede presionar los botones equivocados en una calculadora y obtener la respuesta correcta, ¿no?

Su prueba consiste en recorrer en una sola dirección su lista. Una lista enlazada individualmente habría pasado esa prueba.

¿Probó el recorrido inverso? Después de todo, esa es la diferencia clave entre una lista con enlaces simples y una con enlaces dobles.
¿Probó la inserción y extracción desde el medio y desde el frente y la espalda?

¿Qué hay de los ciclos? ¿Qué sucede si agrega un elemento a la lista que ya está en la lista?

2
UpAndAdam 27 jul. 2016 a las 22:30