2013-05-26 20 views
8

Wdrożyłem inny rodzaj sortowania (bąbelkowa, wstawianie, selekcja). Wiem, że chcesz porównać ich implementacje jak następuje dla każdego rodzaju (oto przykład z sortowanie bąbelkowe):Porównywanie algorytmu sortowania

enter image description here

Na przykład, oto moja bańka sortowania:

private static int[] bubbleSort(int[] tabToSort) { 
    int [] tab = tabToSort.clone(); 
    boolean tabSort = false; 
    while(!tabSort){ 
     tabSort = true; 
     for(int i = 0; i < tab.length -1; i++){ 
      if(tab[i]> tab[i+1]){ 
       int temp = tab[i+1]; 
       tab[i+1] = tab[i]; 
       tab[i] = temp; 
       tabSort = false; 
      } 
     } 
    } 
    return tab; 
} 

Ja rozpocząłem GUI i umieściłem 1000 losowo wybranych punktów na niego i linię y=x:

@Override 
    public void paintComponent (Graphics g){ 
     super.paintComponent(g); 
     Graphics2D g2d = (Graphics2D) g; 
     g2d.setColor(Color.BLACK); 
     Dimension size = getSize(); 
     Insets insets= getInsets(); 
     int w = size.width - insets.left - insets.right; 
     int h = size.height - insets.top - insets.bottom; 

     g2d.drawLine(size.width ,0, 0, size.height); 
     Random r = new Random(); 

     for (int i =0; i < 1000; i++) { 
      int x = Math.abs(r.nextInt()) % w; 
      int y = Math.abs(r.nextInt()) % h; 
      Point p = new Point(x, y); 
      g2d.drawLine(p.x, p.y, p.x, p.y); 
     } 
    } 

Oto co zrobiłem:

enter image description here

Teraz utknąłem, nie mam pojęcia o tym, jak zacząć. Czy ktokolwiek mógłby wskazać mi kroki/wskazówki do wykonania w celu wdrożenia?

Dzięki :)

Odpowiedz

4

Musisz zdefiniować, co oznaczają punkty. Patrząc na animację, wygląda na to, że oś y reprezentuje value, podczas gdy oś x reprezentuje position w tablicy tej wartości.

W swojej metodzie przejdziemy przez listę elementów i pomalujemy kropkę, przy czym punkt x będzie pozycją w tablicy, a punkt y będzie pozycją na osi Y. Zakładając, że wartości mieszczą się w znanym zakresie.

Pamiętaj też, że oś Y w grafice zaczyna się od 0 na top, więc może być konieczne przetłumaczenie wartości na współrzędne (w zależności od tego, jak chcesz wyglądać).

1

Najprostszym sposobem byłoby zamienić metodę farby do jednego, który używa predefiniowanego List punktów jako parametr zamiast przypadkowych punktów. Przy każdej iteracji metody sortowania przekazuj posortowaną tablicę do metody malowania i odśwież kropki.

1

Musisz

  1. Załóż int[] tablicę losowymi wartościami jako zmienna członkowskim. Nazwijmy tablicę data. Prawdopodobnie chcesz zacząć od stałego rozmiaru tablicy i zakresu 100 sztuk. Możesz dostosować wartości do rozmiaru okna później, gdy działa prosta wersja. Może być jeszcze lepiej trzymać się ustalonego rozmiaru i zakresu i skalować do przestrzeni dostępnej w paintComponent, czyniąc zachowanie niezależnym od rozmiaru okna.
  2. Zmień paintComponent na pętlę ponad data. Indeks pętli to twoja wartość x, a data[x] określa wartość y.
  3. Sprawdź, czy kod nadal rysuje początkową losową tablicę. Nie przejmuj się tym, czy jest teraz w górnym lewym rogu, możesz to naprawić, gdy animacja działa.
  4. Musisz dodać pewnego rodzaju wywołanie sleep() do najgłębiej pętli metody sortowania, aby uzyskać szansę obserwowania kroków. W przeciwnym razie nawet bąbelki będą zbyt szybkie do zaobserwowania. Zalecam zacząć od jednej sekundy (wartość parametru 1000). Zrób to szybciej później, gdy wszystko działa.
  5. Uruchomić metodę bubbleSort w nowym wątku i upewnić się, że komponent zostanie przemalowany w każdym kroku. To może być najtrudniejsza część. Być może ręcznie w komponencie do metody bublleSort (lub uczynić bubbleSort niestatyczną metodę składnika) i pozwól mu poprosić repaint() na każdym kroku (na szczęście jest to jedna z niewielu metod bezpiecznego wątku w Swing).
  6. Dokładne dostrojenie kodu: Skaluj współrzędne x i y, mnożąc je przez dostępne miejsce, a następnie dzieląc przez rozmiar tablicy lub zakres wartości. Dostosuj czas snu w razie potrzeby. Dodaj obsługę różnych algorytmów sortowania ...

Jeśli któryś z kroków jest niejasny, dodaj komentarz.

1

Zrobiłem to dla mojego bachelorthesis, zrobiłem to tak (to nie jest idealne, ale może ci pomóc).

(usunąłem kilka nieistotnych metod/funkcji z poniższym kodzie To głównie do zilustrowania tego, jak ją zwizualizowałem.Możesz zastąpić klasę GRectangle na przykład za pomocą prostego pliku java.awt.Point).

Metoda inicjalizacji daje przykład, jak znaleźć maksymalną i minimalną wartość danych więc wiesz, jak przekształcać współrzędne danych =>.

public class DotVisualisation extends Visualisation { 

    private ArrayList<GRectangle> m_points; 

    private Comparable[] m_data; 

    private Comparable m_maxValue; 
    private Comparable m_minValue; 

    private int MAX_HEIGHT; // max height in pixels of visualization 

    /** 
    * Creates a new DotVisualisation.<br> 
    * <br> 
    * This class is a runnable JComponent that will visualize data as a function. 
    * The visualisation will plot the data with X and Y coordinates on the window. 
    * The X coordinate of the point is index of the dataelement. 
    * The Y coordinate of the point is relative to the value of the dataelement.<br> 
    * <br> 
    * This visualisation should be used for medium and large arrays. 
    * 
    * @author David Nysten 
    */ 
    public DotVisualisation() 
    { 
     m_points = new ArrayList<GRectangle>(); 
     MAX_HEIGHT = 150; 
    } 

    /** 
    * Returns the maximum supported dimension by this visualisation. 
    * 
    * @return The supported dimension. 
    */ 
    public static int getSupportedDimension() 
    { 
     return 1; 
    } 

    @Override 
    public Dimension getMaximumSize() 
    { 
     return getPreferredSize(); 
    } 

    @Override 
    public Dimension getPreferredSize() 
    { 
     return new Dimension(m_points.size() + 2, MAX_HEIGHT + 6); 
    } 

    @Override 
    public Dimension getMinimumSize() 
    { 
     return getPreferredSize(); 
    } 

    @Override 
    public void paintComponent(Graphics g) 
    { 
     for(int i = 0; i < m_points.size(); ++i) 
      m_points.get(i).paintComponent(g); 
    } 

    private void swap(int index, int index2) { // See below } 

    private void initialise() 
    { 
     findMinimum(); 
     findMaximum(); 
     m_points.clear(); 
     double multiplier; 
     int x = 0, y = 0, h; 
     for(int i = 0; i < m_data.length; ++i) 
     { 
      if(m_data[i].compareTo(-1) <= 0) 
       h = 0; 
      else 
      { 
       Integer value = (Integer) m_data[i]; 
       Integer min = (Integer) m_minValue; 
       Integer diff = (Integer) m_maxValue - min; 
       multiplier = MAX_HEIGHT/diff.doubleValue(); 
       h = (int) ((value - min) * multiplier); 
      } 
      y = (int) (MAX_HEIGHT - h); 
      GRectangle r = new GRectangle(x, y, 1, 1); // 1, 1 = width and height 
      r.setColor(Color.BLACK); 
      m_points.add(r); 
      ++x; 
     } 
    } 

    private void findMaximum() 
    { 
     Comparable max = null; 
     if(m_data.length > 0) 
     { 
      max = m_data[0]; 
      for(int i = 1; i < m_data.length; ++i) 
       if(m_data[i].compareTo(max) > 0) 
        max = m_data[i]; 
     } 
     m_maxValue = max; 
    } 

    private void findMinimum() 
    { 
     Comparable min = null; 
     if(m_data.length > 0) 
     { 
      min = m_data[0]; 
      for(int i = 1; i < m_data.length; ++i) 
       if(m_data[i].compareTo(min) < 0) 
        min = m_data[i]; 
     } 
     m_minValue = min; 
    } 
} 

Weź to pod uwagę: Wizualizacja całkowitymi między 0 a 150 na wysokości 150 pikseli jest bardzo proste. Wizualizacja zbioru liczb całkowitych między wartościami 565 i 3544545 na wysokości 150 jest nieco mniejsza.

PS: Kod używa indeksu elementu na wejściu jako współrzędnej X.
PS: Klasa zachowuje odwołanie do wejścia (zmienna m_data), ale nie jest to potrzebne, potrzebne jest tylko do zainicjowania punktów.
PS: Moja klasa "Wizualizacji", która jest rozszerzona o wszystkie wizualizacje, jest w zasadzie JPanelem.
PS: Powyższy kod jest zapisany dla dodatnich liczb całkowitych, więc prawdopodobnie będzie potrzebował dodatkowego kodowania do obsługi ujemnych liczb całkowitych, jak również;).

Następnie w celu wizualizacji działań algorytmu użyłem wzorca obserwatora. Algorytm, na przykład sortowanie bąbelkowe, wyglądał następująco:

for(int i = 0; i < size(); ++i) 
     for(int j = 1; j < size(); ++j) 
      if(greaterThan(j - 1, j)) 
       swap(j - 1, j); 

Gdzie swap funkcja została zdefiniowana w następujący sposób (wersja uproszczona znowu):

protected void swap(int index1, int index2) 
{ 
    if(index1 != index2) 
    { 
     incrementSwap(); // counting swaps and visualizing counter 

     m_command.clear(); 
     m_command.setAction(Action.SWAP); 
     m_command.addParameter(index1); 
     m_command.addParameter(index2); 
     setChanged(); 
     notifyObservers(m_command); 

     E temp = m_data[index1]; 
     m_data[index1] = m_data[index2]; 
     m_data[index2] = temp; 
    } 
} 

Gdzie ja powiadomiony moich obserwatorów (wizualizacje), że zamiana wystąpił na indeksie 1 i indeksie 2. Zmienna m_command jest instancją klasy Command (sam ją napisałem), która jest jedynie opakowaniem informacji potrzebnych do wizualizacji. To jest: akcja, która miała miejsce, i odpowiednie informacje (np. Wskaźniki dla akcji typu swap).

W wizualizacji zamieniłem GRektangles na te wskaźniki oraz ich współrzędne X;

private void swap(int index, int index2) 
{ 
    if(index == index2) 
     return; 
    GRectangle r1 = m_points.get(index); 
    GRectangle r2 = m_points.get(index2); 

    int tempX = r1.getX(); 
    r1.setLocation(r2.getX(), r1.getY()); 
    r2.setLocation(tempX, r2.getY()); 

    m_points.set(index, r2); 
    m_points.set(index2, r1); 
} 

Możesz dodać linie tak:

 try { 
      Thread.sleep(100); 
     } catch(InterruptedException ignore) {} 

do niech 100ms snu nić przed continueing.Może się to przydać, jeśli wizualizacja jest zbyt szybka.

Tak na tablicy z losowych liczb może wyglądać następująco:

enter image description here

i po Sortowanie: (Oczywiście to nie jest prosta, ponieważ wartości w inputarray były generowane losowo w ten przypadek)

enter image description here

Więc jeśli trzeba - jak miałem do - pozwalają wielu algorytmów do pracy z tej samej wizualizacji, mogę RECOM napraw w celu oddzielenia klasy wizualizacji od klasy algorytmu i pracy z wzorcem obserwatora, aby umożliwić aktualizację wizualizacji za każdym razem, gdy nastąpi akcja (ustaw, zamień ...).

A potem możesz stworzyć coś takiego dla porównań;

http://i445.photobucket.com/albums/qq179/ultddave/DotVisualizationMany_zps63269d2a.png http://i445.photobucket.com/albums/qq179/ultddave/DotVisualizationMany2_zps65e96fa9.png

Powodzenia!