Igi alakomeji tabi bi o ṣe le mura igi wiwa alakomeji

Prelude

Nkan yii jẹ nipa awọn igi wiwa alakomeji. Mo laipe kowe ohun article nipa funmorawon data nipa ọna Huffman. Nibẹ Emi ko ṣe akiyesi gaan si awọn igi alakomeji, nitori awọn ọna wiwa, fifi sii, piparẹ ko ṣe pataki. Bayi Mo pinnu lati kọ nkan kan nipa awọn igi. Boya a yoo bẹrẹ.

Igi kan jẹ eto data ti o ni awọn apa ti a ti sopọ nipasẹ awọn egbegbe. A le sọ pe igi kan jẹ ọran pataki ti awọn aworan. Eyi ni apẹẹrẹ igi:

Igi alakomeji tabi bi o ṣe le mura igi wiwa alakomeji

Eyi kii ṣe igi wiwa alakomeji! Ohun gbogbo wa labẹ gige!

Ijinlẹ

Gbongbo

Gbongbo igi ni oke ipade. Ni apẹẹrẹ, eyi ni ipade A. Ninu igi, ọna kan nikan ni o le ja lati gbongbo si ipade miiran! Ni otitọ, eyikeyi oju ipade ni a le gba bi gbongbo ti abẹlẹ ti o baamu si ipade yii.

Awọn obi / ọmọ

Gbogbo awọn apa ayafi gbongbo ni gangan eti kan ti o yori si ipade miiran. Awọn ipade loke awọn ti isiyi ipade ni a npe ni obi yi ipade. Ipade ti o wa ni isalẹ ti isiyi ati ti a ti sopọ si rẹ ni a npe ni arọmọdọmọ yi ipade. Jẹ́ ká gbé àpẹẹrẹ kan yẹ̀ wò. Mu node B, lẹhinna obi rẹ yoo jẹ ipade A, ati awọn ọmọ rẹ yoo jẹ apa D, E, ati F.

Ipin ti ko ni ọmọ ni a npe ni ewe igi. Ninu apẹẹrẹ, awọn apa D, E, F, G, I, J, K yoo jẹ awọn ewe.

Eyi ni ipilẹ awọn ọrọ-ọrọ. Miiran ero yoo wa ni sísọ nigbamii. Nitorinaa, igi alakomeji jẹ igi kan ninu eyiti ipade kọọkan ko ni ju ọmọ meji lọ. Gẹgẹbi o ti ṣe akiyesi, igi lati apẹẹrẹ kii yoo jẹ alakomeji, nitori awọn apa B ati H ni ju awọn ọmọde meji lọ. Eyi ni apẹẹrẹ ti igi alakomeji:

Igi alakomeji tabi bi o ṣe le mura igi wiwa alakomeji

Awọn apa igi le ni alaye eyikeyi ninu. Igi wiwa alakomeji jẹ igi alakomeji ti o ni awọn ohun-ini wọnyi:

  1. Mejeeji apa osi ati ọtun jẹ awọn igi wiwa alakomeji.
  2. Gbogbo awọn apa ti apa osi ti apa lainidii X ni awọn iye bọtini data kere ju iye bọtini data ti ipade X funrararẹ.
  3. Gbogbo awọn apa ti apa ọtun ti apa lainidii X ni awọn iye bọtini data ti o tobi ju tabi dogba si iye bọtini data ti ipade X funrararẹ.

Bọtini - diẹ ninu awọn abuda ti ipade (fun apẹẹrẹ, nọmba kan). Awọn bọtini ti wa ni ti nilo ni ibere lati wa ni anfani lati wa awọn ano ti awọn igi si eyi ti bọtini yi ni ibamu. Apẹẹrẹ igi wiwa alakomeji:

Igi alakomeji tabi bi o ṣe le mura igi wiwa alakomeji

wiwo igi

Bi mo ṣe nlọ, Emi yoo pẹlu diẹ ninu awọn koodu (o ṣee ṣe pe ko pe) lati le ni ilọsiwaju oye rẹ. Awọn koodu kikun yoo wa ni opin nkan naa.

Igi naa jẹ awọn apa. Ilana ipade:

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;
    }
//...остальные методы узла
}

Ipade kọọkan ni awọn ọmọde meji (o ṣee ṣe pupọ pe Ọmọ osi ati/tabi awọn ọmọde ọtun yoo jẹ asan). O ṣee ṣe ki o loye pe ninu ọran yii data nọmba jẹ data ti o fipamọ sinu ipade; bọtini - ipade bọtini.

A ṣe akiyesi sorapo, bayi jẹ ki a sọrọ nipa awọn iṣoro titẹ nipa awọn igi. Lẹhin eyi, ọrọ "igi" yoo tumọ si imọran ti igi wiwa alakomeji. Ilana igi alakomeji:

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

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

Gẹgẹbi aaye kilasi, a nilo gbongbo igi nikan, nitori lati gbongbo, ni lilo awọn ọna getLeftChild () ati getRightChild (), o le de ọdọ eyikeyi apa ti igi naa.

Awọn alugoridimu igi

Поиск

Jẹ ki a sọ pe o ni igi ti a kọ. Bawo ni lati wa eroja pẹlu bọtini bọtini? O nilo lati gbe lẹsẹsẹ lati gbongbo si isalẹ igi naa ki o ṣe afiwe iye bọtini pẹlu bọtini ti ipade atẹle: ti bọtini ba kere ju bọtini ti ipade atẹle, lẹhinna lọ si ọmọ apa osi ti apa, ti o ba jẹ diẹ sii - si ọtun, ti o ba ti awọn bọtini ni dogba - awọn ti o fẹ ipade ti wa ni ri! Koodu to wulo:

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;
}

Ti lọwọlọwọ ba di asan, lẹhinna aṣetunṣe ti de opin igi (ni ipele imọran, o wa ni aaye ti ko si ninu igi - ọmọ ti ewe kan).

Ṣe akiyesi ṣiṣe ti algorithm wiwa lori igi iwọntunwọnsi (igi kan ninu eyiti awọn apa ti pin diẹ sii tabi kere si ni deede). Lẹhinna ṣiṣe wiwa yoo jẹ O (log(n)), ati ipilẹ logarithm 2. Wo: ti awọn eroja n ba wa ninu igi iwọntunwọnsi, lẹhinna eyi tumọ si pe log (n) ipilẹ 2 ipele ti igi naa yoo wa. Ati ninu wiwa, fun igbesẹ kan ti ọmọ, o lọ si isalẹ ipele kan.

Fi sii

Ti o ba ti loye pataki ti wiwa, lẹhinna kii yoo nira fun ọ lati ni oye fifi sii. O kan nilo lati sọkalẹ lọ si ewe ti igi (ni ibamu si awọn ofin ti iran ti a ṣalaye ninu wiwa) ati di ọmọ rẹ - osi tabi ọtun, da lori bọtini. imuse:

   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;
                    }
                }
            }
        }
    }

Ni idi eyi, ni afikun si ipade ti o wa lọwọlọwọ, o jẹ dandan lati tọju alaye nipa obi ti oju ipade lọwọlọwọ. Nigbati lọwọlọwọ ba di asan, oniyipada obi yoo ni dì ti a nilo ninu.
Iṣe ṣiṣe ifibọ yoo han gbangba jẹ kanna bi ti wiwa - O(log(n)).

Paarẹ

Piparẹ jẹ iṣẹ ṣiṣe ti o nira julọ ti yoo nilo lati ṣe pẹlu igi kan. O han gbangba pe akọkọ yoo jẹ pataki lati wa nkan ti a yoo yọ kuro. Ṣugbọn nigbana kini? Ti a ba nirọrun ṣeto itọkasi rẹ si asan, lẹhinna a yoo padanu alaye nipa igi abẹlẹ ti gbongbo rẹ jẹ ipade yii. Awọn ọna yiyọ igi ti pin si awọn ọran mẹta.

Ọran akọkọ. Ipade lati yọ kuro ko ni awọn ọmọde.

Ti ipade lati paarẹ ko ni awọn ọmọde, o tumọ si pe o jẹ ewe kan. Nitorinaa, o le jiroro ṣeto awọn aaye osi tabi awọn aaye Ọmọ ọtun ti obi rẹ si asan.

Ọran keji. Ipade lati yọ kuro ni ọmọ kan

Ọran yii tun ko nira pupọ. Jẹ ki a pada si apẹẹrẹ wa. Ṣebi a nilo lati paarẹ nkan kan pẹlu bọtini 14. Gba pe nitori pe o jẹ ọmọ ọtun ti ipade pẹlu bọtini 10, lẹhinna eyikeyi ninu awọn ọmọ rẹ (ninu ọran yii, ọtun) yoo ni bọtini ti o tobi ju 10 lọ, nitorinaa o le ni rọọrun “ge” lati ori igi, ki o so obi pọ taara si ọmọ ti ipade ti a paarẹ, i.e. so oju ipade pẹlu bọtini 10 si ipade 13. Ipo naa yoo jẹ iru ti a ba ni lati pa ipade ti o jẹ ọmọ osi ti obi rẹ. Ronu nipa rẹ fun ara rẹ - afiwe deede.

Ọran kẹta. Node ni ọmọ meji

Ọran ti o nira julọ. Jẹ ki a wo apẹẹrẹ tuntun kan.

Igi alakomeji tabi bi o ṣe le mura igi wiwa alakomeji

Wa arọpo

Jẹ ká sọ pé a nilo lati yọ awọn ipade pẹlu awọn bọtini 25. Ta ni a o fi si awọn oniwe-ibi? Ọkan ninu awọn ọmọ-ẹhin rẹ (awọn ọmọ-ọmọ tabi awọn ọmọ-ọmọ) gbọdọ di arọpo(ẹni tí yóó gba ibi ìpàropá tí a yọ kúrò).

Bawo ni o ṣe mọ ẹniti o yẹ ki o jẹ arọpo? Ni imọran, eyi ni apa inu igi ti bọtini rẹ jẹ atẹle ti o tobi julọ lati ipade ti a yọ kuro. Algoridimu jẹ bi atẹle. O nilo lati lọ si ọmọ ọtun rẹ (nigbagbogbo si ọtun, nitori o ti sọ tẹlẹ pe bọtini ti arọpo ti o tobi ju bọtini ti ipade ti paarẹ), ati lẹhinna lọ nipasẹ pq ti awọn ọmọ osi ti ọtun yii. ọmọ. Ni apẹẹrẹ, a gbọdọ lọ si ipade pẹlu bọtini 35, ati lẹhinna lọ si isalẹ awọn pq ti awọn ọmọ osi rẹ si bunkun - ninu idi eyi, ẹwọn yii jẹ nikan ti ipade pẹlu bọtini 30. Ni pipe, a n wa. ipade ti o kere julọ ninu ṣeto awọn apa ti o tobi ju ipade ti o fẹ.

Igi alakomeji tabi bi o ṣe le mura igi wiwa alakomeji

Koodu ọna wiwa arọpo:

    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;
    }

Koodu pipe ti ọna piparẹ:

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;
    }

Idiju le jẹ isunmọ O(log(n)).

Wiwa ti o pọju / kere julọ ninu igi kan

O han ni, bii o ṣe le rii iye ti o kere julọ / o pọju ninu igi - o nilo lati lọ lẹsẹsẹ nipasẹ pq ti osi / awọn eroja ọtun ti igi, ni atele; nigbati o ba de ewe naa, yoo jẹ ipin ti o kere julọ / o pọju.

    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;
    }

Idiju - O(log(n))

Symmetric Fori

Traversal ni a ibewo si kọọkan ipade ti awọn igi ni ibere lati se nkankan pẹlu rẹ.

Algorithm itọka alarabara ti o ṣe deede:

  1. Ṣe ohun igbese lori osi ọmọ
  2. Ṣe igbese pẹlu ara rẹ
  3. Ṣe ohun igbese lori ọtun ọmọ

Koodu:

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

ipari

Níkẹyìn! Ti Emi ko ba ṣalaye nkankan tabi ni awọn asọye, lẹhinna Mo n duro de awọn asọye. Bi ileri, nibi ni pipe koodu.

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

Ilọkuro si O(n)

Ọpọlọpọ ninu nyin le ti ṣe akiyesi: kini ti o ba jẹ ki igi naa di alaiṣedeede? Fun apẹẹrẹ, fi awọn apa sinu igi pẹlu awọn bọtini ti o pọ si: 1,2,3,4,5,6... Lẹhinna igi naa yoo jẹ iranti diẹ ti atokọ ti o sopọ mọ. Ati bẹẹni, igi naa yoo padanu eto igi rẹ, ati nitorinaa ṣiṣe ti wiwọle data. Idiju wiwa, fifi sii, ati awọn iṣẹ ṣiṣe piparẹ yoo di kanna bi ti atokọ ti o sopọ mọ: O(n). Eyi jẹ ọkan ninu awọn pataki julọ, ninu ero mi, awọn alailanfani ti awọn igi alakomeji.

Awọn olumulo ti o forukọsilẹ nikan le kopa ninu iwadi naa. wọle, Jowo.

Emi ko wa lori Habré fun igba pipẹ, ati pe Emi yoo fẹ lati mọ awọn nkan wo lori awọn akọle wo ni iwọ yoo fẹ lati rii diẹ sii?

  • Data Awọn ẹya

  • Awọn alugoridimu (DP, isọdọtun, funmorawon data, ati bẹbẹ lọ)

  • Ohun elo ti awọn ẹya data ati awọn algoridimu ni igbesi aye gidi

  • Siseto awọn ohun elo Android ni Java

  • Eto Ohun elo Ayelujara Java

2 olumulo dibo. 1 olumulo abstained.

Orisun: www.habr.com

Fi ọrọìwòye kun