{"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\/hr\/blog\/administrirovanie\/binary-tree-ili-kak-prigotovit-binarnoe-derevo-poiska","title":{"rendered":"Binary Tree ili kako pripremiti binarno stablo pretra\u017eivanja","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<h2>Preludij<\/h2>\n<p>\nOvaj \u010dlanak posve\u0107en je binarnim stablima pretra\u017eivanja. Nedavno sam pisao \u010dlanak o <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/438512\/\">kompresiji podataka metodom Huffman.<\/a><\/noindex> Tamo nisam previ\u0161e obra\u0107ao pa\u017enju na binarna stabla, jer metode pretra\u017eivanja, umetanja i brisanja nisu bile relevantne. Sad sam odlu\u010dio napisati \u010dlanak upravo o stablima. Pa, da po\u010dnemo. <\/p>\n<p>Stablo je struktura podataka koja se sastoji od \u010dvorova povezanih granama. Mo\u017ee se re\u0107i da je stablo posebni slu\u010daj grafa. Evo primera stabla: <\/p>\n<p><img decoding=\"async\" alt=\"Binary Tree ili kako pripremiti binarno stablo pretra\u017eivanja\" src=\"\/wp-content\/uploads\/2019\/03\/502ac27f1b93f926c68a68777f6bddd7.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nTo nije binarno stablo pretra\u017eivanja! Sve pod kat.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Terminologija<\/h2>\n<p><\/p>\n<h4>Korijen<\/h4>\n<p>\n<i>Korijen stabla<\/i> je njegov najgornji \u010dvor. U primeru, to je \u010dvor A. U stablu mo\u017ee postojati samo jedan put od korijena do bilo kojeg drugog \u010dvora! U stvarnosti, svaki \u010dvor se mo\u017ee smatrati korijenom odgovaraju\u0107eg podstabla.<\/p>\n<h4>Roditelji\/ potomci<\/h4>\n<p>\nSvi \u010dvorovi, osim korijena, imaju ta\u010dno jednu granju koja vodi prema drugom \u010dvoru. \u010cvor koji se nalazi iznad trenutnog naziva se <i>roditeljem<\/i> ovog \u010dvora. \u010cvor koji se nalazi ispod trenutnog i povezan je s njim, naziva se <i>potomkom<\/i> ovog \u010dvora. Pogledajmo primer. Uzmimo \u010dvor B, tada \u0107e njegov roditelj biti \u010dvor A, a potomci \u0107e biti \u010dvorovi D, E i F.<\/p>\n<h4>List<\/h4>\n<p>\n\u010cvor koji nema potomaka naziva se listem stabla. U primeru, listovi \u0107e biti \u010dvorovi D, E, F, G, I, J, K.<\/p>\n<p>Ovo je osnovna terminologija. Ostali pojmovi \u0107e biti razra\u0111eni kasnije. Tako, binarno stablo je stablo u kojem svaki \u010dvor mo\u017ee imati najvi\u0161e dva potomka. Kako ste pogodili, stablo iz primera ne\u0107e biti binarno, jer \u010dvorovi B i H imaju vi\u0161e od dva potomka. Evo primera binarnog stabla:<\/p>\n<p><img decoding=\"async\" alt=\"Binary Tree ili kako pripremiti binarno stablo pretra\u017eivanja\" src=\"\/wp-content\/uploads\/2019\/03\/2f587bd1c428d3850cb0163d6c2984a1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nU \u010dvorovima stabla mo\u017ee se nalaziti bilo koja informacija. Binarno stablo pretra\u017eivanja je binarno stablo koje ima slede\u0107e osobine:<\/p>\n<ol>\n<li>Oba podstabla \u2014 levo i desno \u2014 su binarna stabla pretra\u017eivanja.<\/li>\n<li>Svi \u010dvorovi levog podstabla proizvoljnog \u010dvora X imaju vrednosti klju\u010deva podataka manje od vrednosti klju\u010da podataka samog \u010dvora X.<\/li>\n<li>Svi \u010dvorovi desnog podstabla proizvoljnog \u010dvora X imaju vrednosti klju\u010deva podataka ve\u0107e ili jednake od vrednosti klju\u010da podataka samog \u010dvora X. <\/li>\n<\/ol>\n<p><i>Klju\u010d<\/i> \u2014 neka karakteristika \u010dvora (na primer, broj). Klju\u010d je potreban kako bi se mogla prona\u0107i stavka stabla kojoj odgovara taj klju\u010d. Primer binarnog stabla pretra\u017eivanja:<\/p>\n<p><img decoding=\"async\" alt=\"Binary Tree ili kako pripremiti binarno stablo pretra\u017eivanja\" src=\"\/wp-content\/uploads\/2019\/03\/a70ca7d2fdf289b5d1e14bdb4bc38b00.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h2>Predstavljanje stabla<\/h2>\n<p>\nKako napredujem, navest \u0107u neke (mogu\u0107e nepotpune) dijelove koda kako bih pobolj\u0161ao va\u0161e razumijevanje. Cijeli kod bit \u0107e na kraju \u010dlanka. <\/p>\n<p>Stablo se sastoji od \u010dvorova. Struktura \u010dvora:<\/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\/\/...ostali metodi \u010dvora\n}\n<\/code><\/pre>\n<p>\nSvaki \u010dvor ima dva potomka (mogu\u0107e je da potomci leftChild i\/ili rightChild sadr\u017ee vrijednost null). Vjerojatno ste shvatili da u ovom slu\u010daju data predstavlja podatke pohranjene u \u010dvoru; key je klju\u010d \u010dvora.<\/p>\n<p>O \u010dvorovima smo razgovarali, sada razgovarajmo o hitnim problemima stabala. Ovdje i dalje pod pojmom \u201establo\u201c mislim na pojam binarnog stabla pretra\u017eivanja. Struktura binarnog stabla:<\/p>\n<pre><code class=\"java\">public class BinaryTree&lt;T&gt; {\n     private Node&lt;T&gt; root;\n\n    \/\/metode stabla\n}\n<\/code><\/pre>\n<p>Kao polje klase trebat \u0107e nam samo korijen stabla, jer se od korijena pomo\u0107u metoda getLeftChild() i getRightChild() mo\u017ee do\u0107i do bilo kojeg \u010dvora stabla.<\/p>\n<h2>Algoritmi u stablu<\/h2>\n<p><\/p>\n<h3>Pretra\u017eivanje<\/h3>\n<p>\nPretpostavimo da imate izgra\u0111eno stablo. Kako prona\u0107i element s klju\u010dem key? Trebate se postupno kretati od korijena prema dolje po stablu i uspore\u0111ivati vrijednost key s klju\u010dem trenutnog \u010dvora: ako je key manji od klju\u010da trenutnog \u010dvora, pre\u0111ite na lijevog potomka \u010dvora, ako je ve\u0107i \u2014 na desnog, ako su klju\u010devi jednaki \u2014 tra\u017eeni \u010dvor je prona\u0111en! Odgovaraju\u0107i kod:<\/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>\nAko current postane jednak null, to zna\u010di da je pretraga dostigla kraj stabla (na konceptualnoj razini nalazite se na nepostoje\u0107em mjestu stabla \u2014 potomku lista).<\/p>\n<p>Razmotrimo u\u010dinkovitost algoritma pretra\u017eivanja na uravnote\u017eenom stablu (stablo u kojem su \u010dvorovi raspore\u0111eni vi\u0161e-manje ravnomjerno). Tada \u0107e u\u010dinkovitost pretra\u017eivanja biti O(log(n)), pri \u010demu je logaritam na osnovi 2. Pogledajte: ako u uravnote\u017eenom stablu ima n elemenata, to zna\u010di da \u0107e biti log(n) na osnovi 2 razina stabla. A u pretra\u017eivanju, za jedan korak petlje, silazite na jedan nivo.<\/p>\n<h3>Umetanje<\/h3>\n<p>\nAko ste shvatili su\u0161tinu pretra\u017eivanja, onda vam umetanje ne\u0107e biti te\u0161ko. Samo se treba spustiti do lista stabla (prema pravilima spu\u0161tanja opisanima u pretra\u017eivanju) i postati njegov potomak \u2014 levi ili desni, u zavisnosti od klju\u010da. Implementacija:<\/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>\nU ovom slu\u010daju je potrebno, osim trenutnog \u010dvora, \u010duvati informacije o roditelju trenutnog \u010dvora. Kada current postane null, u varijabli parent \u0107e biti potrebni list. <br \/>\nEfikasnost umetanja, o\u010digledno, bi\u0107e ista kao i kod pretra\u017eivanja \u2014 O(log(n)).<\/p>\n<h3>Brisanje<\/h3>\n<p>\nBrisanje je najte\u017ea operacija koju treba sprovesti sa stablom. Jasno je da prvo treba prona\u0107i element koji nameravamo da obri\u0161emo. Ali \u0161ta onda? Ako jednostavno dodelimo njegovom referencu vrednost null, izgubi\u0107emo informacije o podstablu \u010diji je ovaj \u010dvor koren. Metode brisanja stabla delimo u tri slu\u010daja.<\/p>\n<h4>Prvi slu\u010daj. Bri\u0161emo \u010dvor koji nema potomaka<\/h4>\n<p>\nAko bri\u0161emo \u010dvor koji nema potomaka, to zna\u010di da je list. Stoga se jednostavno mo\u017ee dodeliti poljima leftChild ili rightChild njegovog roditelja vrednost null. <\/p>\n<h4>Drugi slu\u010daj. Bri\u0161emo \u010dvor koji ima jednog potomka<\/h4>\n<p>\nOvaj slu\u010daj tako\u0111e nije previ\u0161e slo\u017een. Vratimo se na\u0161em primeru. Recimo da treba da obri\u0161emo element sa klju\u010dem 14. Sla\u017eete se da, po\u0161to je on desni potomak \u010dvora sa klju\u010dem 10, bilo koji njegov potomak (u ovom slu\u010daju desni) \u0107e imati klju\u010d ve\u0107i od 10, stoga ga mo\u017eemo lako \u201eizrezati\u201c iz stabla, a roditelja direktno povezati sa potomkom bri\u0161u\u0107eg \u010dvora, tj. \u010dvor sa klju\u010dem 10 povezati sa \u010dvorom 13. Sli\u010dna bi situacija bila da smo trebali obrisati \u010dvor koji je levi potomak svog roditelja. Razmislite o tome sami \u2014 ta\u010dna analogija. <\/p>\n<h4>Tre\u0107i slu\u010daj. \u010cvor ima dva potomka<\/h4>\n<p>\nNajkompleksniji slu\u010daj. Razradi\u0107emo to na novom primeru.<\/p>\n<p><img decoding=\"async\" alt=\"Binary Tree ili kako pripremiti binarno stablo pretra\u017eivanja\" src=\"\/wp-content\/uploads\/2019\/03\/0d600478e4a046ae6f7267be49b231bc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h4>Pretraga naslednika<\/h4>\n<p>\n Pretpostavimo da trebamo ukloniti \u010dvor s klju\u010dem 25. Koga \u0107emo postaviti na njegovo mjesto? Netko od njegovih sljedbenika (potomaka ili potomaka potomaka) trebao bi postati <i>nasljednik<\/i>(onaj tko zauzima mjesto uklonjenog \u010dvora). <\/p>\n<p>Kako shvatiti tko bi trebao postati nasljednik? Intuitivno je jasno da je to \u010dvor u stablu \u010diji je klju\u010d sljede\u0107i ve\u0107i od uklonjenog \u010dvora. Algoritam se svodi na sljede\u0107e. Trebamo prije\u0107i na njegovog desnog potomka (uvijek na desnog, jer je ve\u0107 re\u010deno da je klju\u010d nasljednika ve\u0107i od klju\u010da uklonjenog \u010dvora), a zatim pro\u0107i kroz lanac lijevih potomaka tog desnog potomka. U primjeru trebamo prije\u0107i na \u010dvor s klju\u010dem 35, a zatim se spustiti do lista kroz lanac njegovih lijevih potomaka \u2014 u ovom slu\u010daju, taj lanac se sastoji samo od \u010dvora s klju\u010dem 30. Strogo govore\u0107i, tra\u017eimo najmanji \u010dvor u skupu \u010dvorova, ve\u0107ih od tra\u017eenog \u010dvora.<\/p>\n<p><img decoding=\"async\" alt=\"Binary Tree ili kako pripremiti binarno stablo pretra\u017eivanja\" src=\"\/wp-content\/uploads\/2019\/03\/50c4e3e49111eec9e1fd13083ee9b9b0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nKod metode pretra\u017eivanja nasljednika:<\/p>\n<pre><code class=\"java\">    public Node&lt;T&gt; getSuccessor(Node&lt;T&gt; deleteNode) {\n        Node&lt;T&gt; parentSuccessor = deleteNode; \/\/ roditelj nasljednika\n        Node&lt;T&gt; successor = deleteNode; \/\/ nasljednik\n        Node&lt;T&gt; current = successor.getRightChild(); \/\/ samo \"prolazni\" \u010dvor\n        while (current != null) {\n            parentSuccessor = successor;\n            successor = current;\n            current = current.getLeftChild();\n        }\n        \/\/ na izlazu iz petlje imamo nasljednika i roditelja nasljednika\n        if (successor != deleteNode.getRightChild()) { \/\/ ako nasljednik nije isti kao desni potomak uklonjenog \u010dvora\n            parentSuccessor.setLeftChild(successor.getRightChild()); \/\/ tada njegov roditelj preuzima potomka nasljednika, da ga ne izgubi\n            successor.setRightChild(deleteNode.getRightChild()); \/\/ povezujemo nasljednika s desnim potomkom uklonjenog \u010dvora\n        }\n        return successor;\n    }\n<\/code><\/pre>\n<p>\nPuni kod metode delete:<\/p>\n<pre><code class=\"java\">public boolean delete(int deleteKey) {\n        Node current = root;\n        Node parent = current;\n        boolean isLeftChild = false; \/\/ Ovisno o tome je li \u010dvor koji se uklanja lijevi ili desni potomak svog roditelja, booleanska varijabla isLeftChild \u0107e imati vrijednost true ili 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) { \/\/ prvi slu\u010daj\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) { \/\/ drugi slu\u010daj\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 { \/\/ tre\u0107i slu\u010daj\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>\nVrijednost slo\u017eenosti mo\u017ee se aproksimirati na O(log(n)).<\/p>\n<h3>Pronala\u017eenje maksimuma\/minimuma u stablu<\/h3>\n<p>\nO\u010digledno je da se minimalna\/maksimalna vrijednost u stablu mo\u017ee prona\u0107i slijednim prelaskom kroz lanac lijevih\/desnih elemenata stabla; kada stignete do lista, on \u0107e biti minimalni\/maksimalni 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>\nSlo\u017eenost \u2014 O(log(n))<\/p>\n<h3>Simetri\u010dno obilazak<\/h3>\n<p>\nObilazak \u2014 posjetiti svaki \u010dvor stabla s ciljem izvr\u0161enja neke radnje nad njim.<\/p>\n<p>Algoritam za rekurzivni simetri\u010dni obilazak:<\/p>\n<ol>\n<li>Izvr\u0161i radnju nad lijevim potomkom<\/li>\n<li>Izvr\u0161i radnju nad sobom<\/li>\n<li>Izvr\u0161i radnju nad desnim potomkom<\/li>\n<\/ol>\n<p>\nKod:<\/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() + \" \");\/\/ Ovdje mo\u017ee biti sve, \u0161to god\n            inOrder(current.getRightChild());\n        }\n    }\n<\/code><\/pre>\n<p><\/p>\n<h2>Zaklju\u010dak<\/h2>\n<p>\nNap finally! Ako sam ne\u0161to nedovoljno objasnio ili imate kakve komentare, \u010dekam vas u komentarima. Kao \u0161to sam obe\u0107ao, donosim puni kod.<\/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>Degeneracija do O(n)<\/h3>\n<p>\nMnogi od vas mogli su primijetiti: \u0161to ako napravimo da stablo postane nesmetano? Na primjer, stavljaju\u0107i u stablo \u010dvorove s rastu\u0107im klju\u010devima: 1,2,3,4,5,6\u2026 Tada \u0107e stablo vi\u0161e li\u010diti na povezanu listu. I da, stablo \u0107e izgubiti svoju drvenastu strukturu, a samim time i u\u010dinkovitost pristupa podacima. Slo\u017eenost operacija pretrage, umetanja i brisanja postat \u0107e kao kod povezane liste: O(n). U tome se o\u010dituje jedan od najva\u017enijih, po mom mi\u0161ljenju, nedostataka binarnih stabala.<\/p>\n<p class=\"for_users_only_msg\">Samo registrirani korisnici mogu sudjelovati u anketi. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/auth\/login\/\">Prijavite se<\/a><\/noindex>, molimo.<\/p>\n<h2 class=\"default-block__polling-title\">Nisam dugo na habru i volio bih znati o kojim temama biste \u017eeljeli vidjeti vi\u0161e \u010dlanaka?<\/h2>\n<ul class=\"content-list content-list_polling\">\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Strukture podataka<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Algoritmi (DP, rekurzija, kompresija podataka itd.)<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Primjena struktura podataka i algoritama u stvarnom \u017eivotu<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Programiranje Android aplikacija u Javi<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Programiranje web aplikacija u Javi<\/p>\n<\/li>\n<\/ul>\n<p>    Glasali su 2 korisnika. Suzdr\u017ean 1 korisnik.<br \/>\n<br \/>Izvor: 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.4 - 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\/hr\/blog\/administrirovanie\/binary-tree-ili-kak-prigotovit-binarnoe-derevo-poiska\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"hr_HR\" \/>\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\/hr\/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\udd47Binarno stablo ili kako pripremiti binarno stablo pretra\u017eivanja | ProHoster","description":"Predgovor Ovaj \u010dlanak posve\u0107en je binarnim stablima pretra\u017eivanja.","canonical_url":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/binary-tree-ili-kak-prigotovit-binarnoe-derevo-poiska","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"hr_HR","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\/hr\/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\/hr\/wp-json\/wp\/v2\/posts\/30530","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/comments?post=30530"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts\/30530\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media\/22528"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media?parent=30530"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/categories?post=30530"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/tags?post=30530"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}