Esta solución no es elegante porque hay que diferenciar el caso
en que el eslabón se agrega al lado izquierdo o al lado derecho.
void put(int llave, Object valObj) {
Nodo nodo= raiz;
while (nodo!=null) {
if (nodo.llave==llave) {
nodo.valObj= valObj;
return;
}
if (nodo.llave<llave)
if (nodo.izq!=null)
nodo= nodo.izq;
else {
nodo.izq= new Nodo(llave, valObj, null, null);
return;
}
else
if (nodo.izq!=null)
nodo= nodo.der;
else {
nodo.der= new Nodo(llave, valObj, null, null);
return;
}
}
}
La clave para simplificar la implementación está en hacer que el método recursivo retorne una referencia del árbol modificado. En forma pictórica los distintos casos de modificación se explican en la siguiente figura:

El código para implementar esta operación en Java es:
Como podemos apreciar, la versión es un poco más breve que la
versión iterativa. Sin embargo, ambas son igualmente eficientes.
void put(int llave, Object valObj) {
this.raiz= modificar(llave, valObj, raiz);
}
private Nodo modificar(int llave, Object valObj, Nodo nodo) {
if (nodo==null)
return new Nodo(llave, valObj, null, null);
if (llave==nodo.llave)
nodo.valObj= valObj;
else if (llave<nodo.llave)
nodo.izq= modificar(llave, valObj, nodo.izq);
else
nodo.der= modificar(llave, valObj, nodo.der);
return nodo;
}

Para implementar esta operación se agrega el método recursivo eliminar. Este método recibe un ABB como parámetro y lo transforma de modo que ya no contenga la llave especificada. El método retorna el ABB modificado:
El caso defícil se presenta cuando hay que eliminar un nodo, pero ese
nodo tiene subárboles izquierdo y derecho al mismo tiempo. En este
caso por lo tanto fabricamos un nuevo método que une dos ABBs (unir).
El trabajo realizado por este método queda representado en la siguiente
figura:
void remove(int llave) {
this.raiz= eliminar(llave, raiz);
}
private Nodo eliminar(int llave, Nodo nodo) {
if (nodo==null)
return null;
if (nodo.llave==llave)
return unir(nodo.izq, nodo.der);
if (llave<nodo.llave)
nodo.izq= eliminar(llave, nodo.izq);
else
nodo.der= eliminar(llave, nodo.der);
return nodo;
}

El código de unir es:
Análisis
private Nodo unir(Nodo izq, Nodo der) {
if (izq==null)
return der;
if (der==null)
return izq);
Nodo centro= unir(izq.der, der.izq);
izq.der= der;
der.izq= centro;
return izq;
}
Sea n el número de asociaciones que posee un arreglo asociativo. La siguiente tabla muestra el tiempo de ejecución en función de n para las operaciones típicas de un arreglo asociativo:
| Operación | Tiempo | Tiempo |
|---|---|---|
| caso peor | caso promedio | |
| get | O(n) | O(log(n)) |
| isMapped | O(n) | O(log(n)) |
| put | O(n) | O(log(n)) |
Como vemos, el caso promedio es muy eficiente en comparación con la implementación que usa listas enlazadas.
Map m= new Map();
println(m.size()); // 0
m.put(3, "hola");
m.put(5, "que");
m.put(-1, "tal");
println(m.size()); // 3
Formalmente, findKey debe cumplir con la siguiente propiedad:
Map m= new Map();
Object s= "hola";
m.put(10, s);
m.put(5, "que");
println(m.findKey(s)); // 10
Sea o un objeto cualquiera,
si m.findKey(o)==ll entonces m.get(ll)==o
Observe que pueden existir varias llaves que se asocian con el mismo
objeto o. En tal caso, m.findKey(o) entrega cualquiera de esas llaves.
Si no existe ninguna llave, findKey termina la ejecución con un
mensaje de error (invoca fatalError).Implemente el método findKey para un arreglo asociativo implementado mediante ABBs.
Observación: Ud. debe buscar el objeto en todo el árbol. En este caso, el orden en que se encuentran las llaves en el ABB no sirve de nada. Por lo tanto su implementación tomará tiempo O(n).
| Ejemplo | Significado | Declaración |
|---|---|---|
| StringMap m= new StringMap(); | Construye un arreglo asociativo con llaves de tipo string, inicialmente vacío | StringMap() |
| m.put("juan", "26 de Junio"); | Asocia el string "juan" string "26 de junio" | void put(String ll, Object v) |
| String s= (String)m.get("juan"); | entrega el objeto asociado a la llave "juan". Si la llave no posee valor asociado se produce un error. | Object get(String ll) |
Indicaciones: Suponga que el método recursivo que inserta la llave en la raíz del ABB se llama insertar. El caso simple es cuando la llave ya se encuentra en la raíz o el ABB está vacío. Analícelo. Cuando no se cumple ninguna de estas condiciones, sin pérdida de generalidad podemos suponer que la llave que se reasocia con un nuevo valor es menor que la llave almacenada en la raíz del ABB. La siguiente figura muestra cómo debe calcular el nuevo árbol en el caso en que la llave que se desea agregar es menor que la llave que se encuentra almacenada en la raíz del ABB (ll<ll'):

El resultado del método insertar será entonces el árbol A. Haga las figuras para los casos en que ll==ll' y ll>ll'. Finalmente programe los métodos put e insertar.