Ho imparato da un libro di testo come implementare gli alberi di ricerca binari in modo ricorsivo in Java e sto lavorando per implementarli in modo non ricorsivo. Ho trovato un modo semplice ed elegante per implementare un metodo di inserimento in C / C ++ attraversando l'albero usando un puntatore del tipo Nodo **, ma non riesco a trovare un modo elegante per farlo in Java.
Il mio codice C ++ è il seguente:
class BST {
class Node {
public:
int key;
int val;
Node *left = nullptr;
Node *right = nullptr;
Node(int k, int v) : key(k), val(v) {}
};
Node *root = nullptr;
public:
void insert(int key, int val);
};
void BST::insert(int k, int v) {
Node **link = &root;
while (*link != nullptr && (*link)->key != k) {
if (k < (*link)->key)
link = &(*link)->left;
else if (k > (*link)->key)
link = &(*link)->right;
}
if (*link == nullptr)
*link = new Node(k, v);
else
(*link)->val = v;
}
Quale penso esprima l'idea abbastanza direttamente. Il mio primo tentativo in Java è stato il seguente.
public class BST {
private class Node {
int key;
int val;
Node left = null;
Node right = null;
Node (int k, int v) {
key = k; val = v;
}
}
Node root = null;
void insert(int k, int v) {
if (root == null) {
root = new Node(k, v);
return;
}
Node node = root;
while (node.key != k) {
if (k < node.key) {
if (node.left == null) {
node.left = new Node(k, v);
return;
} else {
node = node.left;
}
} else {
if (node.right == null) {
node.right = new Node(k, v);
return;
} else {
node = node.right;
}
}
}
node.val = v;
}
}
Questo mi sembra molto meno chiaro: deve trattare separatamente molti casi diversi e il codice per la creazione di nuovi nodi si confonde con il codice per attraversare l'albero, mentre la versione C ++ attraversa due fasi chiare. Poi mi è venuto in mente che avrei potuto replicare la versione C ++ memorizzando i puntatori del Nodo negli oggetti di una classe Link:
public class BST {
private class Link {
Node node = null;
}
private class Node {
int key;
int val;
Link left = new Link();
Link right = new Link();
Node (int k, int v) {
key = k; val = v;
}
}
Link root = new Link();
void insert(int k, int v) {
Link link = root;
while (link.node != null && link.node.key != k) {
if (k < link.node.key)
link = link.node.left;
else if (k > link.node.key)
link = link.node.right;
}
if (link.node == null)
link.node = new Node(k, v);
else
link.node.val = v;
}
}
Ciò consente di esprimere elegantemente l'algoritmo, ma il sovraccarico dovuto all'aggiunta di un ulteriore livello di riferimento indiretto a ogni nodo della struttura dati sembra piuttosto un pesante prezzo da pagare. C'è un modo migliore per farlo?