Løsningsforslag - oppgaver i Avsnitt 5.1.10


Oppgave 1

  private static <T> void preorden(Node<T> p, Oppgave<? super T> oppgave)
  {
    while (true)
    {
      oppgave.utførOppgave(p.verdi);
      if (p.venstre != null) preorden(p.venstre,oppgave);
      if (p.høyre == null) return;      // metodekallet er ferdig
      p = p.høyre;
    }
  }

Oppgave 4

  private static <T> void inorden(Node<T> p, Oppgave<? super T> oppgave)
  {
    while (true)
    {
      if (p.venstre != null) inorden(p.venstre,oppgave);
      oppgave.utførOppgave(p.verdi);
      if (p.høyre == null) return;      // metodekallet er ferdig
      p = p.høyre;
    }
  }

Oppgave 6

  public void preorden(Oppgave<? super T> oppgave)
  {
    Object[] a = new Object[10];
    int k = 0;
    a[k++] = null;

    Node<T> p = rot;    // starter i roten

    while (p != null)
    {
      oppgave.utførOppgave(p.verdi);

      if (p.venstre != null)
      {
        if (p.høyre != null)
        {
          if (k == a.length) a = Arrays.copyOf(a,2*k);
          a[k++] = p.høyre;
        }
        p = p.venstre;
      }
      else if (p.høyre != null)  // nå er p.venstre lik null
      {
        p = p.høyre;
      }
      else  // nå er både p.venstre og p.høyre lik null
      {
        p = (Node<T>)a[--k];
      }
    }
  }

Oppgave 7

Oppgave 8

Omvendt preorden er lik speilvendt postorden. Vi får iterativ speilvendt postorden ved å bruke den postorden-metoden og der bytte om høyre og venstre. For å øke lesbarheten lager vi en hjelpemetode som finner den siste i postorden i treet som har p som rot:

  private static <T> Node<T> sistPostorden(Node<T> p, Stakk<Node<T>> stakk)
  {
    while (true)
    {
      stakk.leggInn(p);
      if (p.høyre != null) p = p.høyre;
      else if (p.venstre != null) p = p.venstre;
      else return stakk.taUt();
    }
  }

  public void omvendtPreorden(Oppgave<? super T> oppgave)
  {
    if (tom()) return;
    Stakk<Node<T>> stakk = new TabellStakk<>();
    Node<T> p = sistPostorden(rot, stakk);              // hjelpemetoden

    while (true)                                        // fortsetter
    {
      oppgave.utførOppgave(p.verdi);                    // oppgaven

      if (stakk.tom()) return;                          // ferdig
      Node<T> f = stakk.kikk();                         // f for forelder

      if (f.venstre == null || p == f.venstre)
        p = stakk.taUt();                               // går oppover
      else p = sistPostorden(f.venstre, stakk);         // hjelpemetoden
    }
  }

Omvendt og speilvendt inorden er det samme. Vi får derfor omvendt inorden ved å bytte om høyre og venstre i den iterative inorden-metoden:

  public void omvendtInorden(Oppgave<? super T> oppgave)  // iterativ inorden
  {
    if (tom()) return;            // tomt tre

    Stakk<Node<T>> stakk = new TabellStakk<>();
    Node<T> p = rot;   // starter i roten og går til høyre
    for ( ; p.høyre != null; p = p.høyre) stakk.leggInn(p);

    while (true)
    {
      oppgave.utførOppgave(p.verdi);  // oppgaven utføres

      if (p.venstre != null)          // til høyre i venstre subtre
      {
        for (p = p.venstre; p.høyre != null; p = p.høyre)
        {
          stakk.leggInn(p);
        }
      }
      else if (!stakk.tom())
      {
        p = stakk.taUt();   // p.høyre == null, henter fra stakken
      }
      else break;          // stakken er tom - vi er ferdig
    } // while
  }

Omvendt postorden er lik speilvendt preorden. Vi får iterativ speilvendt preorden ved å bruke den iterative preorden-metoden og der bytte om høyre og venstre:

  public void omvendtPostorden(Oppgave<? super T> oppgave)   // ny versjon
  {
    if (tom()) return;

    Stakk<Node<T>> stakk = new TabellStakk<>();
    Node<T> p = rot;    // starter i roten

    while (true)
    {
      oppgave.utførOppgave(p.verdi);

      if (p.høyre != null)
      {
        if (p.venstre != null) stakk.leggInn(p.venstre);
        p = p.høyre;
      }
      else if (p.venstre != null)  // her er p.venstre lik null
      {
        p = p.venstre;
      }
      else if (!stakk.tom())     // her er p en bladnode
      {
        p = stakk.taUt();
      }
      else                       // p er en bladnode og stakken er tom
        break;                   // traverseringen er ferdig
    }
  }

Oppgave 9

  public void inorden(Oppgave<? super T> oppgave)
  {
    if (rot == null) return;    // tomt tre

    Node<T> p = rot;
    long k = 1;

    while (p.venstre != null)   // går til venstre
    {
      k <<= 1;
      p = p.venstre;
    }

    while (true)
    {
      oppgave.utførOppgave(p.verdi);  // oppgaven utføres

      if (p.høyre != null)            // til venstre i høyre subtre
      {
        p = p.høyre;
        k <<= 1;
        k |= 1;                       // legger på 1 bakerst
        while (p.venstre != null)     // går til venstre
        {
          k <<= 1;
          p = p.venstre;
        }
      }
      else  // p.høyre == null
      {
        while ((k & 1) != 0) k >>= 1;
        k >>= 1;    // k er nå posisjonen til den neste
        if (k == 0) return;

        p = rot;  // starter i roten og nedover til k
        long n = Long.highestOneBit(k >> 1);
        while (n > 0)
        {
          p = (n & k) == 0 ? p.venstre : p.høyre;
          n >>= 1;  // bitforskyver n
        }
      }
    }
  }

Oppgave 10

  public void preorden(Oppgave<? super T> oppgave)    // iterativ versjon
  {
    if (rot == null) return;

    Node<T> p = rot;
    long k = 1;

    while (true)
    {
      oppgave.utførOppgave(p.verdi);

      if (p.venstre != null)
      {
        p = p.venstre;
        k <<= 1;  // 0 bakerst
      }
      else if (p.høyre != null)
      {
        p = p.høyre;
        k <<= 1;
        k |= 1;  // 1 bakerst
      }
      else
      {
        Node<T> q = null;
        int k1 = 1;
        int k2 = 0;  // posisjonen til neste
        p = rot;
        long n = Long.highestOneBit(k >> 1);

        while (n > 0)
        {
          if ((n & k) == 0)
          {
            k1 <<= 1;  // 0 bakerst
            if (p.høyre != null)
            {
              q = p.høyre;
              k2 = k1 | 1;
            }
            p = p.venstre;
          }
          else
          {
            p = p.høyre;
            k1 <<= 1;
            k1 |= 1;  // 1 bakerst
          }
          n >>= 1;
        }
        if (q == null) return;
        p = q;
        k = k2;  // posisjonen til neste
      }
    }
  }