Løsningsforslag - oppgaver i Avsnitt 5.2.11


Oppgave 2

  Integer[] a = {4,8,3,1,7,4,9,1,6,10,2,1,5,10,7,8};        // tabell
  SFBinTre<Integer> tre = SFBinTre.sfbintre(Stream.of(a));  // et tre

  System.out.println(tre);                        // bruker toString
  for (int k : tre) System.out.print(k + "  ");   // bruker iteratoren

Oppgave 3

  public String toString()
  {
    if (tom()) return "[]";
    StringBuilder s = new StringBuilder();   // StringBuilder
    s.append('[');                           // starter med [

    Node<T> p = rot;
    while (p.venstre != null) p = p.venstre;
    s.append(p.verdi);

    while (true)
    {
      if (p.høyre != null)
      {
        p = p.høyre;
        while (p.venstre != null) p = p.venstre;
      }
      else
      {
        while (p.forelder != null && p.forelder.høyre == p)
        {
          p = p.forelder;
        }
        p = p.forelder;
      }
      if (p == null) break;
      s.append(',').append(' ').append(p.verdi);
    }
    s.append(']');

    return s.toString();
  }

Oppgave 4

  public String omvendtString()
  {
    if (tom()) return "[]";
    StringBuilder s = new StringBuilder();   // StringBuilder
    s.append('[');                           // starter med [

    Node<T> p = rot;
    while (p.høyre != null) p = p.høyre;
    s.append(p.verdi);

    while (true)
    {
      if (p.venstre != null)
      {
        p = p.venstre;
        while (p.høyre != null) p = p.høyre;
      }
      else
      {
        while (p.forelder != null && p.forelder.venstre == p)
        {
          p = p.forelder;
        }
        p = p.forelder;
      }
      if (p == null) break;
      s.append(',').append(' ').append(p.verdi);
    }
    s.append(']');

    return s.toString();
  }

Oppgave 5

Oppgave 6

  /////////// class InordenIterator //////////////

  private class InordenIterator implements Iterator<T>
  {
    private Node<T> p = null;
    private Node<T> q = null;
    private int iteratorendringer;

    private Node<T> først(Node<T> q)   // en hjelpemetode
    {
      while (q.venstre != null)        // starter i q
      {
        q = q.venstre;                 // går videre mot venstre
      }
      return q;                        // q er lengst ned til venstre
    }

    public InordenIterator()  // konstruktør
    {
      if (rot != null) p = først(rot);    // bruker hjelpemetoden
      iteratorendringer = endringer;
    }

    @Override
    public T next()
    {
      if (iteratorendringer != endringer)
        throw new ConcurrentModificationException();

      T verdi = p.verdi;             // tar vare på verdien i noden p
      q = p;                         // q er den forrige til p

      if (p.høyre != null)           // p har høyre subtre
      {
        p = først(p.høyre);          // går til venstre i subtreet
      }
      else                           // p har ikke høyre subtre
      {
        while (p.forelder != null && p.forelder.høyre == p)
        {
          p = p.forelder;            // fortsetter opp mot venstre
        }
        p = p.forelder;              // nå er p den neste (eller null)
      }
      return verdi;                  // returnerer verdien
    }

    @Override
    public boolean hasNext()
    {
      return p != null;
    }

    @Override
    public void remove()
    {
      if (q == null) throw new IllegalStateException("Fjerning er ulovlig!");

      if (iteratorendringer != endringer)
                 throw new ConcurrentModificationException("Treet er endret!");

      if (q.høyre == null)                     // Tilfelle 1)
      {
        // hvis q har et venstre barn, vil det når q
        // fjernes få ny forelder 

        if (q.venstre != null)
        {
          q.venstre.forelder = q.forelder;     // ny forelder
        }

        if (p == null)                         // Tilfelle 1a)
        {
          if (q == rot)                        // q er lik roten
          {
            rot = q.venstre;                   // q fjernes
          }
          else                                 // q ligger nede i treet
          {
            q.forelder.høyre = q.venstre;      // q fjernes
          }
        }
        else // p != null                      // Tilfelle 1b)
        {
          if (q == p.venstre)                  // p.venstre har ikke høyre subtre
          {
            p.venstre = q.venstre;             // q fjernes
          }
          else                                 // q ligger i subtreet
          {
            q.forelder.høyre = q.venstre;      // q fjernes
          }
        }
      }
      else // q.høyre != null                  // Tilfelle 2)
      {
        q.verdi = p.verdi;                     // kopierer

        // hvis p har et høyre barn, vil det når p
        // fjernes få en ny forelder

        if (p.høyre != null)
        {
          p.høyre.forelder = p.forelder;       // ny forelder    
        }

        if (q.høyre == p)                      // q.høyre har ikke venstre barn
        {
          q.høyre = p.høyre;                   // fjerner p
        }
        else                                   // q.høyre har venstre barn
        {
          p.forelder.venstre = p.høyre;        // fjerner p
        }

        p = q;                                 // setter p tilbake til q
      }


      q = null;                // q settes til null
      iteratorendringer++;     // en endring i treet via iteratoren
      endringer++;             // en endring i treet
      antall--;                // en verdi mindre i treet
    }

  } // class InordenIterator

Oppgave 7

  /////////// class InordenIterator //////////////

  private class InordenIterator implements Iterator<T>
  {
    private Node<T> p = null;
    private int iteratorendringer;
    private boolean removeOK = false;

    private Node<T> først(Node<T> q)   // en hjelpemetode
    {
      while (q.venstre != null)        // starter i q
      {
        q = q.venstre;                 // går videre mot venstre
      }
      return q;                        // q er lengst ned til venstre
    }

    public InordenIterator()  // konstruktør
    {
      if (rot != null) p = først(rot);    // bruker hjelpemetoden
      iteratorendringer = endringer;
    }

    @Override
    public T next()
    {
      if (iteratorendringer != endringer)
        throw new ConcurrentModificationException();

      T verdi = p.verdi;             // tar vare på verdien i noden p

      if (p.høyre != null)           // p har høyre subtre
      {
        p = først(p.høyre);          // går til venstre i subtreet
      }
      else                           // p har ikke høyre subtre
      {
        while (p.forelder != null && p.forelder.høyre == p)
        {
          p = p.forelder;            // fortsetter opp mot venstre
        }
        p = p.forelder;              // nå er p den neste (eller null)
      }

      removeOK = true;

      return verdi;                  // returnerer verdien
    }

    @Override
    public boolean hasNext()
    {
      return p != null;
    }

    @Override
    public void remove()
    {
      if (!removeOK)
        throw new IllegalStateException("Fjerning er ulovlig!");

      if (iteratorendringer != endringer)
        throw new ConcurrentModificationException("Treet er endret!");

      if (p == null)  // den siste skal fjernes
      {
        Node<T> q = rot;
        while (q.høyre != null) q = q.høyre;

        // q skal fjernes - har ikke høyre barn

        if (q.venstre != null)
        {
          q.venstre.forelder = q.forelder;  // oppdaterer forelder
        }

        if (q == rot)
        {
          rot = q.venstre;
        }
        else
        {
          q.forelder.høyre = q.venstre;
        }
      }
      else if (p.venstre != null)
      {
        Node<T> q = p.venstre;
        while (q.høyre != null) q = q.høyre;

        // q skal fjernes - har ikke høyre barn

        if (q.venstre != null)
        {
          q.venstre.forelder = q.forelder;  // oppdaterer forelder
        }

        if (q == p.venstre)
        {
          p.venstre = q.venstre;
        }
        else
        {
          q.forelder.høyre = q.venstre;
        }
      }
      else  // p.venstre == null
      {
        // vi må oppover mot roten

        Node<T> q = p;

        while (q.forelder.venstre == q)
        {
          q = q.forelder;            // fortsetter opp mot høyre
        }

        q = q.forelder;              // nå er q den forrige  

        // q skal fjernes

        if (q.venstre == null)  // q har kun ett barn
        {
          Node<T> f = q.forelder;

          q.høyre.forelder = f;  // oppdaterer forelder

          if (f == null)  // q er roten
          {
            rot = q.høyre;
          }
          else if (q == f.venstre)  // q er et venstre barn
          {
            f.venstre = q.høyre;
          }
          else                      // q er et høyre barn
          {
            f.høyre = q.høyre;
          }
        }
        else  // q har to barn
        {
          // verdien til p kopieres inn i q og p fjernes

          q.verdi = p.verdi;

          if (p.høyre != null)
          {
            p.høyre.forelder = p.forelder;
          }

          if (p == q.høyre)
          {
            q.høyre = p.høyre;
          }
          else
          {
            p.forelder.venstre = p.høyre;
          }

          p = q;
        }
      }

      removeOK = false;

      iteratorendringer++;     // en endring i treet via iteratoren
      endringer++;             // en endring i treet
      antall--;                // en verdi mindre i treet
    }

  } // class InordenIterator