Pro2324 Help

Tema 3 - Listas

Pásame El Código

Visita nuestra nueva página web con contenidos actualizados y mucho más.

Estos apuntes también están en: Pásame el Código

    TAD Lista

    Una lista es por definición un conjunto de cero o más elementos.

    Los elementos están ordenados de forma lineal, no por su contenido, sino simplemente por la posición que ocupan relativos unos a otros.

    NODO 3

    NODO 2

    NODO 1

    INFORMACIÓN

    SIGUIENTE

    INFORMACIÓN

    SIGUIENTE

    INFORMACIÓN

    SIGUIENTE

    LISTA

    NULL

    TAD Lista enlazada simple

    Por lo tanto, la lista está formada por nodos idénticos. Cada nodo está formado por dos elementos, la información del propio nodo y un puntero que apunta al siguiente. Además, el inicio de la lista está delimitado por un puntero Lista, y finaliza con el último nodo que apunta a NULL.

    Operaciones

    Siguiendo los pasos para la especificación de un TAD, definimos las operaciones del mismo clasificándolas en: constructoras, generadoras, modificadoras, observadoras y destructoras.

    Generadoras

    • Objetivo: Crear una lista vacía y la inicializa
      Salida: Una lista vacía
      Poscondición: La lista sin datos

      LISTA

      NULL

      // SPDX-FileCopyrightText: 2024 Eliana Reigada // // SPDX-License-Identifier: GPL-3.0-only void createEmptyList(tList *lista) { lista->indice = LNULL; }
    • Objetivo: Si la posición es nula, añade un elemento al final de la lista. En caso contrario, el elemento quedará insertado justo antes del que actualmente ocupa la posición indicada.
      Entrada:
      - Item: Contenido del elemento a insertar
      - Position: Posición de referencia para la inserción
      - List: Lista donde vamos a insertar
      Salida: List: Lista con el elemento Item insertado y verdadero si se ha podido insertar, falso en caso contrario
      Precondición: Position es una posición válida de la lista o es una posición nula
      Postcondición: Las posiciones de los elementos de la lista posteriores a la del elemento insertado pueden haber variado

      NODO 2

      NODO 1

      LISTA

      INFORMACIÓN

      SIGUIENTE

      INFORMACIÓN

      SIGUIENTE

      NULL

      NODO 2

      NUEVO NODO

      NODO 1

      LISTA

      INFORMACIÓN

      SIGUIENTE

      INFORMACIÓN

      SIGUIENTE

      INFORMACIÓN

      SIGUIENTE

      NULL

      // SPDX-FileCopyrightText: 2023 Fernando Álvarez // // SPDX-License-Identifier: GPL-3.0-only bool insertItem(tItemL item, tPosL pos, tList *lista) { tPosL posAux; if (!createNode(&posAux)) { return false; } else { posAux->data = item; posAux->next = LNULL; //por si acaso } if (isEmptyList(*lista)) { *lista = posAux; } else if (pos == LNULL) { last(*lista)->next = posAux; } else if (pos == *lista) { posAux->next = pos; *lista = posAux; } else { posAux->next = pos->next; pos->next = posAux; posAux->data = pos->data; pos->data = item; } return true; }

    Modificadores

    • Objetivo: Copia una lista en otra
      Entrada: List_1: Lista que vamos a copiar
      Salida: List_2: Copia de la lista original y verdadero si se ha podido copiar, falso en caso contrario
      Precondición: La lista origen está inicializada

      LISTA 1

      NODO1

      NODO2

      NULL

      LISTA 2

      X

      LISTA 1

      NODO 1

      NODO 2

      NULL

      LISTA 2

      NUEVO NODO

      copiar

      LISTA 1

      NODO 1

      NODO 2

      NULL

      LISTA 2

      NODO 1

      copiar

      LISTA 1

      NODO 1

      NODO 2

      NULL

      LISTA 2

      NODO 1

      NUEVO NODO

      LISTA 1

      NODO 1

      NODO 2

      NULL

      LISTA 2

      NODO 1

      NODO 2

      // SPDX-FileCopyrightText: 2024 Eliana Reigada // // SPDX-License-Identifier: GPL-3.0-only bool copyList(tlist listaDest, tList *listaOrig) { tPosl p, q, r; bool ret = true; createEmptyList(listaOrig); if (!isEmptyList(listaDest)) { p = listaDest; while ((p != LNULL) && createNode(&r)) { r->data = p->data; r->next = LNULL; if (p == listaDest) { *listaOrig = r; q = r; } else { q->next = r; q = r; } p = p->next; } if (p != LNULL) { deleteList(listaOrig); ret = false; } } return ret; }
    • Objetivo: Modifica el contenido de un elemento de la lista
      Entrada:
      - Item: Nuevo contenido a asignar al elemento en Position
      - Position: Posición del elemento que queremos modificar
      - List: Lista a modificar
      Salida: List: Lista con el contenido del elemento modificado
      Precondición: Position es una posición válida de la lista

      _

      NODO 2

      NODO A MODIFICAR

      NODO 1

      LISTA

      INFORMACIÓN

      SIGUIENTE

      INFORMACIÓN ANTIGUA

      SIGUIENTE

      INFORMACIÓN

      SIGUIENTE

      NUEVA INFORMACIÓN

      POSICIÓN A MODIFICAR

      NULL

      // SPDX-FileCopyrightText: 2024 Eliana Reigada // // SPDX-License-Identifier: GPL-3.0-only void updateItem(tItem item, tPosL pos, tList *lista) { pos->data = item; }

    Destructoras

    • Objetivo: Elimina de la lista un elemento con cierta posición
      Entrada: Position: Posición del elemento a eliminar List: Lista a modificar Salida: List: Lista sin el elemento correspondiente a Position
      Precondición: Position es una posición válida de la lista
      Postcondición: Las posiciones de los elementos de la lista posteriores a la de la posición eliminada pueden haber variado

      NODO 2

      NODO A ELIMINAR

      NODO 1

      LISTA

      INFORMACIÓN

      SIGUIENTE

      INFORMACIÓN

      SIGUIENTE

      INFORMACIÓN

      SIGUIENTE

      NULL

      NODO 2

      NODO 1

      LISTA

      INFORMACIÓN

      SIGUIENTE

      INFORMACIÓN

      SIGUIENTE

      NULL

      // SPDX-FileCopyrightText: 2024 Eliana Reigada // // SPDX-License-Identifier: GPL-3.0-only void deleteAtPosition(tPosL pos, tList *lista) { tPosl posAux; if (pos == *lista) *lista = (*lista)->next; else { for (posAux = *lista; posAux->next != pos; posAux = posAux->next); posAux->next = pos->next; } free(pos); }
    • Objetivo: Elimina todos los elementos de la lista
      Entrada: List: Lista a borrar
      Salida: Lista vacía

      NODO 3

      NODO 2

      NODO 1

      LISTA

      INFORMACIÓN

      SIGUIENTE

      INFORMACIÓN

      SIGUIENTE

      INFORMACIÓN

      SIGUIENTE

      NULL

      FREE ()

      NODO 2

      NODO 1

      LISTA

      INFORMACIÓN

      SIGUIENTE

      INFORMACIÓN

      SIGUIENTE

      ANTIGUA DIRECCIÓN DE NODO 3

      NULL

      FREE ()

      NODO 1

      LISTA

      INFORMACIÓN

      SIGUIENTE

      ANTIGUA DIRECCIÓN DE NODO 2

      NULL

      FREE ()

      LISTA

      NULL

      // SPDX-FileCopyrightText: 2024 Eliana Reigada // // SPDX-License-Identifier: GPL-3.0-only void deleteList(tList *lista) { tPosL posAux; while (*lista != LNULL) { while (posAux->next != NULL) posAux = posAux->next; free(posAux); } }

    Observadoras

    • Objetivo: Busca el primer elemento con cierto contenido en la lista
      Entrada:
      - Item: Contenido del elemento buscado
      - List: Lista donde realizar la búsqueda
      Salida: Position: Posición del elemento encontrado o nulo si no se encuentra

      NODO 3

      NODO 2

      NODO 1

      NO

      LISTA

      USUARIO 1

      SIGUIENTE

      USUARIO 2

      SIGUIENTE

      USUARIO 3

      SIGUIENTE

      NULL

      ¿ERES EL USUARIO3?

      NODO 3

      NODO 2

      NODO 1

      NO

      LISTA

      USUARIO 1

      SIGUIENTE

      USUARIO 2

      SIGUIENTE

      USUARIO 3

      SIGUIENTE

      NULL

      ¿ERES EL USUARIO3?

      NODO 3

      NODO 2

      NODO 1

      SI

      LISTA

      USUARIO 1

      SIGUIENTE

      USUARIO 2

      SIGUIENTE

      USUARIO 3

      SIGUIENTE

      NULL

      ¿ERES EL USUARIO3?

      // SPDX-FileCopyrightText: 2024 Eliana Reigada // // SPDX-License-Identifier: GPL-3.0-only tPosL findItem(tItem item, tList lista) { tPosL posAux; for (posAux = lista; (posAux != LNULL) && (posAux->data != item); posAux = posAux->next); return posAux; }
    • Objetivo: Determina si la lista está vacía
      Entrada: List: Lista a comprobar
      Salida: Verdadero si la lista está vacía, falso en caso contrario

      // SPDX-FileCopyrightText: 2024 Eliana Reigada // // SPDX-License-Identifier: GPL-3.0-only bool isEmptyList(tLIst lista) { return lista == LNULL; }
    • Objetivo: Recupera el contenido de un elemento de la lista
      Entrada: Position: Posición del elemento buscado
      List: Lista donde realizar la búsqueda
      Salida: Item: Contenido del elemento que está en Position
      Precondición: Position es una posición válida en la lista

      // SPDX-FileCopyrightText: 2024 Eliana Reigada // // SPDX-License-Identifier: GPL-3.0-only tItem getItem(tPosL pos, tList lista) { return pos->data; }
    • Objetivo: Devuelve la posición del primer elemento de la lista
      Entrada: List: Lista a manipular
      Salida: Position: Posición del primer elemento
      Precondición: La lista no está vacía

      // SPDX-FileCopyrightText: 2024 Eliana Reigada // // SPDX-License-Identifier: GPL-3.0-only tPosL first(tList lista) { return lista; }
    • Objetivo: Devuelve la posición del último elemento de la lista
      Entrada: List: Lista a manipular
      Salida: Position: Posición del último elemento
      Precondición: La lista no está vacía

      // SPDX-FileCopyrightText: 2024 Eliana Reigada // // SPDX-License-Identifier: GPL-3.0-only tPosL last(tList lista) { tPosL posAux; for (posAux = lista; posAux->next != LNULL; posAux->next); return posAux; }
    • Objetivo: Devuelve la posición del elemento anterior al actual
      Entrada: Position: Posición del elemento actual
      List: Lista a manipular
      Salida: Posición del elemento anterior o nulo si es el primero
      Precondición: Position es una posición válida de la lista

      // SPDX-FileCopyrightText: 2024 Eliana Reigada // // SPDX-License-Identifier: GPL-3.0-only tPosL previous(tPosL pos, tList L) { tPosL posAux; for (posAux = L; posAux->next != pos; posAux = posAux->next); return posAux; }
    • Objetivo: Devuelve la posición del elemento siguiente al actual
      Entrada:
      - Position: Posición del elemento actual
      - List: Lista a manipular
      Salida: Position: Posición del elemento siguiente o nulo si es el último
      Precondición: Position es una posición válida de la lista

      // SPDX-FileCopyrightText: 2024 Eliana Reigada // // SPDX-License-Identifier: GPL-3.0-only tPosL next(tPosL pos, tList lista) { return pos->next; }

    TAD Lista ordenada

    Los elementos están ordenados de forma lineal por su contenido.

    En caso de ordenación alfabética:

    NODO 3

    NODO 2

    NODO 1

    AAAA

    SIGUIENTE

    BBBB

    SIGUIENTE

    CCCC

    SIGUIENTE

    LISTA

    NULL

    TAD Lista ordenada enlazada simple

    Operación a cambiar

    Las operaciones del TAD lista ordenada es idéntico al TAD anterior, la única a modificar es la operación de inserción:

    • Objetivo: Inserta un elemento en la lista según el criterio de ordenación sobre el campo Item
      Entrada:
      - Item: Contenido del elemento a insertar
      - List: Lista donde vamos a insertar
      Salida: List: Lista con el elemento Item insertado en la posición correspondiente según su contenido y verdadero si se ha podido insertar, falso en caso contrario
      Precondición: La lista está inicializada
      Postcondición: Las posiciones de los elementos de la lista posteriores a la del elemento insertado pueden haber variado

      NODO 3

      NUEVO 2

      NODO 1

      NUEVO NODO

      CCC

      SIGUIENTE

      LISTA

      AAA

      SIGUIENTE

      BBB

      SIGUIENTE

      DDD

      SIGUIENTE

      NULL

      NUEVO NODO

      NODO 3

      NUEVO 2

      NODO 1

      LISTA

      AAA

      SIGUIENTE

      BBB

      SIGUIENTE

      DDD

      SIGUIENTE

      CCC

      SIGUIENTE

      NULL

      // SPDX-FileCopyrightText: 2023 Fernando Álvarez // // SPDX-License-Identifier: GPL-3.0-only bool insertItem(tItemL item, tList *lista) { tPosL q,p; if (!createNode(&q)) { return false; } else { q->data = item; q->next = LNULL; //por si acaso } if (isEmptyList(*lista)) { *lista = q; } else if(item < (*lista)->data){ q->next = *lista; *lista = q; } else{ p = findPosition(*lista,item); q->next = p->next; p->next = q; } return true; }

    Comparación entre TADs

    Estática

    Simple Enlace

    Doble Enlace

    Necesidad de memoria

    Mucha

    Menos en promedio

    Menos en promedio (+ que simple enlace)

    Memoria contigua

    Acceso directo

    Ampliable

    Operaciones más costosas

    insertItem, deleteAtPosition (excepto al final)

    insertItem (final), deleteAtPosition (final), previous, last, deleteList, copyList

    insertItem (final), last, deleteList, copyList

    Seguridad

    ⚔️😡🛡️

    😴🛡️

    😴🛡️

    Archivo de Cabecera TAD

    #include <stdbool.h> #define LNULL ...; //Constante que representa posiciones nulas // Se define en funcion del problema typedef ... tItemL; typedef ... tPosL; typedef ... tList; // Generadoras void createEmptyList(tList* L); bool insertItem(tItemL d, tPosL p, tList* L); // Modificadoras bool copyList(tList L, tList* M); void updateItem(tItemL d , tPosL p, tList* L); // Destructoras void deleteAtPosition(tPosL p, tList* L); void deleteList(tList* L); // Observadoras tPosL findItem(tItemL d, tList L); bool isEmptyList(tList L); tItemL getItem(tPosL p, tList L); tPosL first(tList L) ; tPosL last(tList L); tPosL previous(tPosL p, tList L); tPosL next(tPosL p, tList L);

    Multilistas

    En problemas de programación reales hacen falta soluciones complejas. Es habitual combinar múltiples TAD simples para construir un TAD complejo.

    En este caso el TAD multilistas es un ejemplo de combinación de TADs, en este caso, listas.

    TAD Multilistas

    La multilista consiste, en crear sublistas enlazadas a los nodos de una lista principal.

    A una lista de usuarios podríamos enlazar, por ejemplo, una playlist para cada uno.

    Multilista.png

    TAD Multiordenadas

    Esta lista multiordenada consta de dos punteros, uno apunta al primer nodo ordenada por nombre, y el otro al primer DNI.

    Los están enlazados entre ellos doblemente. Marcando el nodo anterior y siguiente, en dos categorías: Nombre y **DNI **.

    Multiordenada.png
    Last modified: 16 marzo 2025