<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">import java.util.Iterator;

/**
 * &lt;p&gt;Clase para Ã¡rboles binarios ordenados. Los Ã¡rboles son genÃ©ricos, pero
 * acotados a la interfaz {@link Comparable}.&lt;/p&gt;
 *
 * &lt;p&gt;Un Ã¡rbol instancia de esta clase siempre cumple que:&lt;/p&gt;
 * &lt;ul&gt;
 *   &lt;li&gt;Cualquier elemento en el Ã¡rbol es mayor o igual que todos sus
 *       descendientes por la izquierda.&lt;/li&gt;
 *   &lt;li&gt;Cualquier elemento en el Ã¡rbol es menor o igual que todos sus
 *       descendientes por la derecha.&lt;/li&gt;
 * &lt;/ul&gt;
 */
public class ArbolBinarioOrdenado&lt;T extends Comparable&lt;T&gt;&gt;
   extends ArbolBinario&lt;T&gt; {

   /* Clase privada para iteradores de Ã¡rboles binarios ordenados. */
   private class Iterador implements Iterator&lt;T&gt; {

      /* Pila para emular la pila de ejecuciÃ³n. */
      private Pila&lt;ArbolBinario&lt;T&gt;.Vertice&gt; pila;

      /* Construye un iterador con el vÃ©rtice recibido. */
      public Iterador(ArbolBinario&lt;T&gt;.Vertice vertice) {
         pila = new Pila&lt;ArbolBinario&lt;T&gt;.Vertice&gt;();
         meteIzq(vertice);
      }

      /*Metodo auxiliar para Iterador*/
      private void meteIzq(ArbolBinario&lt;T&gt;.Vertice vertice) {
         if(vertice == null)
            return;
         pila.mete(vertice);
         meteIzq(vertice.izquierdo);
      }

      /* Nos dice si hay un siguiente elemento. */
      @Override public boolean hasNext() {
         return pila.esVacia() != true;
      }

      /* Regresa el siguiente elemento del Ã¡rbol en orden. */
      @Override public T next() {
         if(hasNext()) {
            ArbolBinario&lt;T&gt;.Vertice vertice = pila.saca();
            meteIzq(vertice.derecho);
            return vertice.elemento;
         } else
            return null;
      }

      /* No lo implementamos: siempre lanza una excepciÃ³n. */
      @Override public void remove() {
         throw new UnsupportedOperationException();
      }
   }

   /**
    * Constructor sin parÃ¡metros. Sencillamente ejecuta el constructor sin
    * parÃ¡metros de {@link ArbolBinario}.
    */
   public ArbolBinarioOrdenado() {
      super();
   }

   /**
    * Construye un Ã¡rbol binario ordenado a partir de un Ã¡rbol binario. El
    * Ã¡rbol binario ordenado tiene los mismos elementos que el Ã¡rbol recibido,
    * pero ordenados.
    * @param arbol el Ã¡rbol binario a partir del cuÃ¡l creamos el
    *        Ã¡rbol binario ordenado.
    */
   public ArbolBinarioOrdenado(ArbolBinario&lt;T&gt; arbol) {
      Vertice raiz = arbol.vertice(arbol.raiz());
      ordenaVertices(raiz);
   }

   private void ordenaVertices(Vertice vertice) {
      if(vertice == null)
         return;
      ordenaVertices(vertice.izquierdo);
      agrega(vertice.elemento);
      ordenaVertices(vertice.derecho);
   }

   /**
    * Agrega un nuevo elemento al Ã¡rbol. El Ã¡rbol conserva su orden in-order.
    * @param elemento el elemento a agregar.
    */
   @Override public void agrega(T elemento) {
      elementos++;
      if(raiz == null) {
         raiz = nuevoVertice(elemento);
         ultimoAgregado = raiz;
      } else
         agrega(raiz, elemento);
   }

   /*Metodo auxiliar para agrega*/
   private void agrega(Vertice vertice, T elemento) {
      if(vertice == null)
         return;
      if(vertice.elemento.compareTo(elemento) &lt; 0) {
         /*Si el elemento que queremos agregar es mayor entonces nos vamos a su derecha*/
         if(!vertice.hayDerecho()) {
            vertice.derecho = nuevoVertice(elemento);
            vertice.derecho.padre = vertice;
            ultimoAgregado = vertice.derecho;
         } else
            agrega(vertice.derecho, elemento);
      } else {
         if(!vertice.hayIzquierdo()) {
            vertice.izquierdo = nuevoVertice(elemento);
            vertice.izquierdo.padre = vertice;
            ultimoAgregado = vertice.izquierdo;
         } else
            agrega(vertice.izquierdo, elemento);
      }
   }

   /**
    * Elimina un elemento. Si el elemento no estÃ¡ en el Ã¡rbol, no hace nada; si
    * estÃ¡ varias veces, elimina el primero que encuentre (in-order). El Ã¡rbol
    * conserva su orden in-order.
    * @param elemento el elemento a eliminar.
    */
   @Override public void elimina(T elemento) {
      Vertice v = vertice(busca(elemento));
      if(v != null) {
         elimina(v);
         elementos--;
      }
      return;
   }

   /*Metodo auxiliar para elimina*/
   private void elimina(Vertice vertice) {
      Vertice v1 = buscaAnterior(vertice);
      if(v1 == null) {
         if(vertice.padre == null) {
            raiz = vertice.derecho;
            if(vertice.derecho != null)
               vertice.derecho.padre = null;
            return;
         }
         if(vertice.padre.izquierdo == vertice)
            vertice.padre.izquierdo = vertice.derecho;
         else
            vertice.padre.derecho = vertice.derecho;
         if(vertice.derecho != null)
            vertice.derecho.padre = vertice.padre;
         return;
      }
      vertice.elemento = v1.elemento;
      if(v1.padre.izquierdo == v1)
         v1.padre.izquierdo = v1.izquierdo;
      else
         v1.padre.derecho = v1.izquierdo;
      if(v1.izquierdo != null)
         v1.izquierdo.padre = v1.padre;
   }

   /*Metodo auxiliar para elemina que recibe un Vertice*/
   private Vertice buscaAnterior(Vertice vertice) {
      if(vertice.izquierdo == null)
         return null;
      return veDerecha(vertice.izquierdo);
   }

   /*Metodo auxiliar para buscaAnterior*/
   private Vertice veDerecha(Vertice vertice) {
      if(vertice.derecho == null)
         return vertice;
      return veDerecha(vertice.derecho);
   }

   /**
    * Nos dice si un elemento estÃ¡ contenido en el Ã¡rbol.
    * @param elemento el elemento que queremos ver si estÃ¡ en el Ã¡rbol.
    * @return &lt;code&gt;true&lt;/code&gt; si el elemento estÃ¡ contenido en el Ã¡rbol,
    *         &lt;code&gt;false&lt;/code&gt; en otro caso.
    */
   @Override public boolean contiene(T elemento) {
      VerticeArbolBinario&lt;T&gt; v = busca(elemento);
      Vertice vertice = vertice(v);
      if(vertice == null)
         return false;
      return true;
   }

   /**
    * Busca un elemento en el Ã¡rbol recorriÃ©ndolo in-order. Si lo encuentra,
    * regresa el vÃ©rtice que lo contiene; si no, regresa &lt;tt&gt;null&lt;/tt&gt;.
    * @param elemento el elemento a buscar.
    * @return un vÃ©rtice que contiene al elemento buscado si lo
    *         encuentra; &lt;tt&gt;null&lt;/tt&gt; en otro caso.
    */
   @Override public VerticeArbolBinario&lt;T&gt; busca(T elemento) {
      return busca(raiz, elemento);
   }

   /**
    * Busca recursivamente un elemento, a partir del vÃ©rtice recibido.
    * @param vertice el vÃ©rtice a partir del cuÃ¡l comenzar la bÃºsqueda. Puede
    *                ser &lt;code&gt;null&lt;/code&gt;.
    * @param elemento el elemento a buscar a partir del vÃ©rtice.
    * @return el vÃ©rtice que contiene el elemento a buscar, si se encuentra en
    *         el Ã¡rbol; &lt;code&gt;null&lt;/code&gt; en otro caso.
    */
   @Override protected Vertice busca(Vertice vertice, T elemento) {
      if(vertice == null)
         return null;
      else if(vertice.elemento.compareTo(elemento) &gt; 0)
         return busca(vertice.izquierdo, elemento);
      if(vertice.elemento.compareTo(elemento) &lt; 0)
         return busca(vertice.derecho, elemento);
      else
         return vertice;
   }

   /**
    * Regresa el vÃ©rtice mÃ¡ximo en el subÃ¡rbol cuya raÃ­z es el vÃ©rtice que
    * recibe.
    * @param vertice el vÃ©rtice raÃ­z del subÃ¡rbol del que queremos encontrar el
    *                mÃ¡ximo.
    * @return el vÃ©rtice mÃ¡ximo el subÃ¡rbol cuya raÃ­z es el vÃ©rtice que recibe.
    */
   protected Vertice maximoEnSubarbol(Vertice vertice) {
      if(vertice == null)
         return null;
      if(vertice.derecho == null)
         return vertice;
      else
         return maximoEnSubarbol(vertice.derecho);
   }

   /**
    * Regresa un iterador para iterar el Ã¡rbol. El Ã¡rbol se itera en orden.
    * @return un iterador para iterar el Ã¡rbol.
    */
   @Override public Iterator&lt;T&gt; iterator() {
      return new Iterador(raiz);
   }

   /**
    * Gira el Ã¡rbol a la derecha sobre el vÃ©rtice recibido. Si el vÃ©rtice no
    * tiene hijo izquierdo, el mÃ©todo no hace nada.
    * @param vertice el vÃ©rtice sobre el que vamos a girar.
    */
   public void giraDerecha(VerticeArbolBinario&lt;T&gt; vertice) {
      Vertice v = vertice(vertice);
      giraDerecha(v);
   }

   /* Gira el Ã¡rbol a la derecha sobre el vÃ©rtice recibido. */
   private void giraDerecha(Vertice vertice) {
      if(vertice.izquierdo == null)
         return;
      Vertice ls = vertice.izquierdo;
      if(vertice.padre != null)
         if(vertice.padre.derecho == vertice)
            vertice.padre.derecho = ls;
         else vertice.padre.izquierdo = ls;
      else raiz = ls;
      ls.padre = vertice.padre;

      vertice.izquierdo = ls.derecho;
      if(vertice.izquierdo != null)
         vertice.izquierdo.padre = vertice;
      ls.derecho = vertice;
      ls.derecho.padre = ls;
   }

   /**
    * Gira el Ã¡rbol a la izquierda sobre el vÃ©rtice recibido. Si el vÃ©rtice no
    * tiene hijo derecho, el mÃ©todo no hace nada.
    * @param vertice el vÃ©rtice sobre el que vamos a girar.
    */
   public void giraIzquierda(VerticeArbolBinario&lt;T&gt; vertice) {
      Vertice v = vertice(vertice);
      giraIzquierda(v);
   }

   /* Gira el Ã¡rbol a la izquierda sobre el vÃ©rtice recibido. */
   private void giraIzquierda(Vertice vertice) {
      if(vertice.derecho == null)
         return;
      Vertice rs = vertice.derecho;
      rs.padre = vertice.padre;
      if(vertice.padre != null)
         if(vertice.padre.derecho == vertice)
            vertice.padre.derecho = rs;
         else
            vertice.padre.izquierdo = rs;
      else
         raiz = rs;
      vertice.derecho = rs.izquierdo;
      if(vertice.derecho != null)
         vertice.derecho.padre = vertice;
      rs.izquierdo = vertice;
      vertice.padre = rs;
   }
}
</pre></body></html>