11 - Ejemplo práctico: inventario ordenado

En este ejemplo aplicamos un árbol binario de búsqueda para registrar productos en un depósito. Cada nodo guarda un código y la cantidad disponible. El árbol facilita insertar nuevas referencias, consultar existencias y generar reportes ordenados sin recorrer el inventario de forma lineal.

11.1 Enunciado

Una tienda recibe los siguientes productos (código, cantidad):

  • 1050 → 12 unidades
  • 900 → 6 unidades
  • 1400 → 5 unidades
  • 850 → 20 unidades
  • 1100 → 8 unidades
  • 1600 → 3 unidades

Se desea:

  1. Insertar cada producto manteniendo orden por código.
  2. Consultar el stock de un código dado.
  3. Listar el inventario de menor a mayor código.

11.2 Modelo de nodo

Cada nodo almacena el código, la cantidad y las referencias a sus hijos. Reutilizamos el esquema de clases visto en temas anteriores.

class Producto:
    def __init__(self, codigo, stock):
        self.codigo = codigo
        self.stock = stock
        self.izquierdo = None
        self.derecho = None

11.3 Inserción y actualización

Si el producto existe, se suma al stock actual. De lo contrario, se crea un nuevo nodo.

class ArbolInventario:
    def __init__(self):
        self.raiz = None

    def crear_producto(self, codigo, stock):
        return Producto(codigo, stock)

    def insertar(self, nodo, codigo, stock):
        if nodo is None:
            return self.crear_producto(codigo, stock)

        if codigo == nodo.codigo:
            nodo.stock += stock
        elif codigo < nodo.codigo:
            nodo.izquierdo = self.insertar(nodo.izquierdo, codigo, stock)
        else:
            nodo.derecho = self.insertar(nodo.derecho, codigo, stock)
        return nodo

    def insertar_producto(self, codigo, stock):
        self.raiz = self.insertar(self.raiz, codigo, stock)
        return self.raiz

11.4 Consulta de stock

La búsqueda se apoya en la propiedad de orden del árbol.

class ArbolInventario:
    # ...
    def buscar(self, nodo, codigo):
        if nodo is None:
            return None
        if codigo == nodo.codigo:
            return nodo
        if codigo < nodo.codigo:
            return self.buscar(nodo.izquierdo, codigo)
        return self.buscar(nodo.derecho, codigo)

11.5 Reporte ordenado

Un recorrido inorden lista los productos de menor a mayor código e incluye las existencias.

class ArbolInventario:
    # ...
    def imprimir_inorden(self, nodo):
        if nodo is None:
            return
        self.imprimir_inorden(nodo.izquierdo)
        print(f"Codigo {nodo.codigo}: {nodo.stock} unidades")
        self.imprimir_inorden(nodo.derecho)

11.6 Verificación

  • Inserta dos veces el mismo código y comprueba que el stock se acumula.
  • Consulta un código inexistente y verifica que se retorne NULL.
  • Imprime el inventario y confirma el orden ascendente.

11.7 Código completo en Python 3

Este archivo contiene todo el flujo: inserción, consulta y reporte final.

class Producto:
    def __init__(self, codigo, stock):
        self.codigo = codigo
        self.stock = stock
        self.izquierdo = None
        self.derecho = None


class ArbolInventario:
    def __init__(self):
        self.raiz = None

    def crear_producto(self, codigo, stock):
        return Producto(codigo, stock)

    def insertar(self, nodo, codigo, stock):
        if nodo is None:
            return self.crear_producto(codigo, stock)
        if codigo == nodo.codigo:
            nodo.stock += stock
        elif codigo < nodo.codigo:
            nodo.izquierdo = self.insertar(nodo.izquierdo, codigo, stock)
        else:
            nodo.derecho = self.insertar(nodo.derecho, codigo, stock)
        return nodo

    def insertar_producto(self, codigo, stock):
        self.raiz = self.insertar(self.raiz, codigo, stock)
        return self.raiz

    def buscar(self, nodo, codigo):
        if nodo is None:
            return None
        if codigo == nodo.codigo:
            return nodo
        if codigo < nodo.codigo:
            return self.buscar(nodo.izquierdo, codigo)
        return self.buscar(nodo.derecho, codigo)

    def imprimir_inorden(self, nodo):
        if nodo is None:
            return
        self.imprimir_inorden(nodo.izquierdo)
        print(f"Codigo {nodo.codigo}: {nodo.stock} unidades")
        self.imprimir_inorden(nodo.derecho)


if __name__ == "__main__":
    inventario = ArbolInventario()
    inventario.insertar_producto(1050, 12)
    inventario.insertar_producto(900, 6)
    inventario.insertar_producto(1400, 5)
    inventario.insertar_producto(850, 20)
    inventario.insertar_producto(1100, 8)
    inventario.insertar_producto(1600, 3)
    inventario.insertar_producto(900, 4)  # reingreso

    print("Inventario ordenado:")
    inventario.imprimir_inorden(inventario.raiz)

    codigo_consulta = 1100
    encontrado = inventario.buscar(inventario.raiz, codigo_consulta)
    if encontrado:
        print(f"\nStock del producto {codigo_consulta}: {encontrado.stock} unidades")
    else:
        print(f"\nEl producto {codigo_consulta} no existe")