import java.awt.*;
import Point;
class BSTtop
  {
    int N;
    Node head;
    int depth;

    int delay;
    Graphics page;

    void clear(Color c)
      { 
        int h = page.getClipRect().height;
        int w = page.getClipRect().width;
        page.setColor(c);
        page.fillRect(0, 0, w, h);
      }

    BSTtop(int N, int d, int sw, int delay, Graphics page)
      {
        this.page = page;
        this.head = null; this.depth = d; this.delay = delay;
        if (sw == 0)
          for (int i = 0; i < N; i++)
            {
              this.head = insert(this.head, Math.random(), 1);
              clear(Color.lightGray);
              drawTree(head, head);
            }
        if (sw == 1)
          for (int i = 0; i < N; i++)
            this.head = insert(this.head, ((double) i)/((double) N+1), 0);
        System.out.println(N + "-node tree built");
      }
    void maxmin()
      {
        this.delay = 1;
        while (head.r != null)
          {
            head = rotL(head);
            drawTree(head, head);
          }
        while (head.l != null)
          {
            head = rotR(head);
            drawTree(head, head);
          } 
      }
    void drawVertex(Point p, Color c)
      { 
        int h = page.getClipRect().height-16;
        int w = page.getClipRect().width-16;
        if (c == Color.white)
             page.setColor(Color.black);
        else page.setColor(Color.lightGray);
        page.fillOval( (int) (w*p.x)+6, (int) (h*p.y)+6, 16, 16);
        page.setColor(c);
        for (int j = 0; j < delay; j++)
          {
            page.fillOval( (int) (w*p.x)+8, (int) (h*p.y)+8, 16, 16);
          }
      }
    void drawEdge(Point p, Point q, Color c)
      { 
        int h = page.getClipRect().height-16;
        int w = page.getClipRect().width-16;
        page.setColor(c);
        page.drawLine( (int) (w*p.x)+16, (int) (h*p.y)+16, 
                         (int) (w*q.x)+16, (int) (h*q.y)+16);
        if (c == Color.lightGray)
          {
            page.drawLine( (int) (w*p.x)+17, (int) (h*p.y)+17, 
                         (int) (w*q.x)+17, (int) (h*q.y)+17);
            page.drawLine( (int) (w*p.x)+15, (int) (h*p.y)+15, 
                         (int) (w*q.x)+15, (int) (h*q.y)+15);
          }
      }
    Node rotL(Node h)
      {
        double offset, lim;
        lim = 1.0/((double) this.depth+1); offset = .005;
        for (double x = 0; x < lim; x += offset)
          {
            h.pt.y += offset; 
            moveTree(h.l, h, offset);
            if (h.r != null) 
              { h.r.pt.y -= offset; moveTree(h.r.r, h.r, -offset); }
          }
        Node x = h.r; h.r = x.l; x.l = h; 
        drawTree(x.l, x);
        return x;
      }
    Node rotR(Node h)
      {
        double offset, lim;
        lim = 1.0/((double) this.depth+1); offset = .005;
        for (double x = 0; x < lim; x += offset)
          {
            h.pt.y += offset; 
            moveTree(h.r, h, offset);
            if (h.l != null) 
              { h.l.pt.y -= offset; moveTree(h.l.l, h.l, -offset); }
          }
        Node x = h.l; h.l = x.r; x.r = h; 
        drawTree(x.r, x);
        return x;
      }
    void moveTree(Node h, Node p, double offset)
      {
        double y; 
        if (h == null) return;
        drawVertex(h.pt, Color.lightGray);
        drawVertex(p.pt, Color.lightGray);
        drawEdge(p.pt, h.pt, Color.lightGray);
        h.pt.y += offset; 
        drawEdge(p.pt, h.pt, Color.black);
        drawVertex(h.pt, Color.white);
        drawVertex(p.pt, Color.white);
        moveTree(h.l, h, offset);
        moveTree(h.r, h, offset);
      }
    void drawTree(Node h, Node p)
      {
        if (h == null) return;
        drawEdge(p.pt, h.pt, Color.black);
        drawVertex(h.pt, Color.white);
        drawVertex(p.pt, Color.white);
        drawTree(h.l, h);
        drawTree(h.r, h);
      }
    Node insert(Node h, double v, int d)
      {
        if (h == null) 
          {
            double sy = ((double) d)/((double) this.depth+1);
            Point s = new Point(v, sy);
            return new Node(v, d+1, s);
          }
        drawVertex(h.pt, Color.red);
        if (v < h.v) 
	  { h.l = insert(h.l, v, d+1); h = rotR(h); }
        else 
	  { h.r = insert(h.r, v, d+1); h = rotL(h); }
        drawVertex(h.pt, Color.white);
        return h;
      }
  }










