{"id":30530,"date":"2019-10-31T21:36:01","date_gmt":"2019-10-31T18:36:01","guid":{"rendered":"https:\/\/prohoster.info\/blog\/binary-tree-ili-kak-prigotovit-binarnoe-derevo-poiska\/"},"modified":"2019-10-31T21:36:01","modified_gmt":"2019-10-31T18:36:01","slug":"binary-tree-ili-kak-prigotovit-binarnoe-derevo-poiska","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/binary-tree-ili-kak-prigotovit-binarnoe-derevo-poiska","title":{"rendered":"Albero Binario o come preparare un albero binario di ricerca","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<h2>Preludio<\/h2>\n<p>\nQuesto articolo \u00e8 dedicato agli alberi binari di ricerca. Recentemente ho scritto un articolo su <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/438512\/\">la compressione dei dati mediante il metodo di Huffman.<\/a><\/noindex> In quel caso non prestavo molta attenzione agli alberi binari, poich\u00e9 i metodi di ricerca, inserimento e cancellazione non erano rilevanti. Ora ho deciso di scrivere un articolo proprio sugli alberi. Cominciamo. <\/p>\n<p>Un albero \u00e8 una struttura dati composta da nodi collegati da archi. Si pu\u00f2 dire che un albero \u00e8 un caso particolare di grafo. Ecco un esempio di albero: <\/p>\n<p><img decoding=\"async\" alt=\"Albero Binario o come preparare un albero binario di ricerca\" src=\"\/wp-content\/uploads\/2019\/03\/502ac27f1b93f926c68a68777f6bddd7.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nQuesto non \u00e8 un albero binario di ricerca! Tutto a casa!<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Terminologia<\/h2>\n<p><\/p>\n<h4>Radice<\/h4>\n<p>\n<i>La radice dell'albero<\/i> \u00e8 il nodo pi\u00f9 alto. Nell'esempio, \u00e8 il nodo A. In un albero, dalla radice a qualsiasi altro nodo pu\u00f2 esserci solo un percorso! In realt\u00e0, qualsiasi nodo pu\u00f2 essere considerato come la radice del relativo sott'albero.<\/p>\n<h4>Genitori\/Discendenti<\/h4>\n<p>\nTutti i nodi, tranne quello radice, hanno esattamente un arco che conduce verso un altro nodo. Il nodo situato sopra quello corrente \u00e8 chiamato <i>genitore<\/i> di questo nodo. Il nodo situato sotto quello corrente e collegato ad esso \u00e8 chiamato <i>discendente<\/i> di questo nodo. Prendiamo come esempio il nodo B, quindi il suo genitore sar\u00e0 il nodo A, mentre i suoi discendenti saranno i nodi D, E e F.<\/p>\n<h4>Foglia<\/h4>\n<p>\nUn nodo che non ha discendenti sar\u00e0 chiamato foglia dell'albero. Nell'esempio, le foglie saranno i nodi D, E, F, G, I, J, K.<\/p>\n<p>Questa \u00e8 la terminologia di base. Altri concetti verranno trattati successivamente. Dunque, un albero binario \u00e8 un albero in cui ogni nodo avr\u00e0 al massimo due discendenti. Come avrete gi\u00e0 indovinato, l'albero dell'esempio non sar\u00e0 binario, poich\u00e9 i nodi B e H hanno pi\u00f9 di due discendenti. Ecco un esempio di albero binario:<\/p>\n<p><img decoding=\"async\" alt=\"Albero Binario o come preparare un albero binario di ricerca\" src=\"\/wp-content\/uploads\/2019\/03\/2f587bd1c428d3850cb0163d6c2984a1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNei nodi dell'albero pu\u00f2 trovarsi qualsiasi informazione. Un albero binario di ricerca \u00e8 un albero binario che presenta le seguenti propriet\u00e0:<\/p>\n<ol>\n<li>Entrambi i sott'alberi \u2014 quello sinistro e quello destro \u2014 sono alberi binari di ricerca.<\/li>\n<li>Per tutti i nodi del sott'albero sinistro di un nodo X, i valori delle chiavi sono minori rispetto al valore della chiave del nodo X stesso.<\/li>\n<li>Per tutti i nodi del sott'albero destro di un nodo X, i valori delle chiavi sono maggiori o uguali rispetto al valore della chiave del nodo X stesso. <\/li>\n<\/ol>\n<p><i>Chiave<\/i> \u2014 una qualsiasi caratteristica del nodo (ad esempio, un numero). La chiave \u00e8 necessaria per poter trovare l'elemento dell'albero corrispondente a quella chiave. Ecco un esempio di albero binario di ricerca:<\/p>\n<p><img decoding=\"async\" alt=\"Albero Binario o come preparare un albero binario di ricerca\" src=\"\/wp-content\/uploads\/2019\/03\/a70ca7d2fdf289b5d1e14bdb4bc38b00.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h2>Rappresentazione dell'albero<\/h2>\n<p>\nMan mano che procediamo, fornir\u00f2 alcuni frammenti di codice (possibilmente incompleti) per migliorare la tua comprensione. Il codice completo sar\u00e0 alla fine dell'articolo. <\/p>\n<p>L'albero \u00e8 composto da nodi. La struttura di un nodo:<\/p>\n<pre><code class=\"java\">public class Node {\n    private T data;\n    private int key;\n    private Node leftChild;\n    private Node rightChild;\n\n    public Node(T data, int key) {\n        this.data = data;\n        this.key = key;\n    }\n    public Node getLeftChild() {\n        return leftChild;\n    }\n\n    public Node getRightChild() {\n        return rightChild;\n    }\n\/\/...altri metodi del nodo\n}\n<\/code><\/pre>\n<p>\nOgni nodo ha due discendenti (\u00e8 possibile che i discendenti leftChild e\/o rightChild contengano il valore null). Probabilmente hai capito che in questo caso il numero data rappresenta i dati memorizzati nel nodo; key rappresenta la chiave del nodo.<\/p>\n<p>Ora che abbiamo chiarito il nodo, parliamo delle problematiche attuali sugli alberi. Qui e oltre, con il termine \"albero\" intender\u00f2 il concetto di un albero binario di ricerca. La struttura di un albero binario:<\/p>\n<pre><code class=\"java\">public class BinaryTree {\n     private Node root;\n\n    \/\/metodi dell'albero\n}\n<\/code><\/pre>\n<p>Come campo di classe, avremo bisogno solo della radice dell'albero, poich\u00e9 partendo dalla radice, con i metodi getLeftChild() e getRightChild(), possiamo raggiungere qualsiasi nodo dell'albero.<\/p>\n<h2>Algoritmi nell'albero<\/h2>\n<p><\/p>\n<h3>Ricerca<\/h3>\n<p>\nSupponiamo di avere un albero costruito. Come trovare l'elemento con la chiave key? Bisogna muoversi successivamente dalla radice verso il basso nell'albero e confrontare il valore di key con la chiave del nodo corrente: se key \u00e8 minore della chiave del nodo corrente, passare al discendente sinistro del nodo; se \u00e8 maggiore, passare al destro; se le chiavi sono uguali, il nodo cercato \u00e8 trovato! Il codice corrispondente:<\/p>\n<pre><code class=\"java\">public Node find(int key) {\n    Node current = root;\n    while (current.getKey() != key) {\n        if (key &lt; current.getKey())\n            current = current.getLeftChild();\n        else\n            current = current.getRightChild();\n        if (current == null)\n            return null;\n    }\n    return current;\n}\n<\/code><\/pre>\n<p>\nSe current diventa uguale a null, significa che l'iterazione ha raggiunto la fine dell'albero (a livello concettuale, ti trovi in un luogo inesistente dell'albero \u2014 un discendente di una foglia).<\/p>\n<p>Consideriamo l'efficacia dell'algoritmo di ricerca su un albero bilanciato (un albero in cui i nodi sono distribuiti in modo pi\u00f9 o meno uniforme). In questo caso, l'efficacia della ricerca sar\u00e0 O(log(n)), con logaritmo in base 2. Nota: se in un albero bilanciato ci sono n elementi, significa che ci saranno log(n) livelli in base 2 dell'albero. E nella ricerca, in un singolo ciclo, scenderai di un livello.<\/p>\n<h3>Inserimento<\/h3>\n<p>\nSe hai colto il senso della ricerca, comprendere l'inserimento non ti coster\u00e0 sforzo. Devi semplicemente scendere fino al foglio dell'albero (secondo le regole di discesa descritte nella ricerca) e diventare suo discendente: sinistro o destro, a seconda della chiave. Implementazione:<\/p>\n<pre><code class=\"java\">   public void insert(T insertData, int key) {\n        Node current = root;\n        Node parent;\n        Node newNode = new Node(insertData, key);\n        if (root == null)\n            root = newNode;\n        else {\n            while (true) {\n                parent = current;\n                if (key &lt; current.getKey()) {\n                    current = current.getLeftChild();\n                    if (current == null) {\n                         parent.setLeftChild(newNode);\n                         return;\n                    }\n                }\n                else {\n                    current = current.getRightChild();\n                    if (current == null) {\n                        parent.setRightChild(newNode);\n                        return;\n                    }\n                }\n            }\n        }\n    }\n<\/code><\/pre>\n<p>\nIn questo caso, \u00e8 necessario, oltre al nodo corrente, memorizzare l'informazione sul genitore del nodo attuale. Quando current diventa uguale a null, la variabile parent conterr\u00e0 il foglio di cui abbiamo bisogno. <br \/>\nL'efficienza dell'inserimento sar\u00e0 ovviamente la stessa della ricerca: O(log(n)).<\/p>\n<h3>Elimina<\/h3>\n<p>\nLa cancellazione \u00e8 l'operazione pi\u00f9 complessa che si dovr\u00e0 effettuare sull'albero. \u00c8 chiaro che prima sar\u00e0 necessario trovare l'elemento che si intende eliminare. Ma cosa succede dopo? Se assegniamo semplicemente il suo riferimento a null, perderemo l'informazione sul sottoalbero di cui questo nodo \u00e8 la radice. I metodi di cancellazione dell'albero vengono suddivisi in tre casi.<\/p>\n<h4>Primo caso. Il nodo da eliminare non ha discendenti.<\/h4>\n<p>\nSe il nodo da eliminare non ha discendenti, significa che \u00e8 una foglia. Quindi, \u00e8 possibile semplicemente assegnare il valore null ai campi leftChild o rightChild del suo genitore. <\/p>\n<h4>Secondo caso. Il nodo da eliminare ha un discendente.<\/h4>\n<p>\nQuesto caso non \u00e8 molto complesso. Torniamo al nostro esempio. Supponiamo di dover eliminare l'elemento con chiave 14. Convenite che poich\u00e9 \u00e8 un discendente destro del nodo con chiave 10, qualsiasi suo discendente (in questo caso il destro) avr\u00e0 una chiave maggiore di 10, quindi \u00e8 facile \"ritagliarlo\" dall'albero e collegare direttamente il genitore al discendente del nodo da eliminare, cio\u00e8 collegare il nodo con chiave 10 al nodo 13. Sarebbe simile la situazione se dovessimo eliminare un nodo che \u00e8 un discendente sinistro del suo genitore. Rifletti su questo: \u00e8 un'analogia precisa. <\/p>\n<h4>Terzo caso. Il nodo ha due discendenti.<\/h4>\n<p>\nIl caso pi\u00f9 complesso. Analizziamolo con un nuovo esempio.<\/p>\n<p><img decoding=\"async\" alt=\"Albero Binario o come preparare un albero binario di ricerca\" src=\"\/wp-content\/uploads\/2019\/03\/0d600478e4a046ae6f7267be49b231bc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h4>Ricerca del successore<\/h4>\n<p>\n Supponiamo di dover rimuovere un nodo con la chiave 25. Chi mettiamo al suo posto? Qualcuno dei suoi seguaci (discendenti o discendenti dei discendenti) deve diventare <i>successore<\/i>(colui che occuper\u00e0 il posto del nodo rimosso). <\/p>\n<p>Come capire chi deve diventare successore? \u00c8 intuitivamente chiaro che si tratta di un nodo nell'albero, la cui chiave \u00e8 la successiva pi\u00f9 grande rispetto al nodo rimosso. L'algoritmo \u00e8 il seguente. Dobbiamo passare al suo discendente destro (sempre a destra, poich\u00e9 \u00e8 gi\u00e0 stato detto che la chiave del successore \u00e8 maggiore della chiave del nodo rimosso) e poi attraversare la catena dei discendenti sinistri di questo discendente destro. Nell'esempio dobbiamo passare al nodo con chiave 35 e poi scendere fino alla foglia lungo la catena dei suoi discendenti sinistri: in questo caso, questa catena \u00e8 composta solo dal nodo con chiave 30. In termini rigorosi, stiamo cercando il nodo pi\u00f9 piccolo all'interno dell'insieme dei nodi maggiori del nodo cercato.<\/p>\n<p><img decoding=\"async\" alt=\"Albero Binario o come preparare un albero binario di ricerca\" src=\"\/wp-content\/uploads\/2019\/03\/50c4e3e49111eec9e1fd13083ee9b9b0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCodice del metodo di ricerca del successore:<\/p>\n<pre><code class=\"java\">    public Node&lt;T&gt; getSuccessor(Node&lt;T&gt; deleteNode) {\n        Node&lt;T&gt; parentSuccessor = deleteNode; \/\/ genitore del successore\n        Node&lt;T&gt; successor = deleteNode; \/\/ successore\n        Node&lt;T&gt; current = successor.getRightChild(); \/\/ semplicemente un nodo \"in transito\"\n        while (current != null) {\n            parentSuccessor = successor;\n            successor = current;\n            current = current.getLeftChild();\n        }\n        \/\/ all'uscita dal ciclo abbiamo il successore e il genitore del successore\n        if (successor != deleteNode.getRightChild()) { \/\/ se il successore non coincide con il discendente destro del nodo rimosso\n            parentSuccessor.setLeftChild(successor.getRightChild()); \/\/ il suo genitore prende il discendente del successore, per non perderlo\n            successor.setRightChild(deleteNode.getRightChild()); \/\/ colleghiamo il successore al discendente destro del nodo rimosso\n        }\n        return successor;\n    }\n<\/code><\/pre>\n<p>\nCodice completo del metodo delete:<\/p>\n<pre><code class=\"java\">public boolean delete(int deleteKey) {\n        Node current = root;\n        Node parent = current;\n        boolean isLeftChild = false; \/\/ A seconda che il nodo da eliminare sia un figlio sinistro o destro del suo genitore, la variabile booleana isLeftChild assumer\u00e0 il valore true o false rispettivamente.\n        while (current.getKey() != deleteKey) {\n            parent = current;\n            if (deleteKey &lt; current.getKey()) {\n                current = current.getLeftChild();\n                isLeftChild = true;\n            } else {\n                isLeftChild = false;\n                current = current.getRightChild();\n            }\n            if (current == null)\n                return false;\n        }\n\n        if (current.getLeftChild() == null &amp;&amp; current.getRightChild() == null) { \/\/ primo caso\n            if (current == root)\n                current = null;\n            else if (isLeftChild)\n                parent.setLeftChild(null);\n            else\n                parent.setRightChild(null);\n        }\n        else if (current.getRightChild() == null) { \/\/ secondo caso\n            if (current == root)\n                root = current.getLeftChild();\n            else if (isLeftChild)\n                parent.setLeftChild(current.getLeftChild());\n            else\n                current.setRightChild(current.getLeftChild());\n        } else if (current.getLeftChild() == null) {\n            if (current == root)\n                root = current.getRightChild();\n            else if (isLeftChild)\n                parent.setLeftChild(current.getRightChild());\n            else\n                parent.setRightChild(current.getRightChild());\n        } \n        else { \/\/ terzo caso\n            Node successor = getSuccessor(current);\n            if (current == root)\n                root = successor;\n            else if (isLeftChild)\n                parent.setLeftChild(successor);\n            else\n                parent.setRightChild(successor);\n        }\n        return true;\n    }\n<\/code><\/pre>\n<p>\nLa complessit\u00e0 pu\u00f2 essere approssimata a O(log(n)).<\/p>\n<h3>Ricerca del massimo\/minimo nell'albero<\/h3>\n<p>\n\u00c8 evidente come trovare il valore minimo\/massimo nell'albero: bisogna seguire in sequenza la catena dei nodi sinistri\/destri dell'albero; quando si arriva alla foglia, essa sar\u00e0 l'elemento minimo\/massimo.<\/p>\n<pre><code class=\"java\">    public Node getMinimum(Node startPoint) {\n        Node current = startPoint;\n        Node parent = current;\n        while (current != null) {\n            parent = current;\n            current = current.getLeftChild();\n        }\n        return parent;\n    }\n\n    public Node getMaximum(Node startPoint) {\n        Node current = startPoint;\n        Node parent = current;\n        while (current != null) {\n            parent = current;\n            current = current.getRightChild();\n        }\n        return parent;\n    }\n<\/code><\/pre>\n<p>\nLa complessit\u00e0 \u00e8 O(log(n))<\/p>\n<h3>Traversal simmetrico<\/h3>\n<p>\nIl traversal implica la visita di ogni nodo dell'albero per eseguire un'azione su di esso.<\/p>\n<p>Algoritmo di traversal simmetrico ricorsivo:<\/p>\n<ol>\n<li>Eseguire un'azione sul figlio sinistro<\/li>\n<li>Eseguire un'azione su se stessi<\/li>\n<li>Eseguire un'azione sul figlio destro<\/li>\n<\/ol>\n<p>\nCodice:<\/p>\n<pre><code class=\"java\">    public void inOrder(Node current) {\n        if (current != null) {\n            inOrder(current.getLeftChild());\n            System.out.println(current.getData() + \" \");\/\/Qui pu\u00f2 esserci tutto quello che vuoi\n            inOrder(current.getRightChild());\n        }\n    }\n<\/code><\/pre>\n<p><\/p>\n<h2>Conclusione<\/h2>\n<p>\nFinalmente! Se non ho spiegato qualcosa o se ci sono commenti, aspetto i vostri feedback. Come promesso, fornisco il codice completo.<\/p>\n<p>Node.java:<\/p>\n<pre><code class=\"java\">public class Node {\n    private T data;\n    private int key;\n    private Node leftChild;\n    private Node rightChild;\n\n    public Node(T data, int key) {\n        this.data = data;\n        this.key = key;\n    }\n\n    public void setLeftChild(Node newNode) {\n        leftChild = newNode;\n    }\n\n    public void setRightChild(Node newNode) {\n        rightChild = newNode;\n    }\n\n    public Node getLeftChild() {\n        return leftChild;\n    }\n\n    public Node getRightChild() {\n        return rightChild;\n    }\n\n    public T getData() {\n        return data;\n    }\n\n    public int getKey() {\n        return key;\n    }\n}\n\n<\/code><\/pre>\n<p>\nBinaryTree.java:<\/p>\n<pre><code class=\"java\">classe pubblica BinaryTree&lt;T&gt; {\n    private Node&lt;T&gt; root;\n\n    public Node&lt;T&gt; find(int key) {\n        Node&lt;T&gt; current = root;\n        while (current.getKey() != key) {\n            if (key &lt; current.getKey())\n                current = current.getLeftChild();\n            else\n                current = current.getRightChild();\n            if (current == null)\n                return null;\n        }\n        return current;\n    }\n\n    public void insert(T insertData, int key) {\n        Node&lt;T&gt; current = root;\n        Node&lt;T&gt; parent;\n        Node&lt;T&gt; newNode = new Node&lt;&gt;(insertData, key);\n        if (root == null)\n            root = newNode;\n        else {\n            while (true) {\n                parent = current;\n                if (key &lt; current.getKey()) {\n                    current = current.getLeftChild();\n                    if (current == null) {\n                         parent.setLeftChild(newNode);\n                         return;\n                    }\n                }\n                else {\n                    current = current.getRightChild();\n                    if (current == null) {\n                        parent.setRightChild(newNode);\n                        return;\n                    }\n                }\n            }\n        }\n    }\n\n    public Node&lt;T&gt; getMinimum(Node&lt;T&gt; startPoint) {\n        Node&lt;T&gt; current = startPoint;\n        Node&lt;T&gt; parent = current;\n        while (current != null) {\n            parent = current;\n            current = current.getLeftChild();\n        }\n        return parent;\n    }\n\n    public Node&lt;T&gt; getMaximum(Node&lt;T&gt; startPoint) {\n        Node&lt;T&gt; current = startPoint;\n        Node&lt;T&gt; parent = current;\n        while (current != null) {\n            parent = current;\n            current = current.getRightChild();\n        }\n        return parent;\n    }\n\n    public Node&lt;T&gt; getSuccessor(Node&lt;T&gt; deleteNode) {\n        Node&lt;T&gt; parentSuccessor = deleteNode;\n        Node&lt;T&gt; successor = deleteNode;\n        Node&lt;T&gt; current = successor.getRightChild();\n        while (current != null) {\n            parentSuccessor = successor;\n            successor = current;\n            current = current.getLeftChild();\n        }\n\n        if (successor != deleteNode.getRightChild()) {\n            parentSuccessor.setLeftChild(successor.getRightChild());\n            successor.setRightChild(deleteNode.getRightChild());\n        }\n        return successor;\n    }\n\n    public boolean delete(int deleteKey) {\n        Node&lt;T&gt; current = root;\n        Node&lt;T&gt; parent = current;\n        boolean isLeftChild = false;\n        while (current.getKey() != deleteKey) {\n            parent = current;\n            if (deleteKey &lt; current.getKey()) {\n                current = current.getLeftChild();\n                isLeftChild = true;\n            } else {\n                isLeftChild = false;\n                current = current.getRightChild();\n            }\n            if (current == null)\n                return false;\n        }\n\n        if (current.getLeftChild() == null &amp;&amp; current.getRightChild() == null) {\n            if (current == root)\n                current = null;\n            else if (isLeftChild)\n                parent.setLeftChild(null);\n            else\n                parent.setRightChild(null);\n        }\n        else if (current.getRightChild() == null) {\n            if (current == root)\n                root = current.getLeftChild();\n            else if (isLeftChild)\n                parent.setLeftChild(current.getLeftChild());\n            else\n                current.setRightChild(current.getLeftChild());\n        } else if (current.getLeftChild() == null) {\n            if (current == root)\n                root = current.getRightChild();\n            else if (isLeftChild)\n                parent.setLeftChild(current.getRightChild());\n            else\n                parent.setRightChild(current.getRightChild());\n        } \n        else {\n            Node&lt;T&gt; successor = getSuccessor(current);\n            if (current == root)\n                root = successor;\n            else if (isLeftChild)\n                parent.setLeftChild(successor);\n            else\n                parent.setRightChild(successor);\n        }\n        return true;\n    }\n\n    public void inOrder(Node&lt;T&gt; current) {\n        if (current != null) {\n            inOrder(current.getLeftChild());\n            System.out.println(current.getData() + \" \");\n            inOrder(current.getRightChild());\n        }\n    }\n}\n<\/code><\/pre>\n<h2>P.S.<\/h2>\n<p><\/p>\n<h3>Degradazione a O(n)<\/h3>\n<p>\nMolti di voi potrebbero aver notato: e se facessimo in modo che l'albero diventasse sbilanciato? Ad esempio, inserendo nell'albero nodi con chiavi crescenti: 1,2,3,4,5,6\u2026 Allora l'albero assomiglier\u00e0 a una lista collegata. E s\u00ec, l'albero perder\u00e0 la sua struttura ad albero, e di conseguenza, anche l'efficienza nell'accesso ai dati. La complessit\u00e0 delle operazioni di ricerca, inserimento e cancellazione diventer\u00e0 simile a quella di una lista collegata: O(n). Qui si manifesta uno dei pi\u00f9 grandi difetti, a mio avviso, degli alberi binari.<\/p>\n<p class=\"for_users_only_msg\">Solo gli utenti registrati possono partecipare al sondaggio. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/auth\/login\/\">Accedi<\/a><\/noindex>, per favore.<\/p>\n<h2 class=\"default-block__polling-title\">Non sono su Habr da molto tempo e mi piacerebbe sapere quali argomenti vorreste vedere trattati di pi\u00f9 negli articoli?<\/h2>\n<ul class=\"content-list content-list_polling\">\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Strutture dati<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Algoritmi (DP, ricorsione, compressione dati, ecc.)<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Applicazione di strutture dati e algoritmi nella vita reale<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Programmazione di applicazioni Android in Java<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Programmazione di applicazioni web in Java<\/p>\n<\/li>\n<\/ul>\n<p>    Hanno votato 2 utenti. Si \u00e8 astenuto 1 utente.<br \/>\n<br \/>Fonte: habr.com<\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0435\u043b\u044e\u0434\u0438\u044f \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u043c \u0434\u0435\u0440\u0435\u0432\u044c\u044f\u043c \u043f\u043e\u0438\u0441\u043a\u0430. \u041d\u0435\u0434\u0430\u0432\u043d\u043e \u0434\u0435\u043b\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u044e \u043f\u0440\u043e \u0441\u0436\u0430\u0442\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u0425\u0430\u0444\u0444\u043c\u0430\u043d\u0430. \u0422\u0430\u043c \u044f \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043e\u0431\u0440\u0430\u0449\u0430\u043b \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0435 \u0434\u0435\u0440\u0435\u0432\u044c\u044f, \u0438\u0431\u043e \u043c\u0435\u0442\u043e\u0434\u044b \u043f\u043e\u0438\u0441\u043a\u0430, \u0432\u0441\u0442\u0430\u0432\u043a\u0438, \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043d\u0435 \u0431\u044b\u043b\u0438 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b. \u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0435\u0448\u0438\u043b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u0440\u043e \u0434\u0435\u0440\u0435\u0432\u044c\u044f. \u041f\u043e\u0436\u0430\u043b\u0443\u0439, \u043d\u0430\u0447\u043d\u0435\u043c. \u0414\u0435\u0440\u0435\u0432\u043e \u2014 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0430\u044f \u0438\u0437 \u0443\u0437\u043b\u043e\u0432, \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u043d\u044b\u0445 \u0440\u0435\u0431\u0440\u0430\u043c\u0438. \u041c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u0434\u0435\u0440\u0435\u0432\u043e \u2014 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":22528,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-30530","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0435\u043b\u044e\u0434\u0438\u044f \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u043c \u0434\u0435\u0440\u0435\u0432\u044c\u044f\u043c \u043f\u043e\u0438\u0441\u043a\u0430.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/binary-tree-ili-kak-prigotovit-binarnoe-derevo-poiska\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47Binary Tree \u0438\u043b\u0438 \u043a\u0430\u043a \u043f\u0440\u0438\u0433\u043e\u0442\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u043d\u0430\u0440\u043d\u043e\u0435 \u0434\u0435\u0440\u0435\u0432\u043e \u043f\u043e\u0438\u0441\u043a\u0430 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0435\u043b\u044e\u0434\u0438\u044f \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u043c \u0434\u0435\u0440\u0435\u0432\u044c\u044f\u043c \u043f\u043e\u0438\u0441\u043a\u0430.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/binary-tree-ili-kak-prigotovit-binarnoe-derevo-poiska\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:36:01+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:36:01+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Albero Binario o come preparare un albero binario di ricerca | ProHoster","description":"Preludio Questo articolo \u00e8 dedicato agli alberi binari di ricerca.","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/binary-tree-ili-kak-prigotovit-binarnoe-derevo-poiska","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47Binary Tree \u0438\u043b\u0438 \u043a\u0430\u043a \u043f\u0440\u0438\u0433\u043e\u0442\u043e\u0432\u0438\u0442\u044c \u0431\u0438\u043d\u0430\u0440\u043d\u043e\u0435 \u0434\u0435\u0440\u0435\u0432\u043e \u043f\u043e\u0438\u0441\u043a\u0430 | ProHoster","og:description":"\u041f\u0440\u0435\u043b\u044e\u0434\u0438\u044f \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u043c \u0434\u0435\u0440\u0435\u0432\u044c\u044f\u043c \u043f\u043e\u0438\u0441\u043a\u0430.","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/binary-tree-ili-kak-prigotovit-binarnoe-derevo-poiska","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:36:01+00:00","article:modified_time":"2019-10-31T18:36:01+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"30530","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 01:39:20","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 03:33:27","updated":"2026-01-21 01:39:20","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/30530","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=30530"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/30530\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/22528"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=30530"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=30530"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=30530"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}