Datová struktura disjoint-set slouží k vytvoření systému navzájem se nepřekrývajících podmnožin. Pro implementaci se používají dvě základní operace - Union (spojení dvou podmnožin v jednu) a Find (nalezení reprezentanta daného prvku). Sloučením názvů těchto operací vzniká označení pro implementaci této datové struktury - Union-Find problém/Union-Find algoritmus.

Motivace

Union-Find problém nalézá uplatnění při řešení otázky, zda-li jsou dva uzly v té samé komponentě souvislosti grafu G, čehož se využívá například v Kruskalově algoritmu hledání minimální kostry.

Princip a implementace

Řešení problému spočívá v udržováni tzv. reprezentantů komponent, což jsou uzly, kterými všechny uzly z daných komponent prokazují svojí příslušnost. Za předpokladu, že mají dva uzly stejného reprezentanta, tak patří do stejné komponenty.

K reprezentaci se obvykle používá n-ární strom, ve kterém je kořen reprezentantem. Za předpokladu, že spojujeme dvě komponenty (operace Union), tak kratší podstrom zavěsíme pod reprezentanta delšího podstromu, v případě rovnosti délek na volbě nezáleží. Pokud vyhledáváme reprezentata komponenty, tak z daného uzlu vystoupáme do kořenu stromu, což je hledaný reprezentant (operace Find).

Kontrakce cesty

Optimalizací tohoto algoritmu je na závěr operace Find procházené uzly zavěsit přímo pod reprezentanta (zkrátit cestu). Tímto se sice složitost této operace zhorší, ale tento horší případ proběhne pouze jednou, při každém dalším hledání operace proběhne rychleji, než by proběhla bez tohoto vylepšení. Operace nyní proběhnou s amortizovanou složitostí O(\\alpha(n)), kde \\alpha je inverzní Ackermanova funkce.


Kód

  /**
   * Disjoint set - Union-Find
   * @author Pavel Micka
   */
  public class DisjointSet<ENTITY> {
  
      private Node[] nodes;
  
      /**
       * Konstruktor (Make-Set)
       * @param values hodnoty jednotlivych reprezentantu - id == poradi v seznamu
       */
      public DisjointSet(List<ENTITY> values) {
          nodes = new Node[values.size()];
          for (int i = 0; i < values.size(); i++) {
              nodes[i] = new Node<ENTITY>();
              nodes[i].id = i;
              nodes[i].setValue(values.get(i));
          }
      }
  
      /**
       * Spoji komponenty s danymi id
       * (union by rank)
       * @param a id 1
       * @param b id 2
       * @return id reprezentanda spojene komponenty
       */
      public int union(int a, int b) {
          Node repA = nodes[find(a).id];
          Node repB = nodes[find(b).id];
  
          if (repA.getId() == repB.getId()) return repA.getId();
  
          if(repA.rank == repB.rank){
              repB.parent = repA;
              repA.rank++;
              return repA.id;
          } else if(repA.rank > repB.rank){
              repB.parent = repA;
              return repA.id;
          } else {
              repA.parent = repB;
              return repB.id;
          }
      }
  
      /**
       * Vrati reprezentanta komponenty obsahujici uzel s danym id
       * @param a id uzlu
       * @return reprezentant
       */
      public Node find(int a) {
          Node n = nodes[a];
          int jumps = 0;
          while (n.parent != null) {
              n = n.parent;
              jumps++;
          }
          if (jumps > 1) repair(a, n.getId());
          return n;
      }
  
      /**
       * Kontrahuje cestu do reprezentanta
       * @param a id uzlu, ze ktereho bude cesta opravena
       * @param rootId id reprezentanta
       */
      private void repair(int a, int rootId) {
          Node curr = nodes[a];
          while (curr.getId() != rootId) {
              Node tmp = curr.parent;
              curr.parent = nodes[rootId];
              curr = tmp;
          }
      }
  
      @Override
      public String toString() {
          StringBuilder builder = new StringBuilder();
          for (int i = 0; i < nodes.length; i++) {
              builder.append(find(i) + " ");
          }
          return builder.toString();
      }
  
      /**
       * Uzel n-arniho stromu
       */
      public static class Node<ENTITY> {
          /**
           * Rank of the tree
           */
          private int rank;
          private Node parent;
          private int id;
          private ENTITY value;
  
          /**
           * @return the id
           */
          public int getId() {
              return id;
          }
  
          /**
           * @return the value
           */
          public ENTITY getValue() {
              return value;
          }
  
          /**
           * @param value the value to set
           */
          public void setValue(ENTITY value) {
              this.value = value;
          }
      }
  }
  

SEO od společnosti Digital Pylon


Online casino s algoritmem

České casino online online slot-vegas.cz

Hrajte nejlepší hry jako je GoodGame Empire.





Zajímavé články: Jak najít práci snů? Zvolte kariéru v IT!, Češi mají rádi hrací automaty online, Jak funguje algoritmické obchodování Casino, Online výuka Algoritmus a online marketing mají svá pravidla, Automaty, Matematický vliv, Ratings, Jak fungují algoritmy hazardních her online: více znalostí, více peněz, SYPWAI - nástroj pro vědecký vývoj, Vynikají na globálním trhu: Nejlepší vývojáři softwaru pro online výherní automaty, Jak si vybrat nejlepší české online casino, Proč byste měli hrát online casino VPN revoluce, Kde najdeme algoritmy v každodenním životě?, Čeká vás pracovní pohovor mimo město? Podívejte se, jak dokonale zvládnout včasný příchod, 5 úžasných technologií ze světa hazardních her, Mirror and access to Mostbet, Svou kancelář můžete mít stále po ruce, Jaké výhody má digitalizovaná firma oproti off-line konkurenci?, Jaký systém vybrat pro snadné řízení výroby?, Nahradí umělá inteligence ajťáky?, Důvody, proč používat SnapTik ke stahování videí TikTok, Dokonalý den na pláži: Co si vzít s sebou, aby byl výlet zábavný a bezpečný?, Jak přežít dlouhý let?, Go pay GoodGame Empire, Blockchain, Rozhovor


Doporučujeme

Internet pro vaši firmu na míru

https://www.algoritmy.net