{"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\/et\/blog\/administrirovanie\/binary-tree-ili-kak-prigotovit-binarnoe-derevo-poiska","title":{"rendered":"Binary Tree ehk kuidas koostada binaarset otsingupuud","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<h2>Eelajak<\/h2>\n<p>\nSee artikkel on p\u00fchendatud binaarsetele otsingupuidule. Hiljuti kirjutasin artikli <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/438512\/\">Huffmani meetodiga andmete tihendamisest.<\/a><\/noindex> Seal ma ei p\u00f6\u00f6ranud liiga palju t\u00e4helepanu binaarsetele puudele, kuna otsingu, sisestamise ja kustutamise meetodid ei olnud aktuaalsed. N\u00fc\u00fcd otsustasin kirjutada artikli just puude kohta. Alustame. <\/p>\n<p>Puu on andmestruktuur, mis koosneb s\u00f5lmedest, mis on \u00fchendatud harudega. V\u00f5ib \u00f6elda, et puu on graafi spetsiifiline juhtum. Siin on n\u00e4ide puust: <\/p>\n<p><img decoding=\"async\" alt=\"Binary Tree ehk kuidas koostada binaarset otsingupuud\" src=\"\/wp-content\/uploads\/2019\/03\/502ac27f1b93f926c68a68777f6bddd7.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSee ei ole binaarne otsingupuu! Kogu teave on peidetud!<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Terminoloogia<\/h2>\n<p><\/p>\n<h4>Juurtipp<\/h4>\n<p>\n<i>Puu juurtipp<\/i> on selle k\u00f5ige \u00fclemine s\u00f5lm. Antud n\u00e4ites on see s\u00f5lm A. Puust juurelt igale teisele s\u00f5lmile v\u00f5ib viia ainult \u00fcks tee! Tegelikult v\u00f5ib iga s\u00f5lme k\u00e4sitleda kui vastava s\u00f5lme alampuu juurt.<\/p>\n<h4>Vanem\/alam<\/h4>\n<p>\nK\u00f5igil s\u00f5lmedel, v\u00e4lja arvatud juurtipp, on t\u00e4pselt \u00fcks haru, mis viib \u00fcles poole teise s\u00f5lme juurde. S\u00f5lm, mis asub hetke kohal, nimetatakse <i>vanemaks<\/i> selle s\u00f5lme jaoks. S\u00f5lm, mis asub hetke all ja on sellega \u00fchendatud, nimetatakse <i>alamaks<\/i> selle s\u00f5lme jaoks. Vaatame n\u00e4idet. V\u00f5tame s\u00f5lme B, siis on selle vanem s\u00f5lm A ja alamad on s\u00f5lmed D, E ja F.<\/p>\n<h4>Leht<\/h4>\n<p>\nS\u00f5lm, millel ei ole alamad, nimetatakse puu leheks. Antud n\u00e4ites on lehed s\u00f5lmed D, E, F, G, I, J ja K.<\/p>\n<p>See on p\u00f5hiterminoloogia. Teisi m\u00f5isteid k\u00e4sitletakse hiljem. Nii et binaarne puu on puu, millel igal s\u00f5lmel v\u00f5ib olla mitte rohkem kui kaks alamad. Nagu te juba arvata v\u00f5isite, ei ole antud n\u00e4ide binaarne, kuna s\u00f5lmed B ja H on enam kui kahe alamaga. Siin on n\u00e4ide binaarsest puust:<\/p>\n<p><img decoding=\"async\" alt=\"Binary Tree ehk kuidas koostada binaarset otsingupuud\" src=\"\/wp-content\/uploads\/2019\/03\/2f587bd1c428d3850cb0163d6c2984a1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPuu s\u00f5lmedes v\u00f5ib olla mistahes teavet. Binaarne otsingupuu on binaarne puu, millel on j\u00e4rgmised omadused:<\/p>\n<ol>\n<li>M\u00f5lemad alampuud \u2014 vasak ja parem \u2014 on binaarsed otsingupuud.<\/li>\n<li>K\u00f5igil vasaku alampuu s\u00f5lmedel, mis kuuluvad suvalisele s\u00f5lmele X, on andmete v\u00f5tmete v\u00e4\u00e4rtused v\u00e4iksemad kui s\u00f5lme X enda v\u00f5tme v\u00e4\u00e4rtus.<\/li>\n<li>K\u00f5igil parema alampuu s\u00f5lmedel, mis kuuluvad suvalisele s\u00f5lmele X, on andmete v\u00f5tmete v\u00e4\u00e4rtused suuremad v\u00f5i v\u00f5rdsed s\u00f5lme X enda v\u00f5tme v\u00e4\u00e4rtusega. <\/li>\n<\/ol>\n<p><i>V\u00f5ti<\/i> on mis tahes s\u00f5lme omadus (nt number). V\u00f5ti on vajalik selleks, et leida puust element, millele see v\u00f5ti vastab. N\u00e4ide binaarsest otsingupuust:<\/p>\n<p><img decoding=\"async\" alt=\"Binary Tree ehk kuidas koostada binaarset otsingupuud\" src=\"\/wp-content\/uploads\/2019\/03\/a70ca7d2fdf289b5d1e14bdb4bc38b00.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h2>Puu esitus<\/h2>\n<p>\nEdasi liikudes toon ma v\u00e4lja m\u00f5ned (v\u00f5imalikult mittet\u00e4ielikud) koodil\u00f5igud, et parandada teie arusaamist. T\u00e4ielik kood leiab aset artikli l\u00f5pus. <\/p>\n<p>Puu koosneb s\u00f5lmedest. S\u00f5lme struktuur:<\/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\/\/...teised s\u00f5lme meetodid\n}\n<\/code><\/pre>\n<p>\nIgal s\u00f5lmel on kaks j\u00e4reltulijat (v\u00f5imalik, et j\u00e4reltulijad leftChild ja \/ v\u00f5i rightChild v\u00f5ivad sisaldada v\u00e4\u00e4rtust null). Olete ilmselt aru saanud, et antud juhul number data \u2014 andmed, mis on s\u00f5lmes salvestatud; key \u2014 s\u00f5lme v\u00f5ti.<\/p>\n<p>S\u00f5lmega oleme kursis, n\u00fc\u00fcd r\u00e4\u00e4gime puude praegustest probleemidest. Edaspidi m\u00f5tlen s\u00f5na \"puu\" all binaarset otsingu puud. Binaarse puu struktuur:<\/p>\n<pre><code class=\"java\">public class BinaryTree&lt;T&gt; {\n     private Node&lt;T&gt; root;\n\n    \/\/puu meetodid\n}\n<\/code><\/pre>\n<p>Klassi v\u00e4ljana vajame ainult puu juurt, sest juure kaudu saab meetodite getLeftChild() ja getRightChild() abil j\u00f5uda igasugusele puu s\u00f5lmele.<\/p>\n<h2>Puu algoritmid<\/h2>\n<p><\/p>\n<h3>Vastuse otsimine peab olema keeruline \u2014 kui vastust on lihtne leida<\/h3>\n<p>\nEeldame, et teil on \u00fcles ehitatud puu. Kuidas leida elementi, mille v\u00f5ti on key? Tuleb j\u00e4rjestikku liikuda juurelt alla puu kaudu ja v\u00f5rrelda v\u00e4list key s\u00f5lme v\u00f5tmega: kui key on v\u00e4iksem kui j\u00e4rgmise s\u00f5lme v\u00f5ti, siis liikuda s\u00f5lme vasakule j\u00e4reltulijale, kui suurem \u2014 paremale, kui v\u00f5tmed on v\u00f5rdsed \u2014 otsitav s\u00f5lm on leitud! Vastav kood:<\/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>\nKui current saab nulliks, t\u00e4hendab, et otsing j\u00f5udis puu l\u00f5puni (kontseptsiooniliselt asute te mitteeksisteerivas puu kohas \u2014 lehe j\u00e4reltulijas).<\/p>\n<p>Vaadakem otsingu algoritmi efektiivsust tasakaalus puus (puus, kus s\u00f5lmed on jaotatud \u00fcksjagu \u00fchtlaselt). Sel juhul on otsingu efektiivsus O(log(n)), kusjuures logaritm on p\u00f5hjal 2. Vaadake: kui tasakaalus puus on n elementi, siis see t\u00e4hendab, et puul on log(n) taset. Otsingu k\u00e4igus langete \u00fche sammuga ts\u00fcklis \u00fche taseme v\u00f5rra alla.<\/p>\n<h3>Sisestamine<\/h3>\n<p>\nKui olete otsingu olemuse tabanud, siis ei ole lisamise m\u00f5istmine teile raske. Tuleb lihtsalt liikuda puu lehe juurde (langemisreeglite kohaselt, nagu otsingus kirjeldatud) ja saada selle j\u00e4reltulijaks \u2014 vasakuks v\u00f5i paremaks, s\u00f5ltuvalt v\u00f5tme v\u00e4\u00e4rtusest. Rakendamine:<\/p>\n<pre><code class=\"java\">   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<\/code><\/pre>\n<p>\nAntud juhul tuleb lisaks hetkelisele s\u00f5lmele hoida teavet k\u00e4esoleva s\u00f5lme vanemast. Kui current muutub nulliks, siis on muutujas parent vajalik leht. <br \/>\nSelgelt on sisestamise t\u00f5husus sama, mis otsingul \u2014 O(log(n)).<\/p>\n<h3>Kustutamine<\/h3>\n<p>\nKustutamine on k\u00f5ige keerulisem operatsioon, mille tuleb puu peal teostada. On selge, et k\u00f5igepealt tuleb leida element, mida me kavandame kustutada. Aga mis siis? Kui lihtsalt omistada selle lingile v\u00e4\u00e4rtus null, kaotame teabe selle s\u00f5lme juures oleva alampuu kohta. Puu kustutamise meetodid jagunevad kolmeks juhtumiks.<\/p>\n<h4>Esimene juhtum. Kustutatav s\u00f5lm ei oma j\u00e4reltulijaid<\/h4>\n<p>\nKui kustutataval s\u00f5lmel ei ole j\u00e4reltulijaid, t\u00e4hendab see, et see on leht. Seet\u00f5ttu saab lihtsalt vanema leftChild v\u00f5i rightChild v\u00e4ljadele m\u00e4\u00e4rata nulli. <\/p>\n<h4>Teine juhtum. Kustutataval s\u00f5lmel on \u00fcks j\u00e4reltulija<\/h4>\n<p>\nSee juhtum ei ole samuti v\u00e4ga keeruline. Naaseme tagasi meie n\u00e4ite juurde. Oletame, et tuleb kustutada element v\u00f5tmega 14. Olgu see nii, et kuna see on s\u00f5lm, millel on v\u00f5tmega 10 \u00f5igus j\u00e4reltulija, on selle j\u00e4reltulija (antud juhul parem) v\u00f5tme v\u00e4\u00e4rtus alati suurem kui 10, seega saab selle lihtsalt puust 'v\u00e4lja l\u00f5igata' ja vanema otse j\u00e4reltulijaga \u00fchendada, s.t. s\u00f5le v\u00f5tmega 10 \u00fchendatakse s\u00f5lmiga 13. Sarnane oleks olukord, kui peaksime kustutama s\u00f5lme, mis on oma vanema vasak j\u00e4reltulija. M\u00f5elge selle \u00fcle ise \u2014 t\u00e4pne analoogia. <\/p>\n<h4>Kolmas juhtum. S\u00f5lmel on kaks j\u00e4reltulijat<\/h4>\n<p>\nSee on k\u00f5ige keerulisem juhtum. Anal\u00fc\u00fcsime uut n\u00e4idet.<\/p>\n<p><img decoding=\"async\" alt=\"Binary Tree ehk kuidas koostada binaarset otsingupuud\" src=\"\/wp-content\/uploads\/2019\/03\/0d600478e4a046ae6f7267be49b231bc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h4>Eelk\u00e4ija otsimine<\/h4>\n<p>\n Oletame, et peame kustutama s\u00f5lme, mille v\u00f5ti on 25. Keda paneme selle asemele? Keegi tema j\u00e4rglastest (j\u00e4reltulijatest v\u00f5i j\u00e4reltulijate j\u00e4reltulijatest) peab saama <i>j\u00e4rglaseks<\/i>(see, kes v\u00f5tab eemaldatava s\u00f5lme koha). <\/p>\n<p>Kuidas m\u00f5ista, kes peaks saama j\u00e4rglaseks? Intuitiivselt on selge, et see on puu s\u00f5lm, mille v\u00f5ti on eemaldatava s\u00f5lme omast suurem. Algoritm on j\u00e4rgmine. Tuleb liikuda tema paremale j\u00e4reltulijale (alati paremale, kuna on juba \u00f6eldud, et j\u00e4rglase v\u00f5ti on suurem kui eemaldatava s\u00f5lme oma) ning seej\u00e4rel minna vasakute j\u00e4reltulijate ahelas selle parema j\u00e4reltulija juurde. N\u00e4ites peame liikuma s\u00f5lme, mille v\u00f5ti on 35, ja seej\u00e4rel j\u00e4rgnema allapoole tema vasakute j\u00e4reltulijate ahelas \u2014 antud juhul koosneb see ahel vaid s\u00f5lmest, mille v\u00f5ti on 30. Rikkalikult \u00f6eldes otsime toetava s\u00f5lme seas k\u00f5ige v\u00e4iksemat s\u00f5lme, mis on suurem kui otsitav s\u00f5lm.<\/p>\n<p><img decoding=\"async\" alt=\"Binary Tree ehk kuidas koostada binaarset otsingupuud\" src=\"\/wp-content\/uploads\/2019\/03\/50c4e3e49111eec9e1fd13083ee9b9b0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nJ\u00e4rglase otsimise meetodi kood:<\/p>\n<pre><code class=\"java\">    public Node&lt;T&gt; getSuccessor(Node&lt;T&gt; deleteNode) {\n        Node&lt;T&gt; parentSuccessor = deleteNode; \/\/ j\u00e4rglase vanem\n        Node&lt;T&gt; successor = deleteNode; \/\/ j\u00e4rglane\n        Node&lt;T&gt; current = successor.getRightChild(); \/\/ lihtsalt 'l\u00e4bivate' s\u00f5lm\n        while (current != null) {\n            parentSuccessor = successor;\n            successor = current;\n            current = current.getLeftChild();\n        }\n        \/\/ ts\u00fcklist v\u00e4ljudes saame j\u00e4rglase ja j\u00e4rglase vanema\n        if (successor != deleteNode.getRightChild()) { \/\/ kui j\u00e4rglane ei lange kokku eemaldatava s\u00f5lme parema j\u00e4reltulijaga\n            parentSuccessor.setLeftChild(successor.getRightChild()); \/\/ siis tema vanem v\u00f5tab j\u00e4rglase j\u00e4reltulija endale, et mitte seda kaotada\n            successor.setRightChild(deleteNode.getRightChild()); \/\/ seome j\u00e4rglase eemaldatava s\u00f5lme parema j\u00e4reltulijaga\n        }\n        return successor;\n    }\n<\/code><\/pre>\n<p>\nKustutamise meetodi t\u00e4ielik kood:<\/p>\n<pre><code class=\"java\">public boolean delete(int deleteKey) {\n        Node current = root;\n        Node parent = current;\n        boolean isLeftChild = false; \/\/ Olene l\u00e4hetamine vastavalt, kas kustutatav s\u00f5lm on oma vanema vasak v\u00f5i parem laps, boolean muutuja isLeftChild omandab vastavalt true v\u00f5i 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) { \/\/ esimene juhus\n            if (current == root)\n                current = null;\n            else if (isLeftChild)\n                parent.setLeftChild(null);\n            else\n                parent.setRightChild(null);\n        } else if (current.getRightChild() == null) { \/\/ teine juhus\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 { \/\/ kolmas juhus\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>\nAja keerukus v\u00f5ib olla ligikaudu O(log(n)).<\/p>\n<h3>Puu maksimaalse\/minimaalse v\u00e4\u00e4rtuse otsimine<\/h3>\n<p>\nSelgelt, kuidas leida puu minimaalne\/maximaalne v\u00e4\u00e4rtus - tuleb j\u00e4rjestikku liikuda vasakute\/paremate puu elementide ahelas; kui j\u00f5uate lehtedeni, siis see on minimaalne\/maximaalne element.<\/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>\nKeerukus - O(log(n))<\/p>\n<h3>S\u00fcmmeetriline l\u00e4bimine<\/h3>\n<p>\nL\u00e4bimine - iga puu s\u00f5lme k\u00fclastamine, et teha selle kohta mingisugune toiming.<\/p>\n<p>Rekursiivse s\u00fcmmeetrilise l\u00e4bimise algoritm:<\/p>\n<ol>\n<li>Teha toiming vasaku lapsega<\/li>\n<li>Teha toiming iseendaga<\/li>\n<li>Teha toiming parema lapsega<\/li>\n<\/ol>\n<p>\nKood:<\/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() + \" \");\/\/Siin v\u00f5ib olla k\u00f5ik, mis tahes\n            inOrder(current.getRightChild());\n        }\n    }\n<\/code><\/pre>\n<p><\/p>\n<h2>Kokkuv\u00f5te<\/h2>\n<p>\nL\u00f5puks! Kui ma midagi piisavalt ei selgitanud v\u00f5i kui on mingeid m\u00e4rkusi, ootan kommentaarides. Nagu lubatud, jagan t\u00e4ismahus koodi.<\/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.S.<\/h2>\n<p><\/p>\n<h3>Langenemine O(n) tasemele<\/h3>\n<p>\nPaljud teist on ehk m\u00e4rganud: mis oleks, kui teha puust tasakaalustamata? N\u00e4iteks paigutada puusse s\u00f5lmed, millel on kasvavad v\u00f5tmed: 1, 2, 3, 4, 5, 6... Siis hakkab puu meenutama seotud loendit. Jah, puu kaotab oma puulaadse struktuuri ja seega ka andmete juurdep\u00e4\u00e4su efektiivsuse. Otsingu, sisestamise, kustutamise operatsioonide keerukus muutub sarnaseks seotud loendi omaga: O(n). See on \u00fcks peamine puudus, mida ma arvan, et binaarsetel puudel on.<\/p>\n<p class=\"for_users_only_msg\">Ainult registreeritud kasutajad saavad k\u00fcsitluses osaleda. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/auth\/login\/\">Logige sisse<\/a><\/noindex>, palun.<\/p>\n<h2 class=\"default-block__polling-title\">Ma olen hiljuti Habr's ja tahaksin teada, milliseid teemasid sooviksite rohkem n\u00e4ha?<\/h2>\n<ul class=\"content-list content-list_polling\">\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Andmestruktuurid<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Algoritmid (D\u00fcnaamiline Programmeerimine, rekursioon, andmete kokkusurumine jne)<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Andmestruktuuride ja algoritmide rakendamine reaalses elus<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Androidi rakenduste programmeerimine Java's<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Veebirakenduste programmeerimine Java's<\/p>\n<\/li>\n<\/ul>\n<p>    H\u00e4\u00e4letas 2 kasutajat. 1 kasutaja hoidus.<br \/>\n<br \/>Allikas: 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\/et\/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=\"et_EE\" \/>\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\/et\/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 ehk kuidas valmistada binaarset otsingupuud | ProHoster","description":"Ekleesia See artikkel on p\u00fchendatud binaarsetele otsingupuudele.","canonical_url":"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/binary-tree-ili-kak-prigotovit-binarnoe-derevo-poiska","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"et_EE","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\/et\/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\/et\/wp-json\/wp\/v2\/posts\/30530","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/comments?post=30530"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts\/30530\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/media\/22528"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/media?parent=30530"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/categories?post=30530"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/tags?post=30530"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}