JavaRush /Блоги Java /Random-TG /Сохторҳои маълумот: Пирамида (Heap Binary) дар Java

Сохторҳои маълумот: Пирамида (Heap Binary) дар Java

Дар гурӯҳ нашр шудааст
Салом Салом! Ҳеҷ кас инкор намекунад, ки алгоритмҳо ва сохторҳои додаҳо асоси раднашавандаи барномасозӣ мебошанд. Бале, шумо метавонед ҳамчун барномасоз бидуни донистани онҳо кор кунед, аммо афсӯс, ки шумо дур намеравед. Аз ин рӯ, барои таҳкими пойгоҳи дониши шумо дар ин соҳа, ман мехоҳам дар бораи сохтори додаҳо бо номи пирамида (инчунин бо номи тӯда ва дуӣ маълум) сӯҳбат кунам. Чун қоида, чунин сохторҳои додаҳо дар банақшагирии гуногун ва дигар сохторҳое истифода мешаванд, ки дар онҳо афзалияти вазифаҳои гуногунро нишон додан лозим аст. Ҳамин тавр... Сохторҳои маълумот: Пирамида (Heap дуӣ) дар Java - 1Пирамида як намуди дарахтест, ки дар вақти O(logN) дохил кардан/ҳазф карданро таъмин мекунад ва дорои хосиятҳои зерин аст:
  • Комилан. Ҳама сатҳҳои дарахт ҳама гиреҳҳои имконпазирро дар бар мегиранд, ба истиснои охирин, ки танҳо қисман пур карда мешаванд ва аз чап ба рост пур карда мешаванд;
  • Пирамида одатан дар асоси массив амалӣ карда мешавад;
  • Барои ҳар як гиреҳ дар пирамида шарти асосӣ мавҷуд аст, ки арзиши ҳар як гиреҳ аз арзишҳои насли он бузургтар (ё баробар) бошад. Мувофиқи он, ҳадди аксар дар элементи боло нигоҳ дошта мешавад.
Пирамида, ки аз қуллаҳое иборат аст, ки арзишҳоро на бештар аз 10 нигоҳ медоранд: Сохторҳои маълумот: Пирамида (Heap дуӣ) дар Java - 2Ман мехоҳам қайд намоям, ки дар муқоиса бо дарахти ҷустуҷӯии дуӣ, пирамида суст тартиб дода шудааст , зеро дар дарахти ҷустуҷӯи бинарӣ калиди кӯдаки чап аз он камтар аст. калиди кӯдаки рост ва дар пирамида чунин шароит вуҷуд надорад.

Хориҷ кардани элемент аз рӯи индекс

Аввалан, биёед пайдарпайии амалҳоро ҳангоми нест кардани гиреҳи интихобшуда бубинем:
  1. Гиреҳи интихобшударо нест кунед.
  2. Гиреҳи охирини сатри охиринро ба ҷои тозашуда гузаронед.
  3. Онро ба поён ҳаракат кунед, то он даме, ки он аз гиреҳи калонтар ва болотар аз гиреҳи хурдтар бошад.
Ҳангоми истифодаи пирамида, одатан зарур аст, ки боло (элементи сифрии массиви дохилӣ) ё охиринро хориҷ карда тавонед (пас амалҳои ҳаракатро сарфи назар кардан мумкин аст ва танҳо хориҷ кардани элемент боқӣ мемонад). Ҳамчун мисоли нест кардани элемент аз рӯи индекс дар пирамида, ки мо дар боло дида истодаем, мо гиреҳро бо арзиши 7 нест мекунем:
  1. Мо гиреҳи интихобшударо нест мекунем ва ба ҷои он охиринро мегузорем, ки арзиши 4 дорад:

    Сохторҳои маълумот: Пирамида (Heap дуӣ) дар Java - 3

    Аммо дар ин мавқеъ ин гиреҳ ба шарте ҷавобгӯ нест, ки ҳар як гиреҳи насл набояд аз гиреҳи мавриди назар калонтар бошад, дуруст?

    Барои ҳамон:

  2. Мо онро бо калонтарин кӯдакон иваз мекунем, ки арзиши он 6 аст:

    Сохторҳои маълумот: Пирамида (Heap Binary) дар Java - 4

    Баъдан, мо мебинем, ки оё ягон насли дорои арзиши бузургтар аз унсури кӯчонидашудаи мо вуҷуд дорад ва мо мебинем, ки ҳеҷ кас вуҷуд надорад, яъне ин унсур ҷои худро гирифтааст.

Ворид кардани элементи нав

Ҳангоми ворид кардани элементи нав кадом амалҳо иҷро мешаванд:
  1. Гиреҳи воридшуда дар охири пирамида ҷойгир аст.

    Аммо мо як шарт дорем, ки унсури кӯдак наметавонад аз волидайни худ арзиши бузургтар дошта бошад, дуруст?

    Барои ҳамон:

  2. Унсури навро бо унсури волидайн муқоиса кунед. Агар элементи нав хурдтар бошад, пас амалиёт анҷом мешавад, агар не, он ҷойҳоро бо элементи волидайн иваз мекунад. Пас аз ин, он бо унсури нави волидайн муқоиса карда мешавад ва ғайра... То он даме, ки унсури волидайн аз нав бузургтар бошад.
Масалан, ба пирамидае, ки тавассути нест кардани элемент ба даст оварда шудааст, мо мехоҳем элементеро бо арзиши 8 илова кунем:
  1. Дар охири пирамида гиреҳи нав ҷойгир кунед:

    Сохторҳои маълумот: Пирамида (Heap дуӣ) дар Java - 5
  2. Элементи навро бо унсури волидайн, ки арзиши 4 дорад, муқоиса кунед.

    Азбаски элементи нав аз волидайн калонтар аст, мо онҳоро иваз мекунем:

    Сохторҳои додаҳо: Пирамида (Heap Binary) дар Java - 6
  3. Мо унсури навро бо волидайни нави он муқоиса мекунем ва мебинем, ки элементи мо аз он (8>7) калонтар аст, бинобар ин мо онҳоро низ иваз мекунем:

    Сохторҳои маълумот: Пирамида (Heap дуӣ) дар Java - 7

    Боз, мо элементро бо унсури волидайн муқоиса мекунем ва мебинем, ки ин дафъа элементи волидайн калонтар аст, яъне ин маънои онро дорад, ки элементи нави мо ба ҷои худ афтодааст.

Иваз кардани элемент

Ҳангоми иваз кардани элемент, шумо бояд аввал элементро бо индекси додашуда иваз кунед. Мантиқӣ, дуруст? Пас, баъд чӣ? Охир, арзиши нави элемент аллакай дигар аст ва ин факт нест, ки вай ба шароити пирамида мувофик бошад. Яъне, ин далел нест, ки ҳамаи унсурҳои кӯдак аз унсури воридшуда хурдтаранд. Инчунин далел нест, ки унсурҳои волидайн аз нав калонтаранд. Аз ин рӯ, шумо аввал бояд бо арзиши кӯҳнаи элемент муқоиса кунед:
  • агар элементи нав аз он калонтар бошад, пас мо бояд онро бо унсурҳои волидайн муқоиса кунем ва дар ҳолати зарурӣ онҳоро иваз кунем;
  • агар элементи нав хурдтар бошад, он бояд бо калонтари унсурҳои кӯдак муқоиса карда шавад ва агар унсури кӯдак калонтар бошад (то даме ки элементи нав дар ҷои қобor қабул) иваз карда шавад.
Биёед инро бо мисоли худ дида бароем. Ҳоло мо мехоҳем ба ҷои элементи дорои арзиши 9 як унсури дорои арзиши 1 дохил кунем:
  1. Элементро ба ҷои элементи қаблӣ гузоред:Сохторҳои маълумот: Пирамида (Heap дуӣ) дар Java - 8
  2. Мо унсури қаблии 9 ва нав 1-ро муқоиса мекунем ва мебинем, ки он хурдтар аст, яъне мо кӯшиш мекунем, ки онро ба поён гузаронем.
  3. Мо онро бо бузургтарин унсури аз кӯдакон, яъне бо элементе, ки арзиши 5 дорад, муқоиса мекунем ва мебинем, ки наваш хурдтар аст. Аз ин рӯ, мо унсурҳои муқоисашударо иваз мекунем:Сохторҳои маълумот: Пирамида (Heap дуӣ) дар Java - 9
  4. Азбаски ҳоло дар зер унсури нави мо вуҷуд надорад, мо гуфта метавонем, ки элемент ба ҷои худ афтодааст.

Татбиқи пирамида дар Java

Пас аз фаҳмидани он, ки ин сохтор чӣ гуна кор мекунад, вақти он расидааст, ки ба татбиқи пирамида дар Java назар кунем : Синф, ки як қулла ва арзиши онро дар бар мегирад:
public class Node {
  private int value;

  public Node(int value) {
     this.value = value;
  }

  public int getValue() {
     return this.value;
  }

  public void setValue(int value) {
     this.value = value;
  }
}
Синф, ки худи пирамидаро ифода мекунад:
public class Heap {
  private Node[] heapArray; // массив со всеми вершинами
  private int maxSize; // размер массива
  private int currentSize; // количество узлов массиве

  public Heap(int maxSize) { // создание пустой пирамиды
     this.maxSize = maxSize;
     this.currentSize = 0;
     heapArray = new Node[maxSize];
  }

  public void printHeap() { // отображение перамиды в консоль
     System.out.println("Массив значений: ");

     for (int n = 0; n < currentSize; n++) {
        if (heapArray[n] != null) {
           System.out.println(heapArray[n].getValue() + " ");
        }
        else {
           System.out.println("-");
        }
     }
     System.out.println();

     int countOfGaps = 32;
     int itemsPerRow = 1;
     int columnNumber = 0; // номер element в данной строке
     String lines = "___________________________________________________________________";
     System.out.println(lines);
     for (int i = 0; i < currentSize; i++) {
        if (columnNumber == 0) {  // проверяем первый элемент ли в текущей строке
           for (int k = 0; k < countOfGaps; k++) { // добавляем предшествующие пробелы
              System.out.print(' ');
           }
        }
        System.out.print(heapArray[i].getValue());// выводим в консоль meaning вершины

        if (++columnNumber == itemsPerRow) { // проверяем последний ли элемент в строке
           countOfGaps /= 2; // уменьшаем количество оступов применяемое для следующей строки
           itemsPerRow *= 2; // указываем, что элементов может быть вдвое больше
           columnNumber = 0; // сбрасываем счётчик для текущего element строки
           System.out.println(); // переходим на нову строку
        }
        else { //переход к следующему элементу
           for (int k = 0; k < countOfGaps * 2 - 2; k++) {
              System.out.print(' '); // добавляем оступы
           }
        }
     }
     System.out.println("\n" + lines); // нижний пункир
  }

  public boolean insertNode(int value) { // вставка нового значения
     if (currentSize == maxSize) { // проверяем не выходим ли мы за рамки массива
        return false;
     }
     Node newNode = new Node(value);// создание вершины с данным meaningм
     heapArray[currentSize] = newNode;// вершину задём в самый низ дерева
     displaceUp(currentSize++);// пытаемся поднять вершину, если meaning вершины позволяет
     return true;
  }

  public Node removeNode(int index) { // удалить элемент по индексу массива
     if(index > 0 && currentSize > index) {
        Node root = heapArray[index];
        heapArray[index] = heapArray[--currentSize]; // задаём элементу с переданным индексом, meaning последнего element
        heapArray[currentSize] = null;// последний элемент удаляем
        displaceDown(index);// проталкиваем вниз новый элемент, чтобы он должное ему место
        return root;
     }
     return null;
  }

  public boolean changeNode(int index, int newValue) {
     if (index < 0 || currentSize<=index) {
        return false;
     }
     int oldValue = heapArray[index].getValue(); // сохраняем старое meaning
     heapArray[index].setValue(newValue); // присваиваем новое

     if (oldValue < newValue) {// если узел повышается
        displaceUp(index);     // выполняется смещение вверх
     }
     else {                  // если понижается
        displaceDown(index);   // смещение вниз
     }
     return true;
  }

  private void displaceUp(int index) { //смещение вверх
     int parentIndex = (index - 1) / 2; // узнаем индекс родителя
     Node bottom = heapArray[index]; // берем элемент
     while (index > 0 && heapArray[parentIndex].getValue() < bottom.getValue()) {// если родительский элемент меньше
        heapArray[index] = heapArray[parentIndex];// то меняем его местами с рассматриваемым
        index = parentIndex;
        parentIndex = (parentIndex - 1) / 2;// берем новый родительский индекс и повторяем сравнение элементов
     }
     heapArray[index] = bottom;// соохраняем результат
  }

  private void displaceDown(int index) {// смещение вниз
     int largerChild;
     Node top = heapArray[index]; // сохранение корня, пока у узла есть хотя бы один потомок
     while (index < currentSize / 2) {// если данное condition не выполняется то элемент уже в самом низу пирамиды
        int leftChild = 2 * index + 1; // вычисляем индексы в массиве для левого узла ребенка
        int rightChild = leftChild + 1;// и правого

        if (rightChild < currentSize && heapArray[leftChild].getValue() < heapArray[rightChild].getValue()) {
           largerChild = rightChild;
        }// вычисляем ребенка вершину с наибольшим числовым meaningм
        else {
           largerChild = leftChild;
        }

        if (top.getValue() >= heapArray[largerChild].getValue()) {// если meaning вершины больше or равно
           //значени его наибольшего ребенка
           break;// то выходим из метода
        }

        heapArray[index] = heapArray[largerChild];// заменяем вершину, большей дочерней вершиной
        index = largerChild; // текущий индекс переходит вниз
     }
     heapArray[index] = top; // задаем конечное местоположение для element
  }
}
Ниҳоят, биёед пирамидаи худро дар амал бубинем:
public class Solution {

  public static void main(String[] args) {
     // задаем начальные данные:
     Heap heap = new Heap(31);
     heap.insertNode(120);
     heap.insertNode(40);
     heap.insertNode(50);
     heap.insertNode(80);
     heap.insertNode(20);
     heap.insertNode(100);
     heap.insertNode(150);
     heap.insertNode(30);
     heap.insertNode(210);
     heap.insertNode(180);
     heap.insertNode(10);
     heap.insertNode(90);
      // выводим начальную пирамиду в консоль
     heap.printHeap();
Натиҷаи консол:Сохторҳои маълумот: Пирамида (Heap дуӣ) дар Java - 10
// изменяем элемент под индексом 0 с 210 на 15, и выводим в консоль измененную пирамиду
     heap.changeNode(0,15);
     heap.printHeap();
Натиҷаи консол:Сохторҳои маълумот: Пирамида (Heap дуӣ) дар Java - 11
// удаляем элемент под индексом 3, который имеет meaning 80 и смотрим на изменившуюся пирамиду
     heap.removeNode(3);
     heap.printHeap();
  }
}
Натиҷаи консол: Сохторҳои маълумот: Пирамида (Heap дуӣ) дар Java - 12Бале, ин ҳама аст. Ташаккур ба ҳама барои таваҷҷӯҳатон!Сохторҳои маълумот: Пирамида (Heap дуӣ) дар Java - 13Сохторҳои маълумот: Пирамида (Heap дуӣ) дар Java - 14
Шарҳҳо
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION