import java.applet.Applet;
import java.awt.*;
import java.util.Random;

public class Qsort extends Applet 
  {
    static int N = 10000;
    static int dotsize = 4;
    static Graphics g;

    static void clear(Color c)
      { 
        int h = g.getClipRect().height;
        int w = g.getClipRect().width;
        g.setColor(c);
        g.fillRect(0, 0, w, h);
      }
    static void paint(int i, double x, Color c)
      { 
        int h = g.getClipRect().height;
        int w = g.getClipRect().width;
        g.setColor(c);
        g.fillOval( (i*w)/N, h - (int) (x*h), dotsize, dotsize);
      }
    static void exch(double [] a, int i, int j)
      { double t = a[i]; a[i] = a[j]; a[j] = t;
        paint(i, a[j], Color.white);
        paint(j, a[i], Color.white);
        paint(i, a[i], Color.black);
        paint(j, a[j], Color.black);
      }
    static boolean less(double [] a, int i, int j)
      { 
        paint(i, a[i], Color.red);
        paint(j, a[j], Color.red);
        return a[i] < a[j];
      }
    static int partition(double[] a, int l, int r)
      { int i = l-1, j = r; double t, v = a[r];
        for (;;)
          { 
            while (less(a, ++i, r)) ;
            while (less(a, r, --j)) if (j == l) break;
            if (i >= j) break;
            exch(a, i, j);
          }
        exch(a, i, r);
        return i;
      }
    static void quicksort(double[] a, int l, int r)
      { int i;
        if (r <= l) return;
        i = partition(a, l, r);
        quicksort(a, l, i-1);
        quicksort(a, i+1, r);
      }
    static void quicksortFAST(double[] a, int l, int r)
      { int i, m;
        if (r - l < 50) return;
        m = (r + l)/2;
        exch(a, m, r-1);
        if (less(a, r-1, l)) exch(a, r-1, l); 
        if (less(a, r, l)) exch(a, r, l); 
        if (less(a, r, r-1)) exch(a, r-1, r); 
        i = partition(a, l+1, r-1);
        if (i-l > r-i)
          {
            quicksortFAST(a, i+1, r);
            quicksortFAST(a, l, i-1);
          }
        else
          {
            quicksortFAST(a, l, i-1);
            quicksortFAST(a, i+1, r);
          }
      }
    static int partitionBAD(double[] a, int l, int r)
      { int i = l-1, j = r; double t, v = a[r];
        for (;;)
          { 
            while (less(a, ++i, r)) ;
            while (less(a, r, --j)) if ((j == l) || (a[r] == a[j])) break;
            if (i >= j) break;
            exch(a, i, j);
          }
        exch(a, i, r);
        return i;
      }
    static void quicksortBAD(double[] a, int l, int r)
      { int i;
        if (r <= l) return;
        i = partitionBAD(a, l, r);
        quicksortBAD(a, l, i-1);
        quicksortBAD(a, i+1, r);
      }
    static void quicksortEQ(double[] a, int l, int r)
      { int i, j, k, p, q; double v;
        if (r <= l) return;
        i = l-1; j = r; v = a[r]; p = l-1; q = r;
        for (;;)
          { 
            while (less(a, ++i, r)) ;
            while (less(a, r, --j)) if (j == l) break;
            if (i >= j) break;
            exch(a, i, j);
            if (a[i] == v) { p++; exch(a, p, i); }
            if (a[j] == v) { q--; exch(a, q, j); }
          }
        exch(a, i, r); j = i-1; i = i+1;
        for (k = l  ; k < p; k++, j--) exch(a, k, j);
        for (k = r-1; k > q; k--, i++) exch(a, k, i);
        quicksortEQ(a, l, j);
        quicksortEQ(a, i, r);
      }
    static void insertion(double a[], int l, int r)
      { int i, j; 
        for (i = l+1; i <= r; i++)
          for (j = i; j > l; j--) 
            { if (less(a, j-1, j)) break; exch(a, j-1, j); }
      }
    static void arrayInitRand(double a[], int l, int r)
      { int i; 
        for (i = l; i <= r; i++)
          {
            a[i] =  Math.random(); 
            paint(i, a[i], Color.black);
          }
      }
    static void arrayInitRandEq(double a[], int l, int r)
      { int i; 
        for (i = l; i <= r; i++)
          {
            a[i] =  0.05 + ((int) (Math.random()*10))/10.0; 
            paint(i, a[i], Color.black);
          }
      }
    static void arrayInitRev(double a[], int l, int r)
      { int i; 
        for (i = l; i <= r; i++)
          {
            a[i] =  ((double) (r-i))/((double) (r-l)); 
            paint(i, a[i], Color.black);
          }
      }
    public void paint(Graphics page)
      {
        int alg = Integer.parseInt(getParameter("algorithm"));
        double[] a = new double[N];
        g = page;
        N = Integer.parseInt(getParameter("N"));
        dotsize = Integer.parseInt(getParameter("dotsize"));
        if (alg == 1)
          {
            arrayInitRand(a, 0, N-1);
            quicksort(a, 0, N-1);
            clear(Color.lightGray); arrayInitRand(a, 0, N-1);
            quicksortFAST(a, 0, N-1);
            insertion(a, 0, N-1);
          }
        if (alg == 2)
          {
            arrayInitRand(a, 0, N-1);
            arrayInitRev(a, 0, N/10);
            quicksort(a, 0, N-1);
            clear(Color.lightGray); arrayInitRev(a, 0, N-1);
            quicksortFAST(a, 0, N-1);
            insertion(a, 0, N-1);
          }
        if (alg == 3)
          {
            clear(Color.lightGray); arrayInitRandEq(a, 0, N-1);
            quicksortBAD(a, 0, N-1);
            clear(Color.lightGray); arrayInitRandEq(a, 0, N-1);
            quicksort(a, 0, N-1);
            clear(Color.lightGray); arrayInitRandEq(a, 0, N-1);
            quicksortEQ(a, 0, N-1);
            clear(Color.lightGray); arrayInitRandEq(a, 0, N-1);
            quicksortEQ(a, 0, N-1);
          }
      }
  }

