{"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\/nl\/blog\/administrirovanie\/binary-tree-ili-kak-prigotovit-binarnoe-derevo-poiska","title":{"rendered":"Binaire Boom of hoe een binaire zoekboom te maken","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<h2>Prelude<\/h2>\n<p>\nDit artikel is gewijd aan binaire zoekbomen. Onlangs heb ik een artikel geschreven over <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/438512\/\">gegevenscompressie met de Huffman-methode.<\/a><\/noindex> Daarin keek ik niet echt naar binaire bomen, omdat zoek-, invoeg- en verwijdermethoden niet relevant waren. Nu heb ik besloten een artikel specifiek over bomen te schrijven. Laten we beginnen. <\/p>\n<p>Een boom is een datastructuur die bestaat uit knooppunten die met ribben verbonden zijn. Je kunt zeggen dat een boom een bijzondere vorm van een graaf is. Hier is een voorbeeld van een boom: <\/p>\n<p><img decoding=\"async\" alt=\"Binaire Boom of hoe een binaire zoekboom te maken\" src=\"\/wp-content\/uploads\/2019\/03\/502ac27f1b93f926c68a68777f6bddd7.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDit is geen binaire zoekboom! Alles onder de kat!<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Terminologie<\/h2>\n<p><\/p>\n<h4>Wortel<\/h4>\n<p>\n<i>De wortel van de boom<\/i> is de bovenste knoop ervan. In het voorbeeld is dat knoop A. In de boom kan er vanaf de wortel naar elke andere knoop slechts \u00e9\u00e9n pad leiden! In feite kan elke knoop worden beschouwd als de wortel van het bijbehorende subboom.<\/p>\n<h4>Ouders\/nakomes<\/h4>\n<p>\nAlle knopen, behalve de wortel, hebben precies \u00e9\u00e9n rib die omhoog leidt naar een andere knoop. De knoop die boven de huidige is, wordt genoemd <i>ouder<\/i> van deze knoop. De knoop die zich onder de huidige bevindt en ermee is verbonden, wordt genoemd <i>nakomeling<\/i> van deze knoop. Laten we een voorbeeld nemen. Neem knoop B, dan is zijn ouder knoop A, en zijn nakomelingen zijn de knopen D, E en F.<\/p>\n<h4>Blad<\/h4>\n<p>\nEen knoop zonder nakomelingen wordt een blad van de boom genoemd. In het voorbeeld zijn de bladeren de knopen D, E, F, G, I, J, K.<\/p>\n<p>Dit is de basisterminologie. Andere concepten zullen later worden besproken. Dus, een binaire boom is een boom waarin elke knoop niet meer dan twee nakomelingen heeft. Zoals je al had vermoed, zal de boom uit het voorbeeld geen binaire zijn, omdat de knopen B en H meer dan twee nakomelingen hebben. Hier is een voorbeeld van een binaire boom:<\/p>\n<p><img decoding=\"async\" alt=\"Binaire Boom of hoe een binaire zoekboom te maken\" src=\"\/wp-content\/uploads\/2019\/03\/2f587bd1c428d3850cb0163d6c2984a1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn de knopen van de boom kan elke informatie zijn. Een binaire zoekboom is een binaire boom met de volgende eigenschappen:<\/p>\n<ol>\n<li>Beide subbomen \u2013 het linker en het rechter \u2013 zijn binaire zoekbomen.<\/li>\n<li>Alle knopen van de linker subboom van een willekeurige knoop X hebben datumsleutelwaarden die kleiner zijn dan de waarde van de datumsleutel van knoop X zelf.<\/li>\n<li>Alle knopen van de rechter subboom van een willekeurige knoop X hebben datumsleutelwaarden die groter of gelijk zijn aan de waarde van de datumsleutel van knoop X zelf. <\/li>\n<\/ol>\n<p><i>Sleutel<\/i> is een eigenschap van een knoop (bijvoorbeeld een nummer). De sleutel is nodig om het element van de boom te vinden dat bij deze sleutel hoort. Voorbeeld van een binaire zoekboom:<\/p>\n<p><img decoding=\"async\" alt=\"Binaire Boom of hoe een binaire zoekboom te maken\" src=\"\/wp-content\/uploads\/2019\/03\/a70ca7d2fdf289b5d1e14bdb4bc38b00.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h2>De presentatie van de boom<\/h2>\n<p>\nNaarmate we vorderen, zal ik enkele (mogelijk onvolledige) stukjes code geven om uw begrip te verbeteren. De volledige code zal aan het einde van het artikel zijn. <\/p>\n<p>Een boom bestaat uit knooppunten. De structuur van een knooppunt:<\/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\/\/... andere methoden van de knoop\n}\n<\/code><\/pre>\n<p>\nElke knoop heeft twee kinderen (het is goed mogelijk dat de kinderen leftChild en\/of rightChild een null-waarde hebben). U hebt waarschijnlijk begrepen dat data hier de gegevens zijn die in de knoop worden opgeslagen; key is de sleutel van de knoop.<\/p>\n<p>Nu we de knoop hebben besproken, laten we het hebben over de actuele problemen met bomen. Hier en verder zal ik met 'boom' verwijzen naar het concept van een binaire zoekboom. De structuur van een binaire boom:<\/p>\n<pre><code class=\"java\">public class BinaryTree&lt;T&gt; {\n     private Node&lt;T&gt; root;\n\n    \/\/ methoden van de boom\n}\n<\/code><\/pre>\n<p>Als klasseveld hebben we alleen de wortel van de boom nodig, omdat we vanaf de wortel met de methoden getLeftChild() en getRightChild() elk knooppunt in de boom kunnen bereiken.<\/p>\n<h2>Algoritmen in de boom<\/h2>\n<p><\/p>\n<h3>Zoeken<\/h3>\n<p>\nLaten we aannemen dat u een boom heeft gebouwd. Hoe vindt u een element met de sleutel key? U moet van de wortel naar beneden door de boom bewegen en de waarde key vergelijken met de sleutel van het huidige knooppunt: als key kleiner is dan de sleutel van het huidige knooppunt, ga dan naar het linkerkind van de knoop, als het groter is, ga dan naar het rechterkind, als de sleutels gelijk zijn \u2014 het gezochte knooppunt is gevonden! De bijbehorende code:<\/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>\nAls current gelijk wordt aan null, betekent dit dat de doorlooptijd het einde van de boom heeft bereikt (op conceptueel niveau bevindt u zich op een niet-bestaande plaats in de boom \u2014 het kind van een blad).<\/p>\n<p>Laten we de effici\u00ebntie van het zoekalgoritme in een gebalanceerde boom bekijken (een boom waarin de knopen meer of minder gelijkmatig zijn verdeeld). In dat geval zal de effici\u00ebntie van het zoeken O(log(n)) zijn, met een logaritme met basis 2. Kijk: als er n elementen in de gebalanceerde boom zijn, betekent dit dat er log(n) met basis 2 niveaus van de boom zullen zijn. En bij het zoeken daalt u met \u00e9\u00e9n stap in de lus naar \u00e9\u00e9n niveau.<\/p>\n<h3>Invoegen<\/h3>\n<p>\nAls je de essentie van het zoeken begrijpt, zal het je geen moeite kosten om de invoeging te begrijpen. Je moet gewoon naar het blad van de boom (volgens de afdaalregels die in het zoeken zijn beschreven) en een nakomeling ervan worden \u2014 links of rechts, afhankelijk van de sleutel. Implementatie:<\/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>\nIn dit geval moet je, naast de huidige knoop, informatie opslaan over de ouder van de huidige knoop. Wanneer current null wordt, bevat de variabele parent de benodigde blad. <br \/>\nDe effici\u00ebntie van de invoeging zal vanzelfsprekend hetzelfde zijn als die van het zoeken \u2014 O(log(n)).<\/p>\n<h3>Verwijderen<\/h3>\n<p>\nVerwijderen is de meest complexe operatie die met de boom moet worden uitgevoerd. Het is duidelijk dat we eerst het element moeten vinden dat we willen verwijderen. Maar wat dan? Als we gewoon de referentie null toewijzen, verliezen we de informatie over het onderboompje waarvan deze knoop de wortel is. Verwijdermethoden worden in drie gevallen verdeeld.<\/p>\n<h4>Eerste geval. De te verwijderen knoop heeft geen nakomelingen.<\/h4>\n<p>\nAls de te verwijderen knoop geen nakomelingen heeft, betekent dit dat hij een blad is. Dus, we kunnen gewoon de velden leftChild of rightChild van de ouder null toewijzen. <\/p>\n<h4>Tweede geval. De te verwijderen knoop heeft \u00e9\u00e9n nakomeling.<\/h4>\n<p>\nDit geval is ook niet al te moeilijk. Laten we terugkeren naar ons voorbeeld. Stel dat we het element met sleutel 14 moeten verwijderen. Je zult het ermee eens zijn dat, aangezien het een rechter nakomeling is van de knoop met sleutel 10, elk van zijn nakomelingen (in dit geval de rechter) een sleutel zal hebben die groter is dan 10, dus we kunnen het gemakkelijk 'uitknippen' uit de boom, en de ouder rechtstreeks verbinden met de nakomeling van de te verwijderen knoop, d.w.z., de knoop met sleutel 10 verbinden met de knoop 13. De situatie zou vergelijkbaar zijn als we een knoop zouden moeten verwijderen die de linker nakomeling van zijn ouder is. Denk hier zelf maar over na \u2014 het is een exacte analogie. <\/p>\n<h4>Derde geval. De knoop heeft twee nakomelingen.<\/h4>\n<p>\nHet meest complexe geval. Laten we het met een nieuw voorbeeld uitleggen.<\/p>\n<p><img decoding=\"async\" alt=\"Binaire Boom of hoe een binaire zoekboom te maken\" src=\"\/wp-content\/uploads\/2019\/03\/0d600478e4a046ae6f7267be49b231bc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h4>Zoeken van de opvolger<\/h4>\n<p>\n Stel dat we een knoop met sleutel 25 moeten verwijderen. Wie stellen we op zijn plaats? Iemand uit zijn opvolgers (afstammelingen of afstammelingen van afstammelingen) moet de <i>opvolger<\/i>(degene die de plaats van de verwijderde knoop zal innemen). <\/p>\n<p>Hoe begrijp je wie de opvolger moet worden? Intu\u00eftief is het duidelijk dat dit een knoop in de boom is, waarvan de sleutel de volgende grootste is na de verwijderde knoop. Het algoritme is als volgt. We moeten naar zijn rechterafstammeling gaan (altijd naar rechts, want het is al gezegd dat de sleutel van de opvolger groter is dan de sleutel van de verwijderde knoop), en vervolgens de keten van linkerafstammelingen van deze rechterafstammeling doorlopen. In ons voorbeeld moeten we naar de knoop met sleutel 35 gaan en daarna naar beneden gaan naar het blad in de keten van zijn linkerafstammelingen \u2014 in dit geval bestaat deze keten alleen uit de knoop met sleutel 30. Strikt genomen zoeken we de kleinste knoop in de set van knopen die groter zijn dan de gezochte knoop.<\/p>\n<p><img decoding=\"async\" alt=\"Binaire Boom of hoe een binaire zoekboom te maken\" src=\"\/wp-content\/uploads\/2019\/03\/50c4e3e49111eec9e1fd13083ee9b9b0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCode van de methode om de opvolger te vinden:<\/p>\n<pre><code class=\"java\">    public Node&lt;T&gt; getSuccessor(Node&lt;T&gt; deleteNode) {\n        Node&lt;T&gt; parentSuccessor = deleteNode; \/\/ ouder van de opvolger\n        Node&lt;T&gt; successor = deleteNode; \/\/ opvolger\n        Node&lt;T&gt; current = successor.getRightChild(); \/\/ gewoon een \"huidige\" knoop\n        while (current != null) {\n            parentSuccessor = successor;\n            successor = current;\n            current = current.getLeftChild();\n        }\n        \/\/ bij het verlaten van de lus hebben we de opvolger en de ouder van de opvolger\n        if (successor != deleteNode.getRightChild()) { \/\/ als de opvolger niet overeenkomt met de rechterafstammeling van de verwijderde knoop\n            parentSuccessor.setLeftChild(successor.getRightChild()); \/\/ dan neemt de ouder de afstammeling van de opvolger over om deze niet te verliezen\n            successor.setRightChild(deleteNode.getRightChild()); \/\/ verbinden de opvolger met de rechterafstammeling van de verwijderde knoop\n        }\n        return successor;\n    }\n<\/code><\/pre>\n<p>\nVolledige code van de delete-methode:<\/p>\n<pre><code class=\"java\">public boolean delete(int deleteKey) {\n        Node current = root;\n        Node parent = current;\n        boolean isLeftChild = false; \/\/ Afhankelijk van of de te verwijderen knoop een linkerkind of rechterkind van zijn ouder is, zal de boolean variabele isLeftChild respectievelijk true of false zijn.\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) { \/\/ eerste geval\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) { \/\/ tweede geval\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 { \/\/ derde geval\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>\nDe complexiteit kan worden benaderd als O(log(n)).<\/p>\n<h3>Zoeken naar de maximum\/minimum in een boom<\/h3>\n<p>\nOverduidelijk, om de minimale\/maximale waarde in de boom te vinden - moet je respectievelijk door de keten van linkerkinderen\/rechterkinderen van de boom gaan; wanneer je bij een blad komt, is dit het minimale\/maximale 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>\nComplexiteit - O(log(n))<\/p>\n<h3>Symmetrische traversie<\/h3>\n<p>\nTraversie - elke knoop in de boom bezoeken met als doel er een bepaalde actie mee uit te voeren.<\/p>\n<p>Algoritme voor recursieve symmetrische traversie:<\/p>\n<ol>\n<li>Voer een actie uit met het linkerkind<\/li>\n<li>Voer een actie uit met jezelf<\/li>\n<li>Voer een actie uit met het rechterkind<\/li>\n<\/ol>\n<p>\nCode:<\/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() + \" \");\/\/ Hier kan alles zijn\n            inOrder(current.getRightChild());\n        }\n    }\n<\/code><\/pre>\n<p><\/p>\n<h2>Conclusie<\/h2>\n<p>\nEindelijk! Als ik iets niet goed heb uitgelegd of als er opmerkingen zijn, hoor ik het graag in de reacties. Zoals beloofd, hierbij de volledige code.<\/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>Verlies tot O(n)<\/h3>\n<p>\nVelen van jullie hebben misschien opgemerkt: wat als we het zo maken dat de boom ongebalanceerd wordt? Bijvoorbeeld door knopen met oplopende sleutels in de boom te plaatsen: 1,2,3,4,5,6\u2026 Dan zal de boom iets gaan lijken op een gelinkte lijst. En ja, de boom zal zijn boommachtige structuur verliezen, en dus ook de effici\u00ebntie van gegevensaccess. De complexiteit van zoek-, insertie- en verwijderbewerkingen wordt zoals die van een gelinkte lijst: O(n). Dit is een van de belangrijkste nadelen van binaire bomen, naar mijn mening.<\/p>\n<p class=\"for_users_only_msg\">Alleen geregistreerde gebruikers kunnen deelnemen aan de enqu\u00eate. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/auth\/login\/\">Log in<\/a><\/noindex>, alstublieft.<\/p>\n<h2 class=\"default-block__polling-title\">Ik ben niet zo lang geleden op Habr gekomen, en ik wil graag weten, over welke onderwerpen zouden jullie meer artikelen willen zien?<\/h2>\n<ul class=\"content-list content-list_polling\">\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Gegevensstructuren<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Algoritmen (Dynamisch programmeren, recursie, gegevenscompressie, enz.)<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Toepassing van gegevensstructuren en algoritmen in het echte leven<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Programmeren van Android-applicaties in Java<\/p>\n<\/li>\n<li class=\"content-list__item content-list__item_polling\">\n<p>                    Programmeren van webapplicaties in Java<\/p>\n<\/li>\n<\/ul>\n<p>    2 gebruikers hebben gestemd. 1 gebruiker heeft zich onthouden.<br \/>\n<br \/>Bron: 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\/nl\/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=\"nl_NL\" \/>\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\/nl\/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 of hoe een binaire zoekboom te maken | ProHoster","description":"Prelude Dit artikel is gewijd aan binaire zoekbomen.","canonical_url":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/binary-tree-ili-kak-prigotovit-binarnoe-derevo-poiska","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"nl_NL","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\/nl\/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\/nl\/wp-json\/wp\/v2\/posts\/30530","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/comments?post=30530"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts\/30530\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/media\/22528"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/media?parent=30530"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/categories?post=30530"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/tags?post=30530"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}