Algoritmer og datastrukturer
Løsningsforslag

Eksamen  −  2. desember 2009

Oppgave 1A

Hvis vi ser på tabellene a = {1,2,3,4,5} og b = {3,4,5,6,7} som to mengder, vil metoden ukjent gjøre at tabellen c vil inneholde den eksklusive unionen (eller det som også kalles den symmetriske differensen) til a og b, dvs. (ab) U (ba) = {1,2,6,7}. Returverdien er antall elementer i den eksklusive unionen. Utskriften blir: 1 2 6 7

Oppgave 1B

Først legges A, B og C i køen. Så tas den første (dvs. A) ut og legges inn bakerst. Dermed inneholder køen B C A. Dette gjentas to ganger. Dvs. køen vil deretter inneholde C A B og til slutt A B C. Dermed blir utskriften: A B C.

Oppgave 1C

Verdiene fra de to køene sammenlignes parvis, tas ut og legges inn (bakerst). Hvis det kommer et par som er ulike, stopper sammenligningene og det som eventuelt er igjen i køene, tas ut og legges inn. Dermed vil køene være som de var.

  public static <T> boolean erLike(Kø<T> A, Kø<T> B)
  {
    // De må ha samme antall for å kunne være like
    if (A.antall() != B.antall()) return false;

    boolean erLike = true;
    int n = A.antall(), i = 0;

    for (; i < n && erLike; i++)
    {
      erLike = A.kikk().equals(B.kikk());
      A.leggInn(A.taUt());  // tar ut og legger inn
      B.leggInn(B.taUt());  // tar ut og legger inn
    }

    for (; i < n; i++)      // tar med resten av køene
    {
      A.leggInn(A.taUt());  // tar ut og legger inn
      B.leggInn(B.taUt());  // tar ut og legger inn
    }

    return erLike;
  }

Oppgave 2A

  public static String toString(int[] a)
  {
    if (a == null) return null;

    if (a.length == 0) return "[]";

    StringBuilder s = new StringBuilder();

    s.append('[');
    s.append(a[0]);

    for (int i = 1; i < a.length; i++)
    {
      s.append(',');
      s.append(' ');
      s.append(a[i]);
    }

    s.append(']');

    return s.toString();
  }

Oppgave 2B

Huffmantreet for A, B, C, D, E, F og G


  A = 00
  B = 110
  C = 0100
  D = 011
  E = 10
  F = 111
  G = 0101

  Delsekvensen var ABCDEFG






Oppgave 2C

  private static Node byggHuffmanTre(String[] koder)
  {
    Node rot = new Node();

    for (int i = 0; i < koder.length; i++)
    {
      String s = koder[i];
      if (s != null)  // tegnet med ascii-verdi lik i er med
      {
        Node p = rot;
        for (int j = 0; j < s.length(); j++)
        {
          if (s.charAt(j) == '0')
          {
            if (p.venstre == null) p.venstre = new Node();
            p = p.venstre;
          }
          else
          {
            if (p.høyre == null) p.høyre = new Node();
            p = p.høyre;
          }
        }
        p.tegn = (char)i;  // legger tegnet i bladnoden
      }
    }
    return rot;
  }

Oppgave 3A

Tallene 12, 8, 10, 17, 14, 2, 5, 20, 4, 7

Tallene 8, 12, 10, 17, 5, 7, 4, 20, 2, 14

Oppgave 3B

  public T nestMinst()
  {
    if (antall < 2) throw new
      NoSuchElementException("Treet har færre enn to noder!");

    Node<T> p = rot, f = null;

    while (p.venstre != null)
    {
      f = p;  // f er forelder til p
      p = p.venstre;
    }

    if (p.høyre == null) return f.verdi;

    p = p.høyre;

    while (p.venstre != null)
    {
      p = p.venstre;
    }
    return p.verdi;
  }

Oppgave 3C

Tallene 2, 4, 5, 7, 8, 10
public boolean erFullstendigHøyreskjevt()
{
  Node<T> p = rot;

  while (p != null)
  {
    if (p.venstre != null) return false;
    p = p.høyre;
  }

  return true;
}



Oppgave 3D

  private static <T> Node<T> hRotasjon(Node<T> p)
  {
    Node<T> q = p.venstre;

    p.venstre = q.høyre;
    q.høyre = p;

    return q;
  }
En høyrerotasjon på roten i det første treet
En høyrerotasjon på roten i det andre treet

Første versjon av metoden gjørFullstendigHøyreskjevt:

Det enkleste er å først gjøre en serie rotasjoner på rotnoden inntil den ikke lenger har venstre barn. Deretter fortsetter vi på nodene nedover mot høyre fra rotnoden:

  public void gjørFullstendigHøyreskjevt()
  {
    if (tom()) return;

    while (rot.venstre != null) rot = hRotasjon(rot);

    Node<T> p = rot;

    while (p.høyre != null)
    {
      while (p.høyre.venstre != null) p.høyre = hRotasjon(p.høyre);
      p = p.høyre;
    }

Andre versjon av metoden gjørFullstendigHøyreskjevt:

Dette kan gjøres på mange måter. Hvis treet traverseres i inorden, kan pekerne endres under traverseringen. Alternativt kan nodene legges fortløpende f.eks. over en kø. Deretter lages det et fullstendig høyreskjevt tre ved å ta ut én og én node fra køen og for hver node gjøre noden til høyre barn til forrige node:

  private static <T> void inorden(Node<T> p, Kø<Node<T>> kø)
  {
    if (p.venstre != null) inorden(p.venstre, kø);
    kø.leggInn(p);
    if (p.høyre != null) inorden(p.høyre, kø);
  }

  public void gjørFullstendigHøyreskjevt2()
  {
    if (tom()) return;

    Kø<Node<T>> kø = new TabellKø<Node<T>>();
    inorden(rot,kø);

    rot = kø.taUt();     // den første blir ny rot
    rot.venstre = null;

    Node<T> p = rot;
    while (!kø.tom())
    {
      p.høyre = kø.taUt();
      p = p.høyre;
      p.venstre = null;
    }
  }