Lausnum skal skilað til viðkomandi dæmakennara (sjá lista yfir dæmatíma).
Reynið að skrifa stutt, skýr og hnitmiðuð forrit. Notið réttan inndrátt og gætið þess að forritin ykkar séu læsileg.
Skiladagur: þriðjudaginn 17. apríl fyrir kl 16:00
Bætið eftirfarandi runu af gildum í tóman skopplista: E A S Y Q U T I O N. Kastið krónu til að ákveða framgöngu. Teiknið mynd af skopplistanum eftir að öll gildin hafa verið sett í hann.
Skrifið fall sem tekur inn tilvísun á rótarhnút í tré og prentar út hnútana á hverri hæð í röð frá efstu hæð til neðstu með eina hæð per línu.
Dæmi: fyrir eftirfarandi tré myndi fallið prenta út
A
/ \
B C
/ \ /
D E F
Level 0: A Level 1: B C Level 2: D E F
import java.util.LinkedList;
import java.util.Queue;
public class BinaryTree
{
private String val;
private BinaryTree left, right;
private int level;
public BinaryTree(BinaryTree left, BinaryTree right, String val, int level)
{
this.left = left;
this.right = right;
this.val = val;
this.level = level;
}
public static void levelPrint(BinaryTree root)
{
if (root == null)
return;
Queue<BinaryTree> q = new LinkedList<BinaryTree>();
q.offer(root);
int lastLevel = -1;
while (!q.isEmpty())
{
BinaryTree x = q.remove();
if (lastLevel < 0)
System.out.printf("Level %d: %s ", x.level, x.val);
else if (lastLevel != x.level)
System.out.printf("\nLevel %d: %s ", x.level, x.val);
else
System.out.print(x.val + " ");
if (x.left != null)
q.offer(x.left);
if (x.right != null)
q.offer(x.right);
lastLevel = x.level;
}
System.out.println();
}
public static void main(String[] args)
{
BinaryTree D = new BinaryTree(null, null, "D", 2);
BinaryTree E = new BinaryTree(null, null, "E", 2);
BinaryTree B = new BinaryTree(D, E, "B", 1);
BinaryTree F = new BinaryTree(null, null, "F", 2);
BinaryTree C = new BinaryTree(F, null, "C", 1);
BinaryTree A = new BinaryTree(B, C, "A", 0);
BinaryTree.levelPrint(A);
}
}
Skrifið klasa sem uppfyllir eftirfarandi skil (interface) fyrir mengi strengja. Útfærið klasann þannig að hann geymi strengina í menginu í tengdum lista. Ef streng er bætt við sem er þegar í menginu þá á að gæta þess að hann sé ekki tvískráður í listann.
Með klasanum á að fylgja fastayrðing gagna sem lýsir þeirri gagnaskipan sem er notuð í útfærslunni. Tilgreinið einnig tímaflækju add og contains.
Skil (interface) fyrir mengi strengja:
public interface StringSet
{
// Notkun: set.add(s);
// Fyrir: Ekkert
// Eftir: Búið er að bæta strengnum s í mengið set.
void add(String s);
// Notkun: b = set.contains(s);
// Fyrir: Ekkert
// Eftir: b er satt þþaa. s er í set.
boolean contains(String s);
}
public class StringSetList implements StringSet
{
private static class Node
{
String s;
Node next;
}
private Node head;
// Öll gildi í menginu eru í keðjunni head í engri
// sérstakri röð.
// Notkun: set = new StringSetList();
// Fyrir: Ekkert
// Eftir: set er nýtt tómt mengi strengja
public StringSetList()
{
head = null;
}
// Notkun: set.add(s);
// Fyrir: Ekkert
// Eftir: Búið er að bæta strengnum s í mengið set.
public void add(String s)
{
if (contains(s))
return;
Node p = new Node();
p.s = s;
p.next = head;
head = p;
}
// Notkun: b = set.contains(s);
// Fyrir: Ekkert
// Eftir: b er satt þþaa. s er í set.
public boolean contains(String s)
{
Node p = head;
while (p != null)
{
if (s.equals(p.s))
return true;
p = p.next;
}
return false;
}
public static void main(String[] args)
{
StringSetList set = new StringSetList();
set.add("A");
set.add("B");
set.add("C");
set.add("D");
System.out.println("A: " + set.contains("A"));
System.out.println("B: " + set.contains("B"));
System.out.println("C: " + set.contains("C"));
System.out.println("D: " + set.contains("D"));
System.out.println("E: " + set.contains("E"));
System.out.println("F: " + set.contains("F"));
}
}
public class StringSetList implements StringSet
{
private static class Node
{
String str;
Node next;
}
private Node head;
// Strengirnir í menginu eru í keðjunni head í vaxandi
// stafrófsröð.
public void add(String str)
{
if (head == null || head.str.compareTo(str) > 0)
{
Node n = new Node();
n.str = str;
n.next = head;
head = n;
return;
}
if (head.str.compareTo(str) == 0)
return;
Node p = head;
while (p.next != null)
{
// p er keðja sem er aftari hluti keðjunnar head.
// Hlekkurinn p og fremri hlekkir innihalda strengi
// sem eru framar en str í stafrófsröð.
int cmp = p.next.str.compareTo(str);
if (cmp == 0)
return;
else if (cmp > 0)
break;
p = p.next;
}
Node n = new Node();
n.str = str;
n.next = p.next;
p.next = n;
}
public boolean contains(String str)
{
Node p = head;
while (p != null)
{
// p bendir á aftari hluta keðjunnar head (má vera tóm keðja).
// Sá hluti keðjunnar sem er fyrir framan p inniheldur ekki str.
int cmp = p.str.compareTo(str);
if (cmp == 0)
return true;
else if (cmp > 0)
return false;
p = p.next;
}
return false;
}
public static void main(String[] args) throws Exception
{
StringSetList set = new StringSetList();
set.add("A");
set.add("B");
set.add("C");
set.add("D");
System.out.println("A: " + set.contains("A"));
System.out.println("B: " + set.contains("B"));
System.out.println("C: " + set.contains("C"));
System.out.println("D: " + set.contains("D"));
System.out.println("E: " + set.contains("E"));
System.out.println("F: " + set.contains("F"));
}
}
Skrifið klasa sem uppfyllir skilin (interface) fyrir mengi strengja sem voru gefin upp í dæmi 3. Útfærið klasann þannig að hann geymi strengina í menginu í HashMap (útfærsla á fjölnota tætitöflu sem fylgir með Java).
Skrifið fastayrðingu gagna fyrir þá gagnaskipan sem er notuð í útfærslunni. Tilgreinið tímaflækju add og contains.
Þeir sem vilja mega alveg útfæra tætitöfluna sjálfir í staðinn fyrir að nota HashMap.
import java.util.LinkedList;
public class StringSetMap
{
private LinkedList<String>[] st;
private int N;
private int M;
// Öll gildi í menginu eru í listunum st[0..M-1]
// N er heildarfjöldi gilda í menginu
// st[h] inniheldur öll gildi í menginu sem hafa tætigildi h
// (þ.e. öll gildi x þar sem hash(x) = i)
@SuppressWarnings({"unchecked"})
public StringSetMap(int M)
{
this.st = (LinkedList<String>[]) new LinkedList[M];
this.M = M;
this.N = 0;
}
private void resize(int chains)
{
StringSetMap temp = new StringSetMap(chains);
for (int i = 0; i < M; i++)
{
for (String key : st[i])
{
temp.add(key);
}
}
this.M = temp.M;
this.N = temp.N;
this.st = temp.st;
}
private int hash(String key)
{
return (key.hashCode() & 0x7fffffff) % M;
}
public boolean contains(String key)
{
int i = hash(key);
if (st[i] == null)
return false;
return st[i].contains(key);
}
public void add(String key)
{
if (N >= 10*M)
resize(2*M);
int i = hash(key);
if (st[i] == null)
st[i] = new LinkedList<String>();
else if (st[i].contains(key))
return;
st[i].add(key);
N++;
}
public static void main(String[] args)
{
StringSetMap set = new StringSetMap(1000);
set.add("A");
set.add("B");
set.add("C");
set.add("D");
System.out.println("A: " + set.contains("A"));
System.out.println("B: " + set.contains("B"));
System.out.println("C: " + set.contains("C"));
System.out.println("D: " + set.contains("D"));
System.out.println("E: " + set.contains("E"));
System.out.println("F: " + set.contains("F"));
}
}
Gerum ráð fyrir að við séum með forrit sem þarf að byggja risastórt mengi af strengjum og það sé ekki pláss fyrir alla strengina í minni. Gerum ennfremur ráð fyrir því að við séum tilbúin að sætta okkur við eftirfarandi breytingu á contains í StringSet:
public interface StringSet
{
// Notkun: set.add(s);
// Fyrir: Ekkert
// Eftir: Búið er að bæta strengnum s í mengið set.
void add(String s);
// Notkun: b = set.contains(s);
// Fyrir: Ekkert
// Eftir: Ef b er satt þá er s kannski í set,
// en ef b er ósatt þá er s bókað ekki í set.
boolean contains(String s);
}
Við erum semsagt tilbúin að sætta okkur við ranglega jákvæð svör (tilfelli þar sem contains skilar true en s er í raun ekki í set), en ekki ranglega neikvæð svör (ef contains skilar false þá er s bókað ekki í menginu).
Skrifið klasa sem uppfyllir ofangreind skil. Útfærið klasann með því að nota tætingu og BitSet.
Útfærslan í þessu dæmi líkist einfaldri útgáfu af svokölluðum bloom filters. Áhugasamir nemendur geta lesið um þá á Wikipedia.
public class StringSetBitSet
{
private BitSet bs;
private int n;
public StringSetBitSet(int n)
{
bs = new BitSet(n);
this.n = n;
}
public boolean contains(String s)
{
int h = (s.hashCode() & 0x7fffffff) % n;
return bs.get(h);
}
public void add(String s)
{
int h = (s.hashCode() & 0x7fffffff) % n;
bs.set(h);
}
public static void main(String[] args)
{
StringSetBitSet set = new StringSetBitSet(1000);
set.add("A");
set.add("B");
set.add("C");
set.add("D");
System.out.println("A: " + set.contains("A"));
System.out.println("B: " + set.contains("B"));
System.out.println("C: " + set.contains("C"));
System.out.println("D: " + set.contains("D"));
System.out.println("E: " + set.contains("E"));
System.out.println("F: " + set.contains("F"));
}
}