{"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\/da\/blog\/administrirovanie\/binary-tree-ili-kak-prigotovit-binarnoe-derevo-poiska","title":{"rendered":"Bin\u00e6rt tr\u00e6 eller hvordan man laver et bin\u00e6rt s\u00f8getr\u00e6","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<h2>Pr\u00e6ludium<\/h2>\n<p>\nDenne artikel handler om bin\u00e6re s\u00f8getr\u00e6er. For nylig skrev jeg en artikel om <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/438512\/\">komprimering af data ved hj\u00e6lp af Huffman-metoden.<\/a><\/noindex> Der fokuserede jeg ikke meget p\u00e5 bin\u00e6re tr\u00e6er, da s\u00f8ge-, inds\u00e6tte- og slette-metoder ikke var relevante. Nu har jeg besluttet at skrive en artikel specifikt om tr\u00e6er. Lad os komme i gang. <\/p>\n<p>Et tr\u00e6 er en datastruktur, der best\u00e5r af noder der er forbundet med kanter. Man kan sige, at et tr\u00e6 er et s\u00e6rligt tilf\u00e6lde af en graf. Her er et eksempel p\u00e5 et tr\u00e6: <\/p>\n<p><img decoding=\"async\" alt=\"Bin\u00e6rt tr\u00e6 eller hvordan man laver et bin\u00e6rt s\u00f8getr\u00e6\" src=\"\/wp-content\/uploads\/2019\/03\/502ac27f1b93f926c68a68777f6bddd7.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDette er ikke et bin\u00e6rt s\u00f8getr\u00e6! Alt under katten!<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Terminologi<\/h2>\n<p><\/p>\n<h4>Rod<\/h4>\n<p>\n<i>Rod af tr\u00e6et<\/i> er den \u00f8verste node. I eksemplet er det node A. I et tr\u00e6 kan der kun v\u00e6re \u00e9n vej fra roden til enhver anden node! Faktisk kan enhver node betragtes som rod for det undertr\u00e6, der svarer til denne node.<\/p>\n<h4>For\u00e6ldre\/efterkommere<\/h4>\n<p>\nAlle noder, undtagen roden, har pr\u00e6cist \u00e9n kant, der g\u00e5r op til en anden node. Den node, der ligger over den aktuelle, kaldes <i>for\u00e6lder<\/i> denne node. Den node, der ligger under den aktuelle og er forbundet med den, kaldes <i>efterkommer<\/i> denne node. Lad os tage et eksempel. Tag node B, s\u00e5 er dens for\u00e6lder node A, og dens efterkommere er noderne D, E og F.<\/p>\n<h4>Blad<\/h4>\n<p>\nEn node, der ikke har nogen efterkommere, kaldes et blad i tr\u00e6et. I eksemplet vil bladene v\u00e6re noderne D, E, F, G, I, J, K.<\/p>\n<p>Dette er den grundl\u00e6ggende terminologi. Andre begreber vil blive gennemg\u00e5et senere. S\u00e5 et bin\u00e6rt tr\u00e6 er et tr\u00e6, hvor hver node har h\u00f8jst to efterkommere. Som du kan g\u00e6tte, vil tr\u00e6et fra eksemplet ikke v\u00e6re bin\u00e6rt, da noderne B og H har mere end to efterkommere. Her er et eksempel p\u00e5 et bin\u00e6rt tr\u00e6:<\/p>\n<p><img decoding=\"async\" alt=\"Bin\u00e6rt tr\u00e6 eller hvordan man laver et bin\u00e6rt s\u00f8getr\u00e6\" src=\"\/wp-content\/uploads\/2019\/03\/2f587bd1c428d3850cb0163d6c2984a1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nI noderne i tr\u00e6et kan der v\u00e6re enhver information. Et bin\u00e6rt s\u00f8getr\u00e6 er et bin\u00e6rt tr\u00e6, der har f\u00f8lgende egenskaber:<\/p>\n<ol>\n<li>Begge undertr\u00e6er - venstre og h\u00f8jre - er bin\u00e6re s\u00f8getr\u00e6er.<\/li>\n<li>Alle noder i venstre undertr\u00e6 af en vilk\u00e5rlig node X har datan\u00f8gler, der er mindre end datan\u00f8glen for node X selv.<\/li>\n<li>Alle noder i det h\u00f8jre undertr\u00e6 af en vilk\u00e5rlig node X har datan\u00f8gler, der er st\u00f8rre end eller lig med datan\u00f8glen for node X selv. <\/li>\n<\/ol>\n<p><i>N\u00f8gle<\/i> - en hvilken som helst egenskab af noden (for eksempel et nummer). N\u00f8glen er n\u00f8dvendig for at kunne finde elementet i tr\u00e6et, som denne n\u00f8gle svarer til. Eksempel p\u00e5 et bin\u00e6rt s\u00f8getr\u00e6:<\/p>\n<p><img decoding=\"async\" alt=\"Bin\u00e6rt tr\u00e6 eller hvordan man laver et bin\u00e6rt s\u00f8getr\u00e6\" src=\"\/wp-content\/uploads\/2019\/03\/a70ca7d2fdf289b5d1e14bdb4bc38b00.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h2>Pr\u00e6sentation af tr\u00e6et<\/h2>\n<p>\nI takt med at vi skrider frem, vil jeg give nogle (muligvis ufuldst\u00e6ndige) kodeeksempler for at forbedre din forst\u00e5else. Den fulde kode vil v\u00e6re i slutningen af artiklen. <\/p>\n<p>Tr\u00e6et best\u00e5r af noder. Struktur for en node:<\/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\/\/...andre metoder for noden\n}\n<\/code><\/pre>\n<p>\nHver node har to efterkommere (det er muligt, at efterkommerne leftChild og\/eller rightChild kan indeholde v\u00e6rdien null). Du har nok forst\u00e5et, at i dette tilf\u00e6lde er data \u2014 de data, der opbevares i noden; key \u2014 nodens n\u00f8gle.<\/p>\n<p>Vi har nu v\u00e6ret igennem noden, lad os tage fat p\u00e5 de relevante problemer omkring tr\u00e6er. Her og derefter vil jeg med ordet \"tr\u00e6\" henvise til konceptet om et bin\u00e6rt s\u00f8getr\u00e6. Strukturen for et bin\u00e6rt tr\u00e6:<\/p>\n<pre><code class=\"java\">public class BinaryTree&lt;T&gt; {\n     private Node&lt;T&gt; root;\n\n    \/\/metoder for tr\u00e6et\n}\n<\/code><\/pre>\n<p>Som klassefelt har vi kun brug for rodtr\u00e6et, da vi med metoderne getLeftChild() og getRightChild() kan n\u00e5 enhver node i tr\u00e6et.<\/p>\n<h2>Algoritmer i tr\u00e6et<\/h2>\n<p><\/p>\n<h3>S\u00f8gning<\/h3>\n<p>\nAntag, at du har et opbygget tr\u00e6. Hvordan finder man et element med n\u00f8glen key? Man skal bev\u00e6ge sig fra roden ned gennem tr\u00e6et og sammenligne v\u00e6rdien af key med n\u00f8glev\u00e6rdien i den aktuelle node: hvis key er mindre end n\u00f8glev\u00e6rdien i den aktuelle node, s\u00e5 g\u00e5 til den venstre efterkommer; hvis st\u00f8rre \u2014 til den h\u00f8jre; hvis n\u00f8glerne er ens \u2014 s\u00e5 er den \u00f8nskede node fundet! Den relevante kode er:<\/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>\nHvis current bliver lig med null, s\u00e5 betyder det, at vi er n\u00e5et til enden af tr\u00e6et (p\u00e5 det konceptuelle niveau befinder du dig et sted, der ikke eksisterer i tr\u00e6et \u2014 efterkommeren til et blad).<\/p>\n<p>Lad os se p\u00e5 effektiviteten af s\u00f8gealgoritmen i et balanceret tr\u00e6 (et tr\u00e6, hvor noderne er nogenlunde j\u00e6vnt fordelt). S\u00e5 vil effektiviteten af s\u00f8gningen v\u00e6re O(log(n)), hvor logaritmen er med base 2. Se: hvis der er n elementer i det balancerede tr\u00e6, betyder det, at der vil v\u00e6re log(n) niveauer i tr\u00e6et baseret p\u00e5 2. Og i s\u00f8gningen, for hvert skridt i r\u00e6kken, bev\u00e6ger du dig ned et niveau.<\/p>\n<h3>Inds\u00e6ttelse<\/h3>\n<p>\nHvis du har forst\u00e5et essensen af s\u00f8gningen, vil det ikke v\u00e6re sv\u00e6rt for dig at forst\u00e5 inds\u00e6ttelsen. Du skal bare bev\u00e6ge dig ned til bladet i tr\u00e6et (if\u00f8lge de nedstigende regler, der er beskrevet i s\u00f8gningen) og blive dens efterkommer \u2014 venstre eller h\u00f8jre, afh\u00e6ngigt af n\u00f8glev\u00e6rdien. Implementering:<\/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>\nI dette tilf\u00e6lde skal vi, udover den nuv\u00e6rende node, gemme oplysninger om for\u00e6lderen til den nuv\u00e6rende node. N\u00e5r current bliver lig med null, vil variablen parent indeholde det \u00f8nskede blad. <br \/>\nEffektiviteten af inds\u00e6ttelse vil \u00e5benlyst v\u00e6re den samme som for s\u00f8gning \u2014 O(log(n)).<\/p>\n<h3>Sletning<\/h3>\n<p>\nSletning er den mest komplekse operation, der skal udf\u00f8res med tr\u00e6et. Det er klart, at vi f\u00f8rst skal finde det element, vi \u00f8nsker at slette. Men hvad s\u00e5? Hvis vi blot tildeler dens reference v\u00e6rdien null, vil vi miste informationen om den undertr\u00e6, der har denne node som rod. Metoder til sletning af tr\u00e6er opdeles i tre tilf\u00e6lde.<\/p>\n<h4>F\u00f8rste tilf\u00e6lde. Den slettede node har ingen efterkommere.<\/h4>\n<p>\nHvis den slettede node ikke har nogen efterkommere, betyder det, at den er et blad. Derved kan vi blot s\u00e6tte venstre eller h\u00f8jre barn af dens for\u00e6lder til null. <\/p>\n<h4>Andet tilf\u00e6lde. Den slettede node har \u00e9n efterkommer.<\/h4>\n<p>\nDette tilf\u00e6lde er heller ikke s\u00e6rlig udfordrende. Lad os vende tilbage til vores eksempel. Antag, at vi skal slette elementet med n\u00f8gle 14. Enig, da det er en h\u00f8jre efterkommer af noden med n\u00f8gle 10, vil enhver af dens efterkommere (i dette tilf\u00e6lde h\u00f8jre) have en n\u00f8gle, der er st\u00f8rre end 10, og derfor kan vi let 'sk\u00e6re' det ud af tr\u00e6et, og for\u00e6lderen kan forbindes direkte med efterkommeren af den slettede node, dvs. noden med n\u00f8gle 10 kan forbindes med noden 13. En lignende situation ville v\u00e6re, hvis vi skulle slette en node, der er en venstre efterkommer af sin for\u00e6lder. T\u00e6nk selv over det \u2014 en n\u00f8jagtig analogi. <\/p>\n<h4>Tredje tilf\u00e6lde. Noden har to efterkommere.<\/h4>\n<p>\nDet mest komplekse tilf\u00e6lde. Lad os tage et nyt eksempel.<\/p>\n<p><img decoding=\"async\" alt=\"Bin\u00e6rt tr\u00e6 eller hvordan man laver et bin\u00e6rt s\u00f8getr\u00e6\" src=\"\/wp-content\/uploads\/2019\/03\/0d600478e4a046ae6f7267be49b231bc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h4>S\u00f8gning efter efterf\u00f8lger.<\/h4>\n<p>\n Lad os antage, at vi skal fjerne noden med n\u00f8gle 25. Hvem s\u00e6tter vi i dens sted? En af dens efterf\u00f8lgere (efterkommere eller efterkommere til efterkommere) skal blive <i>efterf\u00f8lgeren<\/i>(den, der skal overtage den fjernede nodes plads). <\/p>\n<p>Hvordan forst\u00e5r man, hvem der skal blive efterf\u00f8lger? Det er intuitivt klart, at det er en node i tr\u00e6et, hvis n\u00f8gle er den n\u00e6ste st\u00f8rste i forhold til den fjernede node. Algoritmen g\u00e5r som f\u00f8lger. Man skal g\u00e5 til dens h\u00f8jre efterkommer (altid til h\u00f8jre, da det allerede er sagt, at efterf\u00f8lgerens n\u00f8gle er st\u00f8rre end den fjernede nodes n\u00f8gle), og derefter bev\u00e6ge sig ned ad k\u00e6den af venstre efterkommere til denne h\u00f8jre efterkommer. I eksemplet skal vi g\u00e5 til noden med n\u00f8gle 35, og derefter bev\u00e6ge os ned til bladet langs k\u00e6den af dens venstre efterkommere \u2014 i dette tilf\u00e6lde best\u00e5r denne k\u00e6de kun af noden med n\u00f8gle 30. Strengt taget leder vi efter den mindste node i s\u00e6ttet af noder, der er st\u00f8rre end den \u00f8nskede node.<\/p>\n<p><img decoding=\"async\" alt=\"Bin\u00e6rt tr\u00e6 eller hvordan man laver et bin\u00e6rt s\u00f8getr\u00e6\" src=\"\/wp-content\/uploads\/2019\/03\/50c4e3e49111eec9e1fd13083ee9b9b0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nKoden til metoden til at finde efterf\u00f8lgeren:<\/p>\n<pre><code class=\"java\">    public Node&lt;T&gt; getSuccessor(Node&lt;T&gt; deleteNode) {\n        Node&lt;T&gt; parentSuccessor = deleteNode; \/\/ for\u00e6lder til efterf\u00f8lgeren\n        Node&lt;T&gt; successor = deleteNode; \/\/ efterf\u00f8lger\n        Node&lt;T&gt; current = successor.getRightChild(); \/\/ simpelthen en \"catching\" node\n        while (current != null) {\n            parentSuccessor = successor;\n            successor = current;\n            current = current.getLeftChild();\n        }\n        \/\/ n\u00e5r vi forlader loopet har vi efterf\u00f8lgeren og for\u00e6lderen til efterf\u00f8lgeren\n        if (successor != deleteNode.getRightChild()) { \/\/ hvis efterf\u00f8lgeren ikke stemmer overens med den h\u00f8jre efterkommer til den fjernede node\n            parentSuccessor.setLeftChild(successor.getRightChild()); \/\/ s\u00e5 overtager dens for\u00e6lder efterf\u00f8lgerens efterkommer, s\u00e5 de ikke mister den\n            successor.setRightChild(deleteNode.getRightChild()); \/\/ forbinder efterf\u00f8lgeren med den h\u00f8jre efterkommer til den fjernede node\n        }\n        return successor;\n    }\n<\/code><\/pre>\n<p>\nDen komplette kode til metoden delete:<\/p>\n<pre><code class=\"java\">public boolean delete(int deleteKey) {\n        Node current = root;\n        Node parent = current;\n        boolean isLeftChild = false; \/\/ Afh\u00e6ngigt af om den slettede node er venstre eller h\u00f8jre barn af sin for\u00e6lder, vil boolesk variabel isLeftChild v\u00e6re true eller false henholdsvis.\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) { \/\/ f\u00f8rste tilf\u00e6lde\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) { \/\/ andet tilf\u00e6lde\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 { \/\/ tredje tilf\u00e6lde\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>\nKompleksiteten kan tiln\u00e6rmes til O(log(n)).<\/p>\n<h3>S\u00f8gning efter maksimum\/minimum i tr\u00e6et<\/h3>\n<p>\nDet er \u00e5benlyst, hvordan man finder den mindste\/st\u00f8rste v\u00e6rdi i tr\u00e6et - man skal konsekvent bev\u00e6ge sig gennem k\u00e6den af venstre\/h\u00f8jre elementer i tr\u00e6et; n\u00e5r man n\u00e5r bladet, er det den mindste\/st\u00f8rste 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>\nKompleksiteten er O(log(n))<\/p>\n<h3>Symmetrisk gennemgang<\/h3>\n<p>\nGennemgang - at bes\u00f8ge hver node i tr\u00e6et for at udf\u00f8re en handling med den.<\/p>\n<p>Algoritmen for rekursiv symmetrisk gennemgang:<\/p>\n<ol>\n<li>Udf\u00f8r handling med venstre barn<\/li>\n<li>Udf\u00f8r handling med dig selv<\/li>\n<li>Udf\u00f8r handling med h\u00f8jre barn<\/li>\n<\/ol>\n<p>\nKode:<\/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() + \" \"); \/\/Her kan v\u00e6re hvad som helst\n            inOrder(current.getRightChild());\n        }\n    }\n<\/code><\/pre>\n<p><\/p>\n<h2>Konklusion<\/h2>\n<p>\nEndelig! Hvis jeg har uddybet noget for lidt, eller hvis der er kommentarer, ser jeg frem til at h\u00f8re dem. Som lovet, bringer jeg den fulde kode.<\/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>Hen til O(n)<\/h3>\n<p>\nMange af jer har m\u00e5ske bem\u00e6rket: hvad nu hvis vi g\u00f8r, s\u00e5 tr\u00e6et bliver ubalanceret? For eksempel ved at inds\u00e6tte noder i tr\u00e6et med stigende n\u00f8gler: 1,2,3,4,5,6\u2026 S\u00e5 vil tr\u00e6et minde om en k\u00e6deloop. Og ja, tr\u00e6et vil miste sin tr\u00e6-lignende struktur, og dermed ogs\u00e5 effektiviteten af datatilgang. Tidskompleksiteten for s\u00f8ge-, inds\u00e6tte- og sletteoperationer vil blive den samme som for en k\u00e6deloop: O(n). Dette er en af de vigtigste ulemper ved bin\u00e6re tr\u00e6er, efter min mening.<\/p>\n<p class=\"for_users_only_msg\">Kun registrerede brugere kan deltage i unders\u00f8gelsen. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/auth\/login\/\">Log ind<\/a><\/noindex>, please.<\/p>\n<h2 class=\"default-block__polling-title\">Jeg er ikke s\u00e5 l\u00e6nge siden p\u00e5 Habr, og jeg vil gerne vide, hvilke emner I gerne vil se flere artikler om?<\/h2>\n<ul class=\"content-list content-list_polling\">\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Datakonstruktioner<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Algoritmer (DP, rekursion, datakompression osv.)<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Anvendelse af datakonstruktioner og algoritmer i det virkelige liv<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Programmering af Android-applikationer i Java<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Programmering af webapplikationer i Java<\/p>\n<\/li>\n<\/ul>\n<p>    2 brugere har stemt. 1 bruger har afholdt sig.<br \/>\n<br \/>Kilde: 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.3 - 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\/da\/blog\/administrirovanie\/binary-tree-ili-kak-prigotovit-binarnoe-derevo-poiska\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"da_DK\" \/>\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\/da\/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 eller hvordan man laver et bin\u00e6rt s\u00f8getr\u00e6 | ProHoster","description":"Pr\u00e6ludium Denne artikel er dedikeret til bin\u00e6re s\u00f8getr\u00e6er.","canonical_url":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/binary-tree-ili-kak-prigotovit-binarnoe-derevo-poiska","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"da_DK","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\/da\/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\/da\/wp-json\/wp\/v2\/posts\/30530","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/comments?post=30530"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/30530\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media\/22528"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media?parent=30530"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/categories?post=30530"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/tags?post=30530"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}