Semestrální práce z předmětu Teoretická informatika
Semestrální práce z předmětu
Teoretická informatika.
36TI


Vypracoval: Jan Saidl
Datum: 28.12.2002


Úloha číslo 2 z českých úloh


Zadání:
Jsou dána čísla 1, 2, ... N. Tato čísla lze permutovat právě N! způsoby. Permutace lze seřadit v rostoucím lexikografickém pořadí:
0, 1, ... N-3, N-2, N-1
0, 1, ... N-3, N-1, N-2
0, 1, ... N-1, N-2, N-2
. . .
N-1, N-2,.... 0, 1
N-1, N-2,.... 1, 0
Navrhněte, popište a implementujte algoritmus, který pro zadané i vytvoří i-tou permutaci. Určete výpočetní složitost algoritmu v závislosti na hodnotě N.

Implementace (Applet JAVA):


Operační složitost:
   Paměťová složitost je lineární, v každé části algoritmu je potřeba si pamatovat pouze N znakové pole členů permutace.

Paměťová složitost:
   Algoritmus provádí N-1 dělení indexu I řádem, který se v každém cyklu snizuje N-krát. V nejhořím případě, kdy výsledkem je permutace s indexem 0, dochází k n^2/2 presunům v poli dostupných členů permutace. Operační složitost algoritmu je O(N^2). Tato kvadratická složitost by se dala odstranit, kdyby pole dostupných členů permutace bylo reprezentováno spojovým seznamem. Vypuštění jednoho členu by proběhlo s konstatní složisostí. Operační složitost algoritmu by v tomto případě byla O(N).

Popis algoritmu:
   Nejprve je vygenerováno pole dostupných členů permutace (max. 12) a spočítán nejvyšší řád N! permutace. V N-1 průchodech je určeno N-1 členů hledané permurtace, od nejvyššího řádu. Index X-tého členu je výsledek celočíselného dělení indexu I X-tým řádem. Nový index je zbytek po tomto dělení a řád se snižuje na (X-1)!. Po N-1 cyklech je určeno N-1 členů permutace a poslední člen je na nultém indexu pole dostupných členů permutace.

Zdrojový text:
package permutace;

import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class AppletPermutace extends Applet {

  // implementace GUI
  boolean isStandalone = false;
  private Label lable_velikost;
  private Label lable_index;
  private Label vysledekLB;
  private TextField velikost;
  private TextField index;
  private Button buttonGo;

  private GridBagLayout gbl;
  private GridBagConstraints gbc;

  private class ButtonGoClick implements ActionListener {
    public void actionPerformed(ActionEvent p) {
      String result =  countPerm(velikost.getText(),index.getText());
      vysledekLB.setText(result);
    }
  }

  private void vlozComponentu(Component c, int gridx, int gridy) {
    gbc.gridx = gridx;
    gbc.gridy = gridy;
    gbl.setConstraints(c,gbc);
    add(c);
  }

  private void initMetoda() {
    // implementace GUI
         lable_velikost = new Label("delka permutace N: ");
    lable_index = new Label("index permutace I: ");
    velikost = new TextField("");
    vysledekLB = new Label("");
    index = new TextField("");
    buttonGo = new Button("Spocti");
    buttonGo.addActionListener(new ButtonGoClick());
    gbl = new GridBagLayout();
    this.setLayout(gbl);
    this.setBackground(Color.white);
    gbc = new GridBagConstraints();
    gbc.insets = new Insets(2,2,2,2);
    gbc.anchor = gbc.WEST;
    vlozComponentu(lable_velikost,0,0);
    gbc.weightx = 1.0;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    vlozComponentu(velikost,0,1);
    gbc.anchor = gbc.WEST;
    vlozComponentu(lable_index,0,2);
    gbc.weightx = 1.0;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    vlozComponentu(index,0,3);
    gbc.fill = GridBagConstraints.NONE;
    gbc.weightx = 0.0;
    gbc.anchor = gbc.CENTER;
    vlozComponentu(buttonGo,0,4);
    gbc.anchor = gbc.CENTER;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    vysledekLB.setSize(200,20);
    vlozComponentu(vysledekLB,0,5);
    }

  // Initialize appletu
  public void init() {
    try {
      initMetoda();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }
    // funkce pro vypocet I-te permutace
    public static String countPerm(String NStr, String IStr) {
         int NValue = 0;   // N je delka permutace
         int IValue = 0;   // I je index hledane permutace
         try {             // pokus o prevedeni N na cislo 
           Integer N = new Integer(NStr);
           NValue = N.intValue();
         } catch(NumberFormatException ex) {
           return "CHYBA N neni cislo nebo je mimo rozsah";
         }
         // kontrola rozsahu N maximum je N = 12 protoze 13! = 6227020800 > integer.MAX_VALUE = 2147483647 
         if ((NValue > 12) || (NValue < 1)) { return "CHYBA N mimo rozsah <1,12>"; }

         try {            // pokus o prevedeni I na cislo 
           Integer I = new Integer(IStr);
           IValue = I.intValue();
         } catch(NumberFormatException ex) {
           return "CHYBA I neni cislo nebo je mimo rozsah";
         }

         int rad = 1;     // vypocet maximalniho radu permutace = N! 
         for (int x = NValue; x > 0; x--) {
           rad = rad * x;
         }
                          // overeni zda I je v intervalu <0 ; N!-1> 
         if ((IValue >= rad) || (IValue < 0)) { return "CHYBA I mimo rozsah <0,"+(new Long(rad-1)).toString()+">"; }
         rad = rad / NValue;

         String chars = new String("0123456789AB");  // pojmenovani jednotlivych dostupnych clenu premutace 
         String perm = new String("");               // inicializace vysledne premutace 

         while (NValue > 1) {                        // pres vsechny cleny permutace 
           NValue--;
           int divx = IValue / rad;                  // urci N-ty clen permutace
           IValue = IValue % rad;                    // urci zbytek po N-tem clenu permutace
           perm = perm + chars.charAt(divx);         // pridej N-ty clen permutace do vysledne permutace
           chars = chars.substring(0,divx) + chars.substring(divx+1);  // a odstran ho z dostupnych clenu
           rad = rad / NValue;                       // sniz rad permutace 
           }

         perm = "Permutace = "+ perm + chars.charAt(0); // pouzij posledni dostupny clen permutace
         return perm;                                // vrat vypoctenou permutaci
    }
}