13 - Ejercicios prácticos sugeridos

Pon en práctica lo aprendido

Estos ejercicios amplían los temas anteriores y ayudan a consolidar la manipulación de listas enlazadas. Cada punto incluye una sugerencia de implementación en Python.

# ejercicios_lista.py

class Nodo:
    def __init__(self, valor):
        self.valor = valor
        self.sig = None


class Lista:
    def __init__(self):
        self.cabeza = None

    def contar(self):
        total = 0
        reco = self.cabeza
        while reco:
            total += 1
            reco = reco.sig
        return total

    def insertar_inicio(self, valor):
        nuevo = Nodo(valor)
        nuevo.sig = self.cabeza
        self.cabeza = nuevo

    def ordenar(self):
        if self.cabeza is None or self.cabeza.sig is None:
            return
        ordenada = None
        while self.cabeza:
            curr = self.cabeza
            self.cabeza = curr.sig
            if ordenada is None or curr.valor < ordenada.valor:
                curr.sig = ordenada
                ordenada = curr
            else:
                reco = ordenada
                while reco.sig and reco.sig.valor < curr.valor:
                    reco = reco.sig
                curr.sig = reco.sig
                reco.sig = curr
        self.cabeza = ordenada

    def eliminar_duplicados(self):
        curr = self.cabeza
        while curr:
            prev = curr
            reco = curr.sig
            while reco:
                if reco.valor == curr.valor:
                    prev.sig = reco.sig
                    reco.sig = None
                    reco = prev.sig
                else:
                    prev = reco
                    reco = reco.sig
            curr = curr.sig

    def invertir(self):
        prev = None
        curr = self.cabeza
        while curr:
            sig = curr.sig
            curr.sig = prev
            prev = curr
            curr = sig
        self.cabeza = prev

    def fusionar(self, otra):
        dummy = Nodo(0)
        cola = dummy
        recoA, recoB = self.cabeza, otra.cabeza
        while recoA or recoB:
            if recoB is None or (recoA and recoA.valor < recoB.valor):
                cola.sig = recoA
                recoA = recoA.sig
            else:
                cola.sig = recoB
                recoB = recoB.sig
            cola = cola.sig
        fusionada = Lista()
        fusionada.cabeza = dummy.sig
        return fusionada

    def tiene_ciclo(self):
        lento = self.cabeza
        rapido = self.cabeza
        while rapido and rapido.sig:
            lento = lento.sig
            rapido = rapido.sig.sig
            if lento == rapido:
                return True
        return False

    def imprimir(self):
        reco = self.cabeza
        while reco:
            print(reco.valor, end=" -> ")
            reco = reco.sig
        print("None")


def main():
    lista = Lista()
    lista.insertar_inicio(1)
    lista.insertar_inicio(2)
    lista.insertar_inicio(1)
    lista.insertar_inicio(3)

    print("Lista original:")
    lista.imprimir()
    print("Total nodos:", lista.contar())

    lista.eliminar_duplicados()
    print("Sin duplicados:")
    lista.imprimir()

    lista.ordenar()
    print("Ordenada:")
    lista.imprimir()

    lista.invertir()
    print("Invertida:")
    lista.imprimir()

    otra = Lista()
    for v in (4, 6, 7):
        otra.insertar_inicio(v)
    otra.ordenar()

    fusionada = lista.fusionar(otra)
    print("Fusionada con [4,6,7]:")
    fusionada.imprimir()

    print("Tiene ciclo?:", fusionada.tiene_ciclo())


if __name__ == "__main__":
    main()

El script incluye contar nodos, invertir, ordenar por inserción, eliminar duplicados, fusionar listas ordenadas y detectar ciclos (Floyd), todo en un enfoque orientado a objetos con Lista y Nodo.