Sublista

Descripcion del TAD

Estructura jerarquica secuencial: cada nodo padre mantiene su propia sublista de hijos. En la animacion observa dos niveles de punteros (padres e hijos) y valida que cada operacion afecte solo la rama correspondiente sin corromper otras sublistas. La Sublista agrega un segundo nivel de enlaces: nodos padre y sus hijos. El foco didactico esta en aislar cambios por rama sin corromper otras relaciones.

Objetivo

Modificar una rama sin afectar a las demás.

Estrategia

Localizar primero el padre y luego recorrer sus hijos.

Invariante

Cada hijo pertenece a un único padre.

Memoria dinámica

La liberación de una rama no autoriza liberar ramas vecinas.

Errores frecuentes

Glosario contextual
Nodo
Objeto dinámico con datos y uno o más enlaces.
Enlace
Campo puntero que conecta objetos.
Alias
Dos punteros que designan el mismo objeto.
LIFO
El último en entrar es el primero en salir.
FIFO
El primero en entrar es el primero en salir.
Prioridad
Criterio de selección independiente del orden físico.
Circularidad
El último enlace vuelve al inicio.
malloc
Reserva memoria; puede devolver NULL.
free
Libera una reserva que deja de ser válida.

Controles de ejecucion paso a paso

Operaciones soportadas

Operaciones pendientes / restricciones

Estructura del TAD en C

typedef struct Sublista {
    int nro;                
    struct Sublista *sgte;  
} Sublista;

typedef struct Nodo {
    int nro;              
    struct Nodo *sgte;    
    Sublista *sub;        
} Nodo;

Metodos del TAD en C

Codigo C: insertar_padre

Crea nodo padre en la lista principal de sublistas manteniendo su cadena independiente.

/**
 * @brief Inserta un nuevo nodo padre al final de la lista principal.
 * @param[in,out] lista       Doble puntero a la lista principal.
 * @param[in]     valor_padre Valor del nuevo padre.
 * @return Puntero al nuevo nodo insertado, o NULL si falla.
 */
Nodo *sublista_insertar_padre_final(Nodo **lista, int valor_padre) {
    Nodo *nuevo;
    Nodo *actual;

    if (lista == NULL) {
        return NULL;
    }

    nuevo = crear_padre(valor_padre);
    if (nuevo == NULL) {
        return NULL;
    }

    if (*lista == NULL) {
        *lista = nuevo;
        return nuevo;
    }

    actual = *lista;
    while (actual->sgte != NULL) {
        actual = actual->sgte;
    }
    actual->sgte = nuevo;
    return nuevo;
}

Codigo C: insertar_hijo

Localiza el padre objetivo y agrega el hijo en su sublista, sin afectar otros padres.

/**
 * @brief Inserta un nuevo nodo hijo al final de la sublista de un padre.
 * @param[in,out] padre      Puntero al nodo padre.
 * @param[in]     valor_hijo Valor del nuevo hijo.
 * @return true si se insertó exitosamente, false en caso de error.
 */
bool sublista_insertar_hijo_final(Nodo *padre, int valor_hijo) {
    Sublista *nuevo;
    Sublista *actual;

    if (padre == NULL) {
        return false;
    }

    nuevo = crear_hijo(valor_hijo);
    if (nuevo == NULL) {
        return false;
    }

    if (padre->sub == NULL) {
        padre->sub = nuevo;
        return true;
    }

    actual = padre->sub;
    while (actual->sgte != NULL) {
        actual = actual->sgte;
    }
    actual->sgte = nuevo;
    return true;
}

Codigo C: eliminar_padre

Elimina un padre y libera recursivamente/iterativamente su sublista de hijos asociada.

/**
 * @brief Elimina la primera ocurrencia de un nodo padre y todos sus hijos.
 * @param[in,out] lista       Doble puntero a la lista.
 * @param[in]     valor_padre Valor del padre a eliminar.
 * @return true si fue eliminado con éxito, false si no se encontró.
*/
bool sublista_eliminar_padre_primero(Nodo **lista, int valor_padre) {
    Nodo *actual;
    Nodo *anterior = NULL;

    if (lista == NULL || *lista == NULL) {
        return false;
    }

    actual = *lista;
    while (actual != NULL) {
        if (actual->nro == valor_padre) {
            if (anterior == NULL) {
                *lista = actual->sgte;
            } else {
                anterior->sgte = actual->sgte;
            }
            destruir_hijos(&actual->sub);
            free(actual);
            return true;
        }
        anterior = actual;
        actual = actual->sgte;
    }

    return false;
}

Codigo C: eliminar_hijo

Dentro del padre indicado, busca el hijo por valor y lo elimina ajustando enlaces locales.

/**
 * @brief Elimina la primera ocurrencia de un hijo en la sublista de un padre.
 * @param[in,out] padre      Puntero al nodo padre.
 * @param[in]     valor_hijo Valor del hijo a eliminar.
 * @return true si se eliminó correctamente, false si no se encontró.
 */
bool sublista_eliminar_hijo_primero(Nodo *padre, int valor_hijo) {
    Sublista *actual;
    Sublista *anterior = NULL;

    if (padre == NULL || padre->sub == NULL) {
        return false;
    }

    actual = padre->sub;
    while (actual != NULL) {
        if (actual->nro == valor_hijo) {
            if (anterior == NULL) {
                padre->sub = actual->sgte;
            } else {
                anterior->sgte = actual->sgte;
            }
            free(actual);
            return true;
        }
        anterior = actual;
        actual = actual->sgte;
    }

    return false;
}

Codigo C: hijos_de

Devuelve la coleccion de hijos del padre solicitado sin modificar la estructura.

/* Consulta de hijos en C: buscar padre y copiar su sublista a un arreglo. */
Nodo *padre = sublista_buscar_padre(lista, valor_padre);
if (padre != NULL) {
    int hijos[256];
    int usados = sublista_copiar_hijos(padre, hijos, 256);
    /* hijos[0..usados-1] contiene los valores de la sublista */
}

Codigo C: limpiar

Recorre la estructura liberando todos los nodos y deja el puntero raiz en estado nulo para reinicio seguro.

/**
 * @brief Libera completamente la memoria de todos los padres y sus respectivos hijos.
 * @param[in,out] lista Doble puntero a la lista principal.
 */
void sublista_destruir(Nodo **lista) {
    Nodo *actual;
    Nodo *next;

    if (lista == NULL) {
        return;
    }

    actual = *lista;
    while (actual != NULL) {
        next = actual->sgte;
        destruir_hijos(&actual->sub);
        free(actual);
        actual = next;
    }
    *lista = NULL;
}

/* Reinicio recomendado del TAD luego de liberar memoria */
/**
 * @brief Inicializa la lista principal de nodos padre estableciéndola en NULL.
 * @param[out] lista Doble puntero a la lista a inicializar.
 */
void sublista_inicializar(Nodo **lista) {
    if (lista == NULL) {
        return;
    }
    *lista = NULL;
}

Ir a la visualizacion