{"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\/es\/blog\/administrirovanie\/binary-tree-ili-kak-prigotovit-binarnoe-derevo-poiska","title":{"rendered":"\u00c1rbol binario o c\u00f3mo construir un \u00e1rbol binario de b\u00fasqueda","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<h2>Preludio<\/h2>\n<p>\nEste art\u00edculo se dedica a los \u00e1rboles binarios de b\u00fasqueda. Recientemente escrib\u00ed un art\u00edculo sobre <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/438512\/\">la compresi\u00f3n de datos mediante el m\u00e9todo de Huffman.<\/a><\/noindex> En ese momento no prest\u00e9 mucha atenci\u00f3n a los \u00e1rboles binarios, ya que los m\u00e9todos de b\u00fasqueda, inserci\u00f3n y eliminaci\u00f3n no eran relevantes. Ahora decid\u00ed escribir un art\u00edculo espec\u00edficamente sobre los \u00e1rboles. Comencemos. <\/p>\n<p>Un \u00e1rbol es una estructura de datos compuesta por nodos conectados por aristas. Se puede decir que un \u00e1rbol es un caso particular de un grafo. Aqu\u00ed hay un ejemplo de un \u00e1rbol: <\/p>\n<p><img decoding=\"async\" alt=\"\u00c1rbol binario o c\u00f3mo construir un \u00e1rbol binario de b\u00fasqueda\" src=\"\/wp-content\/uploads\/2019\/03\/502ac27f1b93f926c68a68777f6bddd7.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n\u00a1Este no es un \u00e1rbol binario de b\u00fasqueda! \u00a1Todo lo dem\u00e1s debajo!<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Terminolog\u00eda<\/h2>\n<p><\/p>\n<h4>Ra\u00edz<\/h4>\n<p>\n<i>La ra\u00edz del \u00e1rbol<\/i> es su nodo m\u00e1s alto. En el ejemplo, este es el nodo A. Desde la ra\u00edz a cualquier otro nodo solo puede haber un camino. De hecho, cualquier nodo se puede considerar como la ra\u00edz de su respectivo sub\u00e1rbol.<\/p>\n<h4>Padres\/hijos<\/h4>\n<p>\nTodos los nodos, excepto la ra\u00edz, tienen exactamente una arista que sube hacia otro nodo. El nodo ubicado por encima del actual se llama <i>padre<\/i> de este nodo. El nodo que se encuentra debajo del actual y conectado a \u00e9l se llama <i>hijo<\/i> de este nodo. Vamos con un ejemplo. Tomemos el nodo B, entonces su padre ser\u00e1 el nodo A, y sus hijos ser\u00e1n los nodos D, E y F.<\/p>\n<h4>Hoja<\/h4>\n<p>\nUn nodo que no tiene hijos se llamar\u00e1 hoja del \u00e1rbol. En el ejemplo, las hojas son los nodos D, E, F, G, I, J, K.<\/p>\n<p>Esta es la terminolog\u00eda b\u00e1sica. Otros conceptos se explicar\u00e1n m\u00e1s adelante. Por lo tanto, un \u00e1rbol binario es un \u00e1rbol en el que cada nodo tendr\u00e1 no m\u00e1s de dos hijos. Como habr\u00e1n adivinado, el \u00e1rbol del ejemplo no ser\u00e1 binario, ya que los nodos B y H tienen m\u00e1s de dos hijos. Aqu\u00ed hay un ejemplo de un \u00e1rbol binario:<\/p>\n<p><img decoding=\"async\" alt=\"\u00c1rbol binario o c\u00f3mo construir un \u00e1rbol binario de b\u00fasqueda\" src=\"\/wp-content\/uploads\/2019\/03\/2f587bd1c428d3850cb0163d6c2984a1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLos nodos del \u00e1rbol pueden contener cualquier informaci\u00f3n. Un \u00e1rbol binario de b\u00fasqueda es un \u00e1rbol binario que presenta las siguientes propiedades:<\/p>\n<ol>\n<li>Ambos sub\u00e1rboles, el izquierdo y el derecho, son \u00e1rboles binarios de b\u00fasqueda.<\/li>\n<li>Todos los nodos del sub\u00e1rbol izquierdo de un nodo X tienen valores de clave de datos que son menores que el valor de la clave de datos del propio nodo X.<\/li>\n<li>Todos los nodos del sub\u00e1rbol derecho de un nodo X tienen valores de clave de datos que son mayores o iguales al valor de la clave de datos del propio nodo X. <\/li>\n<\/ol>\n<p><i>Clave<\/i> es alguna caracter\u00edstica del nodo (por ejemplo, un n\u00famero). La clave es necesaria para poder encontrar el elemento del \u00e1rbol correspondiente a esta clave. Ejemplo de \u00e1rbol binario de b\u00fasqueda:<\/p>\n<p><img decoding=\"async\" alt=\"\u00c1rbol binario o c\u00f3mo construir un \u00e1rbol binario de b\u00fasqueda\" src=\"\/wp-content\/uploads\/2019\/03\/a70ca7d2fdf289b5d1e14bdb4bc38b00.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h2>Introducci\u00f3n al \u00e1rbol<\/h2>\n<p>\nA medida que avance, proporcionar\u00e9 algunos (posiblemente incompletos) fragmentos de c\u00f3digo para mejorar su comprensi\u00f3n. El c\u00f3digo completo estar\u00e1 al final del art\u00edculo. <\/p>\n<p>Un \u00e1rbol consta de nodos. La estructura de un nodo:<\/p>\n<pre><code class=\"java\">public class Node&lt;T&gt; {\n    private T data;\n    private int key;\n    private Node&lt;T&gt; leftChild;\n    private Node&lt;T&gt; rightChild;\n\n    public Node(T data, int key) {\n        this.data = data;\n        this.key = key;\n    }\n    public Node&lt;T&gt; getLeftChild() {\n        return leftChild;\n    }\n\n    public Node&lt;T&gt; getRightChild() {\n        return rightChild;\n    }\n\/\/...otros m\u00e9todos del nodo\n}\n<\/code><\/pre>\n<p>\nCada nodo tiene dos hijos (posiblemente, los hijos leftChild y\/o rightChild pueden tener el valor nulo). Supongo que ya entendi\u00f3 que, en este caso, data es la informaci\u00f3n almacenada en el nodo; key es la clave del nodo.<\/p>\n<p>Hemos entendido el nodo, ahora hablemos de los problemas actuales relacionados con los \u00e1rboles. De aqu\u00ed en adelante, al t\u00e9rmino '\u00e1rbol' me referir\u00e9 al concepto de \u00e1rbol binario de b\u00fasqueda. La estructura de un \u00e1rbol binario:<\/p>\n<pre><code class=\"java\">public class BinaryTree&lt;T&gt; {\n     private Node&lt;T&gt; root;\n\n    \/\/m\u00e9todos del \u00e1rbol\n}\n<\/code><\/pre>\n<p>Como campo de clase, solo necesitaremos la ra\u00edz del \u00e1rbol, porque desde la ra\u00edz, mediante los m\u00e9todos getLeftChild() y getRightChild(), se puede llegar a cualquier nodo del \u00e1rbol.<\/p>\n<h2>Algoritmos en el \u00e1rbol<\/h2>\n<p><\/p>\n<h3>B\u00fasqueda<\/h3>\n<p>\nSupongamos que tiene un \u00e1rbol construido. \u00bfC\u00f3mo encontrar el elemento con la clave key? Debe moverse secuencialmente desde la ra\u00edz hacia abajo por el \u00e1rbol y comparar el valor key con la clave del nodo actual: si key es menor que la clave del nodo actual, debe pasar al hijo izquierdo del nodo; si es mayor, al derecho; si las claves son iguales, \u00a1el nodo buscado ha sido encontrado! El c\u00f3digo correspondiente es:<\/p>\n<pre><code class=\"java\">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<\/code><\/pre>\n<p>\nSi current se convierte en nulo, significa que se ha llegado al final del \u00e1rbol (en un nivel conceptual, se encuentra en un lugar inexistente del \u00e1rbol: el hijo de una hoja).<\/p>\n<p>Consideremos la eficiencia del algoritmo de b\u00fasqueda en un \u00e1rbol balanceado (un \u00e1rbol en el que los nodos est\u00e1n distribuidos m\u00e1s o menos uniformemente). Entonces, la eficiencia de la b\u00fasqueda ser\u00e1 O(log(n)), siendo el logaritmo de base 2. Observe: si hay n elementos en un \u00e1rbol balanceado, significa que habr\u00e1 log(n) niveles en el \u00e1rbol. Y en la b\u00fasqueda, en un paso del ciclo, usted baja un nivel.<\/p>\n<h3>Inserci\u00f3n<\/h3>\n<p>\nSi entendiste la esencia de la b\u00fasqueda, no te ser\u00e1 dif\u00edcil comprender la inserci\u00f3n. Solo necesitas bajar hasta el nodo hoja (seg\u00fan las reglas de descenso descritas en la b\u00fasqueda) y convertirte en su descendiente: izquierdo o derecho, dependiendo de la clave. Implementaci\u00f3n:<\/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>\nEn este caso, adem\u00e1s del nodo actual, debemos almacenar informaci\u00f3n sobre el padre del nodo actual. Cuando current se convierta en null, la variable parent tendr\u00e1 el nodo hoja que necesitamos. <br \/>\nLa eficiencia de la inserci\u00f3n, obviamente, ser\u00e1 la misma que la de la b\u00fasqueda: O(log(n)).<\/p>\n<h3>Eliminaci\u00f3n<\/h3>\n<p>\nLa eliminaci\u00f3n es la operaci\u00f3n m\u00e1s compleja que se debe realizar con el \u00e1rbol. Es evidente que primero debemos encontrar el elemento que vamos a eliminar. Pero, \u00bfqu\u00e9 hacemos despu\u00e9s? Si simplemente asignamos el valor null a su referencia, perderemos informaci\u00f3n sobre el sub\u00e1rbol cuyo ra\u00edz es este nodo. Los m\u00e9todos de eliminaci\u00f3n del \u00e1rbol se dividen en tres casos.<\/p>\n<h4>Primer caso. El nodo eliminado no tiene descendientes<\/h4>\n<p>\nSi el nodo eliminado no tiene descendientes, significa que es una hoja. Por lo tanto, se puede asignar el valor null a los campos leftChild o rightChild de su padre. <\/p>\n<h4>Segundo caso. El nodo eliminado tiene un descendiente<\/h4>\n<p>\nEste caso tampoco es muy complicado. Volvamos a nuestro ejemplo. Supongamos que necesitamos eliminar el elemento con la clave 14. Acepten que, como es el descendiente derecho del nodo con la clave 10, cualquier descendiente suyo (en este caso, derecho) tendr\u00e1 una clave mayor que 10, por lo que se puede \"cortar\" f\u00e1cilmente del \u00e1rbol y conectar directamente al padre con el descendiente del nodo eliminado, es decir, conectar el nodo con la clave 10 con el nodo 13. La situaci\u00f3n ser\u00eda similar si tuvi\u00e9semos que eliminar un nodo que es el descendiente izquierdo de su padre. Piensa en esto t\u00fa mismo: es una analog\u00eda precisa. <\/p>\n<h4>Tercer caso. El nodo tiene dos descendientes<\/h4>\n<p>\nEl caso m\u00e1s complicado. Analicemos un nuevo ejemplo.<\/p>\n<p><img decoding=\"async\" alt=\"\u00c1rbol binario o c\u00f3mo construir un \u00e1rbol binario de b\u00fasqueda\" src=\"\/wp-content\/uploads\/2019\/03\/0d600478e4a046ae6f7267be49b231bc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h4>B\u00fasqueda del sucesor<\/h4>\n<p>\n Supongamos que necesitamos eliminar el nodo con la clave 25. \u00bfA qui\u00e9n pondremos en su lugar? Alguien de sus seguidores (descendientes o descendientes de descendientes) debe convertirse en <i>el sucesor<\/i>(quien ocupe el lugar del nodo eliminado). <\/p>\n<p>\u00bfC\u00f3mo entender qui\u00e9n debe convertirse en sucesor? Es intuitivamente claro que este nodo en el \u00e1rbol es aquel cuya clave es la siguiente m\u00e1s grande que la del nodo eliminado. El algoritmo consiste en lo siguiente. Debemos ir a su descendiente derecho (siempre al derecho, ya que ya se ha dicho que la clave del sucesor es mayor que la clave del nodo eliminado), y luego recorrer la cadena de descendientes izquierdos de ese descendiente derecho. En el ejemplo, debemos ir al nodo con la clave 35 y luego bajar por la cadena de descendientes izquierdos hasta llegar a la hoja; en este caso, esta cadena consiste solo en el nodo con la clave 30. Estrictamente hablando, estamos buscando el nodo m\u00e1s peque\u00f1o en el conjunto de nodos que son m\u00e1s grandes que el nodo buscado.<\/p>\n<p><img decoding=\"async\" alt=\"\u00c1rbol binario o c\u00f3mo construir un \u00e1rbol binario de b\u00fasqueda\" src=\"\/wp-content\/uploads\/2019\/03\/50c4e3e49111eec9e1fd13083ee9b9b0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nC\u00f3digo del m\u00e9todo de b\u00fasqueda del sucesor:<\/p>\n<pre><code class=\"java\">    public Node&lt;T&gt; getSuccessor(Node&lt;T&gt; deleteNode) {\n        Node&lt;T&gt; parentSuccessor = deleteNode; \/\/ padre del sucesor\n        Node&lt;T&gt; successor = deleteNode; \/\/ sucesor\n        Node&lt;T&gt; current = successor.getRightChild(); \/\/ nodo \"traves\u00eda\"\n        while (current != null) {\n            parentSuccessor = successor;\n            successor = current;\n            current = current.getLeftChild();\n        }\n        \/\/ al salir del ciclo tenemos al sucesor y al padre del sucesor\n        if (successor != deleteNode.getRightChild()) { \/\/ si el sucesor no coincide con el hijo derecho del nodo eliminado\n            parentSuccessor.setLeftChild(successor.getRightChild()); \/\/ entonces su padre toma el hijo del sucesor para no perderlo\n            successor.setRightChild(deleteNode.getRightChild()); \/\/ enlazamos el sucesor con el hijo derecho del nodo eliminado\n        }\n        return successor;\n    }\n<\/code><\/pre>\n<p>\nC\u00f3digo completo del m\u00e9todo delete:<\/p>\n<pre><code class=\"java\">public boolean delete(int deleteKey) {\n        Node current = root;\n        Node parent = current;\n        boolean isLeftChild = false; \/\/ Dependiendo de si el nodo a eliminar es un hijo izquierdo o derecho de su padre, la variable booleana isLeftChild tomar\u00e1 el valor true o false respectivamente.\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) { \/\/ Primer 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) { \/\/ Segundo 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 { \/\/ Tercer 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 complejidad puede ser aproximada a O(log(n)).<\/p>\n<h3>B\u00fasqueda de m\u00e1ximo\/m\u00ednimo en el \u00e1rbol<\/h3>\n<p>\nObviamente, para encontrar el valor m\u00ednimo\/m\u00e1ximo en el \u00e1rbol, se debe ir recorriendo de manera secuencial la cadena de elementos izquierdos\/derechos del \u00e1rbol respectivamente; cuando llegues a una hoja, ser\u00e1 el elemento m\u00ednimo\/m\u00e1ximo.<\/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 complejidad es O(log(n))<\/p>\n<h3>Recorrido sim\u00e9trico<\/h3>\n<p>\nEl recorrido es visitar cada nodo del \u00e1rbol con el objetivo de realizar alguna acci\u00f3n con \u00e9l.<\/p>\n<p>Algoritmo del recorrido sim\u00e9trico recursivo:<\/p>\n<ol>\n<li>Realizar una acci\u00f3n con el hijo izquierdo<\/li>\n<li>Realizar una acci\u00f3n consigo mismo<\/li>\n<li>Realizar una acci\u00f3n con el hijo derecho<\/li>\n<\/ol>\n<p>\nC\u00f3digo:<\/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() + \" \");\/\/Aqu\u00ed puede haber cualquier cosa\n            inOrder(current.getRightChild());\n        }\n    }\n<\/code><\/pre>\n<p><\/p>\n<h2>Conclusi\u00f3n<\/h2>\n<p>\n\u00a1Por fin! Si he dejado algo sin explicar o hay alg\u00fan comentario, espero sus opiniones. Como promet\u00ed, aqu\u00ed est\u00e1 el c\u00f3digo 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\">public class 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.D.<\/h2>\n<p><\/p>\n<h3>Degeneraci\u00f3n a O(n)<\/h3>\n<p>\nMuchos de ustedes habr\u00e1n notado: \u00bfy si hacemos que el \u00e1rbol se vuelva desequilibrado? Por ejemplo, si insertamos nodos en el \u00e1rbol con claves crecientes: 1,2,3,4,5,6\u2026 Entonces el \u00e1rbol se parecer\u00e1 a una lista enlazada. Y s\u00ed, el \u00e1rbol perder\u00e1 su estructura jer\u00e1rquica, y por lo tanto, la eficiencia en el acceso a los datos. La complejidad de las operaciones de b\u00fasqueda, inserci\u00f3n y eliminaci\u00f3n ser\u00e1 la misma que en una lista enlazada: O(n). Este es uno de los m\u00e1s importantes, en mi opini\u00f3n, desventajas de los \u00e1rboles binarios.<\/p>\n<p class=\"for_users_only_msg\">Solo los usuarios registrados pueden participar en la encuesta. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/auth\/login\/\">Inicie sesi\u00f3n<\/a><\/noindex>, por favor.<\/p>\n<h2 class=\"default-block__polling-title\">No hace mucho que estoy en Habr, y me gustar\u00eda saber qu\u00e9 temas les gustar\u00eda ver m\u00e1s en los art\u00edculos.<\/h2>\n<ul class=\"content-list content-list_polling\">\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Estructuras de datos<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Algoritmos (DP, recursi\u00f3n, compresi\u00f3n de datos, etc.)<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Aplicaci\u00f3n de estructuras de datos y algoritmos en la vida real<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Programaci\u00f3n de aplicaciones Android en Java<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Programaci\u00f3n de aplicaciones web en Java<\/p>\n<\/li>\n<\/ul>\n<p>    Votaron 2 usuarios. Se abstuvo 1 usuario.<br \/>\n<br \/>Fuente: 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.2 - 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\/es\/blog\/administrirovanie\/binary-tree-ili-kak-prigotovit-binarnoe-derevo-poiska\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"es_ES\" \/>\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\/es\/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\udd47Binary Tree o c\u00f3mo preparar un \u00e1rbol binario de b\u00fasqueda | ProHoster","description":"Preludio Este art\u00edculo est\u00e1 dedicado a los \u00e1rboles binarios de b\u00fasqueda.","canonical_url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/binary-tree-ili-kak-prigotovit-binarnoe-derevo-poiska","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"es_ES","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\/es\/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\/es\/wp-json\/wp\/v2\/posts\/30530","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/comments?post=30530"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/30530\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media\/22528"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media?parent=30530"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/categories?post=30530"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/tags?post=30530"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}