Binary Tree ko yadda ake shirya bishiyar bincike na binary

Wasan Tsokaci

Wannan labarin yana game da bishiyoyin bincike na binary. Kwanan nan na rubuta labarin game da matsawar bayanai ta hanyar Huffman. A can ban kula da bishiyoyin binary ba, saboda hanyoyin bincike, sakawa, sharewa ba su dace ba. Yanzu na yanke shawarar rubuta labarin game da bishiyoyi. Wataƙila za mu fara.

Itace tsarin bayanai ne wanda ya ƙunshi nodes da aka haɗa ta gefuna. Za mu iya cewa itace wani lamari ne na musamman na jadawali. Ga bishiyar misali:

Binary Tree ko yadda ake shirya bishiyar bincike na binary

Wannan ba bishiyar bincike ba ce! Komai yana ƙarƙashin yanke!

Terminology

Tushen

Tushen itace shine mafi girman kumburi. A cikin misali, wannan kumburin A. A cikin bishiyar, hanya ɗaya kawai zata iya kaiwa daga tushen zuwa kowane kumburi! A haƙiƙa, kowane kumburi za a iya la'akari da shi azaman tushen bishiyar da ke daidai da wannan kumburin.

Iyaye/ zuriya

Duk nodes ban da tushen suna da daidai gefen gefe ɗaya wanda zai kai ga wani kumburi. Ana kiran kumburin da ke sama da kumburin yanzu iyaye wannan kumburin. Ana kiran kumburin da ke ƙasa da na yanzu kuma an haɗa shi da shi zuriya wannan kumburin. Bari mu dauki misali. Ɗauki kumburin B, sannan iyayensa za su zama kumburin A, yaran kuma za su zama nodes D, E, da F.

Leaf

Kullin da ba shi da yara ana kiransa ganyen bishiyar. A cikin misali, nodes D, E, F, G, I, J, K za su zama ganye.

Wannan shi ne ainihin kalmomin kalmomi. Wasu ra'ayoyi za a tattauna daga baya. Don haka, bishiyar binaryar itace itace wacce kowace kumburi ba zata sami yara sama da biyu ba. Kamar yadda kuka yi tsammani, itacen daga misalin ba zai zama binary ba, saboda nodes B da H suna da yara fiye da biyu. Ga misalin bishiyar binaryar:

Binary Tree ko yadda ake shirya bishiyar bincike na binary

Nodes na bishiyar na iya ƙunsar kowane bayani. Bishiyar neman binaryar itace bishiyar binaryar da ke da abubuwa masu zuwa:

  1. Bishiyoyi na hagu da dama biyu bishiyar bincike ne.
  2. Duk nodes na gefen hagu na kumburin sabani X suna da ƙimar maɓalli na bayanai ƙasa da ƙimar maɓallin bayanan kumburin X kanta.
  3. Duk nodes na gefen dama na kumburin sabani X suna da ƙimar maɓalli na bayanai mafi girma ko daidai da ƙimar maɓallin bayanan kumburin X kanta.

Key - wasu halaye na kumburi (misali, lamba). Ana buƙatar maɓallin don samun damar gano nau'in itacen da wannan maɓalli ya dace da shi. Misalin bishiyar binciken binaryar:

Binary Tree ko yadda ake shirya bishiyar bincike na binary

kallon itace

Yayin da nake tafiya, zan haɗa wasu (wataƙila ba cikakke) na lamba don inganta fahimtar ku. Cikakken lambar zai kasance a ƙarshen labarin.

Itacen yana kunshe da nodes. Tsarin kumburi:

public class Node<T> {
    private T data;
    private int key;
    private Node<T> leftChild;
    private Node<T> rightChild;

    public Node(T data, int key) {
        this.data = data;
        this.key = key;
    }
    public Node<T> getLeftChild() {
        return leftChild;
    }

    public Node<T> getRightChild() {
        return rightChild;
    }
//...остальные методы узла
}

Kowane kumburi yana da ƴaƴa guda biyu (yana yiwuwa Yaran na hagu da/ko na dama Yara ba su da tushe). Wataƙila kun fahimci cewa a cikin wannan yanayin bayanan lamba shine bayanan da aka adana a cikin kumburi; key - node key.

Mun gano kullin, yanzu bari muyi magana game da matsalolin matsalolin bishiyoyi. Daga baya, kalmar "itace" za ta zama ma'anar bishiyar bincike ta binary. Tsarin bishiyar binaryar:

public class BinaryTree<T> {
     private Node<T> root;

    //методы дерева
}

A matsayin filin aji, tushen bishiyar kawai muke buƙata, saboda daga tushen, ta amfani da hanyoyin getLeftChild () da kuma samunRightChild (), zaku iya zuwa kowane kumburin bishiyar.

Algorithms Tree

Поиск

A ce kana da itace da aka gina. Yadda ake nemo kashi tare da maɓalli? Kuna buƙatar matsawa a jere daga tushen bishiyar kuma kwatanta ƙimar maɓalli tare da maɓallin kumburi na gaba: idan maɓalli ya kasa da maɓallin kumburi na gaba, to je zuwa zuriyar hagu na kumburi, idan ƙari - zuwa dama, idan maɓallan suna daidai - an sami kumburin da ake so! Lambar da ta dace:

public Node<T> find(int key) {
    Node<T> current = root;
    while (current.getKey() != key) {
        if (key < current.getKey())
            current = current.getLeftChild();
        else
            current = current.getRightChild();
        if (current == null)
            return null;
    }
    return current;
}

Idan halin yanzu ya zama mara amfani, to, haɓakawa ya kai ƙarshen bishiyar (a matakin tunani, kuna cikin wurin da ba a wanzu a cikin bishiyar - ɗan ganye).

Yi la'akari da ingancin algorithm na bincike akan bishiyar ma'auni (itacen da ake rarraba nodes fiye ko žasa daidai). Sannan ingantaccen bincike zai zama O (log(n)), da kuma tushen logarithm 2. Duba: idan akwai abubuwan da ke cikin madaidaicin bishiyar, to wannan yana nufin cewa za a sami matakan log(n) tushe 2 na bishiyar. Kuma a cikin binciken, don mataki ɗaya na zagayowar, kun gangara matakin ɗaya.

saka

Idan kun fahimci ainihin binciken, to ba zai yi muku wuya ku fahimci abin da aka shigar ba. Kuna buƙatar kawai zuwa ga ganyen itacen (bisa ga ka'idodin zuriyar da aka bayyana a cikin binciken) kuma ku zama zuriyarsa - hagu ko dama, dangane da maɓallin. Aiwatarwa:

   public void insert(T insertData, int key) {
        Node<T> current = root;
        Node<T> parent;
        Node<T> newNode = new Node<>(insertData, key);
        if (root == null)
            root = newNode;
        else {
            while (true) {
                parent = current;
                if (key < current.getKey()) {
                    current = current.getLeftChild();
                    if (current == null) {
                         parent.setLeftChild(newNode);
                         return;
                    }
                }
                else {
                    current = current.getRightChild();
                    if (current == null) {
                        parent.setRightChild(newNode);
                        return;
                    }
                }
            }
        }
    }

A wannan yanayin, ban da kumburi na yanzu, yana da mahimmanci don adana bayanai game da iyayen kundi na yanzu. Lokacin da halin yanzu ya zama mara amfani, canjin iyaye zai ƙunshi takardar da muke buƙata.
Ƙarfin shigar da ƙara zai kasance daidai da na binciken - O(log(n)).

Share

Share shine aiki mafi rikitarwa wanda zai buƙaci a yi da itace. A bayyane yake cewa da farko zai zama dole a nemo sinadarin da za mu cire. Amma sai me? Idan kawai muka saita zancensa zuwa banza, to za mu rasa bayani game da itacen da tushensa shine wannan kumburi. Hanyoyin kawar da itace sun kasu kashi uku.

Harka ta farko. Kullin da za a cire ba shi da yara.

Idan kullin da za a goge ba shi da yara, yana nufin cewa ganye ne. Don haka, zaku iya kawai saita filayen Hagu ko na dama na iyayensu zuwa banza.

Harka ta biyu. Kullin da za a cire yana da ɗa ɗaya

Wannan shari'ar kuma ba ta da wahala sosai. Mu koma ga misalinmu. A ce muna buƙatar share wani abu tare da maɓalli 14. Yarda da cewa tun da shi ne daidai yaron node tare da maɓalli 10, to, kowane zuriyarsa (a cikin wannan yanayin, wanda ya dace) zai sami maɓalli fiye da 10, don haka ku zai iya “yanke” cikin sauƙi daga bishiyar, kuma ya haɗa iyaye kai tsaye da ɗan kullin da ake sharewa, watau. haɗa kullin tare da maɓalli 10 zuwa kumburi 13. Yanayin zai kasance iri ɗaya idan mun share kumburi wanda shine ɗan hagu na iyayensa. Ka yi tunani game da shi da kanka - ainihin kwatanci.

Harka ta uku. Node yana da yara biyu

Harka mafi wahala. Bari mu kalli sabon misali.

Binary Tree ko yadda ake shirya bishiyar bincike na binary

Nemo magaji

Bari mu ce muna buƙatar cire kumburi tare da maɓalli 25. Wanene za mu saka a wurinsa? Daya daga cikin mabiyansa (zuriyarsa ko zuriyarsa) dole ne ya zama magaji(wanda zai dauki wurin kumburin da aka cire).

Ta yaya aka san wanda ya kamata ya zama magaji? A hankali, wannan shine kumburin bishiyar wanda maɓalli shine mafi girma na gaba daga kumburin da ake cirewa. Algorithm shine kamar haka. Kuna buƙatar zuwa wurin ɗanta na dama (ko da yaushe zuwa dama, saboda an riga an faɗi cewa maɓalli na magaji ya fi maɓalli na kullin da ake sharewa), sannan ku shiga cikin jerin 'ya'yan hagu na wannan dama. yaro. A cikin misali, dole ne mu je kullin tare da maɓalli 35, sa'an nan kuma mu gangara sarkar 'ya'yanta na hagu zuwa ga ganye - a wannan yanayin, wannan sarkar ta ƙunshi kawai kumburi tare da maɓalli 30. Magana mai mahimmanci, muna nema. ƙaramin kumburi a cikin saitin nodes mafi girma fiye da kumburin da ake so.

Binary Tree ko yadda ake shirya bishiyar bincike na binary

Lambar hanyar neman magaji:

    public Node<T> getSuccessor(Node<T> deleteNode) {
        Node<T> parentSuccessor = deleteNode;//родитель преемника
        Node<T> successor = deleteNode;//преемник
        Node<T> current = successor.getRightChild();//просто "пробегающий" узел
        while (current != null) {
            parentSuccessor = successor;
            successor = current;
            current = current.getLeftChild();
        }
        //на выходе из цикла имеем преемника и родителя преемника
        if (successor != deleteNode.getRightChild()) {//если преемник не совпадает с правым потомком удаляемого узла
            parentSuccessor.setLeftChild(successor.getRightChild());//то его родитель забирает себе потомка преемника, чтобы не потерять его
            successor.setRightChild(deleteNode.getRightChild());//связываем преемника с правым потомком удаляемого узла
        }
        return successor;
    }

Cikakken lambar hanyar sharewa:

public boolean delete(int deleteKey) {
        Node<T> current = root;
        Node<T> parent = current;
        boolean isLeftChild = false;//В зависимости от того, является ли  удаляемый узел левым или правым потомком своего родителя, булевская переменная isLeftChild будет принимать значение true или false соответственно.
        while (current.getKey() != deleteKey) {
            parent = current;
            if (deleteKey < current.getKey()) {
                current = current.getLeftChild();
                isLeftChild = true;
            } else {
                isLeftChild = false;
                current = current.getRightChild();
            }
            if (current == null)
                return false;
        }

        if (current.getLeftChild() == null && current.getRightChild() == null) {//первый случай
            if (current == root)
                current = null;
            else if (isLeftChild)
                parent.setLeftChild(null);
            else
                parent.setRightChild(null);
        }
        else if (current.getRightChild() == null) {//второй случай
            if (current == root)
                root = current.getLeftChild();
            else if (isLeftChild)
                parent.setLeftChild(current.getLeftChild());
            else
                current.setRightChild(current.getLeftChild());
        } else if (current.getLeftChild() == null) {
            if (current == root)
                root = current.getRightChild();
            else if (isLeftChild)
                parent.setLeftChild(current.getRightChild());
            else
                parent.setRightChild(current.getRightChild());
        } 
        else {//третий случай
            Node<T> successor = getSuccessor(current);
            if (current == root)
                root = successor;
            else if (isLeftChild)
                parent.setLeftChild(successor);
            else
                parent.setRightChild(successor);
        }
        return true;
    }

Za a iya kusantar da hadaddun zuwa O(log(n)).

Nemo mafi girma/mafi ƙarancin a itace

Babu shakka, yadda za a sami mafi ƙanƙanta / matsakaicin darajar a cikin bishiyar - kuna buƙatar bi ta hanyar jerin abubuwan hagu / dama na bishiyar, bi da bi; lokacin da kuka isa ga ganyen, zai zama mafi ƙanƙanta/mafi girman kashi.

    public Node<T> getMinimum(Node<T> startPoint) {
        Node<T> current = startPoint;
        Node<T> parent = current;
        while (current != null) {
            parent = current;
            current = current.getLeftChild();
        }
        return parent;
    }

    public Node<T> getMaximum(Node<T> startPoint) {
        Node<T> current = startPoint;
        Node<T> parent = current;
        while (current != null) {
            parent = current;
            current = current.getRightChild();
        }
        return parent;
    }

Complexity - O(log(n))

Ƙimar Simmetric

Traversal ziyara ce zuwa kowane kumburin bishiyar domin yin wani abu da ita.

Algorithm na jujjuyawar simmetric:

  1. Yi wani mataki akan yaron hagu
  2. Yi mataki da kanku
  3. Yi mataki akan yaron da ya dace

Lambar:

    public void inOrder(Node<T> current) {
        if (current != null) {
            inOrder(current.getLeftChild());
            System.out.println(current.getData() + " ");//Здесь может быть все, что угодно
            inOrder(current.getRightChild());
        }
    }

ƙarshe

A ƙarshe! Idan ban bayyana wani abu ba ko da wani sharhi, to ina jira a cikin sharhin. Kamar yadda aka yi alkawari, ga cikakken lambar.

Node.java:

public class Node<T> {
    private T data;
    private int key;
    private Node<T> leftChild;
    private Node<T> rightChild;

    public Node(T data, int key) {
        this.data = data;
        this.key = key;
    }

    public void setLeftChild(Node<T> newNode) {
        leftChild = newNode;
    }

    public void setRightChild(Node<T> newNode) {
        rightChild = newNode;
    }

    public Node<T> getLeftChild() {
        return leftChild;
    }

    public Node<T> getRightChild() {
        return rightChild;
    }

    public T getData() {
        return data;
    }

    public int getKey() {
        return key;
    }
}

BinaryTree.java:

public class BinaryTree<T> {
    private Node<T> root;

    public Node<T> find(int key) {
        Node<T> current = root;
        while (current.getKey() != key) {
            if (key < current.getKey())
                current = current.getLeftChild();
            else
                current = current.getRightChild();
            if (current == null)
                return null;
        }
        return current;
    }

    public void insert(T insertData, int key) {
        Node<T> current = root;
        Node<T> parent;
        Node<T> newNode = new Node<>(insertData, key);
        if (root == null)
            root = newNode;
        else {
            while (true) {
                parent = current;
                if (key < current.getKey()) {
                    current = current.getLeftChild();
                    if (current == null) {
                         parent.setLeftChild(newNode);
                         return;
                    }
                }
                else {
                    current = current.getRightChild();
                    if (current == null) {
                        parent.setRightChild(newNode);
                        return;
                    }
                }
            }
        }
    }

    public Node<T> getMinimum(Node<T> startPoint) {
        Node<T> current = startPoint;
        Node<T> parent = current;
        while (current != null) {
            parent = current;
            current = current.getLeftChild();
        }
        return parent;
    }

    public Node<T> getMaximum(Node<T> startPoint) {
        Node<T> current = startPoint;
        Node<T> parent = current;
        while (current != null) {
            parent = current;
            current = current.getRightChild();
        }
        return parent;
    }

    public Node<T> getSuccessor(Node<T> deleteNode) {
        Node<T> parentSuccessor = deleteNode;
        Node<T> successor = deleteNode;
        Node<T> current = successor.getRightChild();
        while (current != null) {
            parentSuccessor = successor;
            successor = current;
            current = current.getLeftChild();
        }

        if (successor != deleteNode.getRightChild()) {
            parentSuccessor.setLeftChild(successor.getRightChild());
            successor.setRightChild(deleteNode.getRightChild());
        }
        return successor;
    }

    public boolean delete(int deleteKey) {
        Node<T> current = root;
        Node<T> parent = current;
        boolean isLeftChild = false;
        while (current.getKey() != deleteKey) {
            parent = current;
            if (deleteKey < current.getKey()) {
                current = current.getLeftChild();
                isLeftChild = true;
            } else {
                isLeftChild = false;
                current = current.getRightChild();
            }
            if (current == null)
                return false;
        }

        if (current.getLeftChild() == null && current.getRightChild() == null) {
            if (current == root)
                current = null;
            else if (isLeftChild)
                parent.setLeftChild(null);
            else
                parent.setRightChild(null);
        }
        else if (current.getRightChild() == null) {
            if (current == root)
                root = current.getLeftChild();
            else if (isLeftChild)
                parent.setLeftChild(current.getLeftChild());
            else
                current.setRightChild(current.getLeftChild());
        } else if (current.getLeftChild() == null) {
            if (current == root)
                root = current.getRightChild();
            else if (isLeftChild)
                parent.setLeftChild(current.getRightChild());
            else
                parent.setRightChild(current.getRightChild());
        } 
        else {
            Node<T> successor = getSuccessor(current);
            if (current == root)
                root = successor;
            else if (isLeftChild)
                parent.setLeftChild(successor);
            else
                parent.setRightChild(successor);
        }
        return true;
    }

    public void inOrder(Node<T> current) {
        if (current != null) {
            inOrder(current.getLeftChild());
            System.out.println(current.getData() + " ");
            inOrder(current.getRightChild());
        }
    }
}

PS

Lalacewa zuwa O(n)

Yawancin ku na iya lura: menene idan kun sa itacen ya zama marar daidaituwa? Misali, sanya nodes a cikin bishiyar tare da maɓallai masu haɓaka: 1,2,3,4,5,6... Sa'an nan itacen zai zama ɗan tuno da jerin abubuwan da aka haɗa. Kuma a, bishiyar za ta rasa tsarin bishiyar, don haka ingancin samun bayanai. Matsalolin bincike, shigarwa, da ayyukan sharewa zasu zama iri ɗaya da na jerin da aka haɗa: O(n). Wannan shi ne daya daga cikin mafi mahimmanci, a ganina, rashin amfani na binaryar bishiyoyi.

Masu amfani da rajista kawai za su iya shiga cikin binciken. Shigadon Allah.

Ban daɗe a Habré ba, kuma ina so in san waɗanne labarai kan waɗanne batutuwa kuke son ƙarin gani?

  • Tsarin Bayanai

  • Algorithms (DP, maimaitawa, matsa bayanai, da sauransu)

  • Aikace-aikacen tsarin bayanai da algorithms a rayuwa ta ainihi

  • Shirya aikace-aikacen android a Java

  • Java Web Application Programming

Masu amfani 2 sun kada kuri'a. 1 mai amfani ya ƙi.

Source: www.habr.com

Add a comment