fakult¨at f¨ur informatik

Werbung
TECHNISCHE UNIVERSITÄT MÜNCHEN
FAKULTÄT FÜR INFORMATIK
Lehrstuhl für Sprachen und Beschreibungsstrukturen
Einführung in die Informatik I
Prof. Dr. Helmut Seidl, A. Lehmann, A. Herz, Dr. M. Petter
SS 2011
Übungsblatt 7
16.06.11
Abgabe: 26.06.11 (vor 12 Uhr)
Aufgabe 7.1 (P) Rationale Zahlen
Implementieren Sie die Klasse Rational zur Repräsentation rationaler Zahlen aus der Vorlesung. Definieren Sie neben einem geeigneten Konstruktor für die Klasse auch ObjektMethoden für folgende Operationen:
Anmerkung: Die Bruchzahl soll stets in gekürzter Form gespeichert werden.
a) Addition: Rational add(Rational r)
b) Subtraktion: Rational sub(Rational r)
c) Multiplikation: Rational mul(Rational r)
d) Division: Rational div(Rational r)
e) Dezimalwert: double decimal()
Der Aufruf r.decimal() soll den dezimalen Wert von r berechnen und zurückliefern.
f) Vergleich: int compareTo(Rational r)
Der Aufruf r1.compareTo(r2) soll −1 zurückliefern falls x1 < x2 , 0 falls x1 = x2 und
schließlich 1 falls x1 > x2 . Dabei sollen x1 und x2 die Werte sein, die durch die Objekte
r1 und r2 repräsentiert werden.
g) Duplizieren: Rational clone() Der Aufruf r.clone() soll eine Kopie von r erstellen
und zurückliefern.
Lösungsvorschlag 7.1
public c l a s s R a t i o n a l {
// D e k l a r a t i o n d e r Komponenten e i n e r r a t i o n a l e n Z a h l
private int z a e h l e r , nenner ;
/∗ Bestimmung d e s g r o e s s t e n gemeinsamen T e i l e r s von n und m
mit dem e u k l i d s c h e n A l g o r i t h m u s ∗/
private s t a t i c int ggT ( int n , int m) {
i f ( ( n == 0 ) | | (m == 0 ) ) {
// Abbruch b e i Eingabe ( m i n d e s t e n s ) e i n e r 0 => t e i l e r f r e i
return 0 ;
} else {
while ( n != m) {
// annaehern d e s ggT durch s u k z e s s i v e s a b z i e h e n
i f ( n > m) {
n = n−m;
} else {
m = m−n ;
}
}
}
// r u e c k g a b e d e s ggT durch n
return n ;
}
2
// E r s t e l l e n e i n e r r a t i o n a l e n z a h l aus z w e i ganzen Zahlen
public R a t i o n a l ( int z , int n ) {
i f ( n == 0 ) // Eingabe u e b e r p r u e f u n g
throw new I l l e g a l A r g u m e n t E x c e p t i o n ( ” D i v i s i o n by z e r o ”) ;
// z u w e i s e n d e r Parameter
zaehler = z ;
nenner = n ;
// E n t f e r n e n u n n o e t i g e r V o r z e i c h e n und p o s i t i v e n z a e h l e r s i c h e r s t e l l e n
int s i g n = I n t e g e r . signum ( nenner ) ;
zaehler = sign ∗ zaehler ;
nenner = s i g n ∗ nenner ;
k u e r z e n ( ) ; // s i c h e r s t e l l e n , d a s s d i e Z a h l g e k u e r z t
gespeichert ist
}
// E r s t e l l e n e i n e r r a t i o n a l e n z a h l aus e i n e r ganzen Zahlen
public R a t i o n a l ( int z ) {
t h i s ( z , 1 ) ; // A u f r u f d e s o b i g e n K o n s t r u k t o r s mit
Zaehler 1
}
// a d d i e r n von r z u r a k t u e l l e n Z a h l
public R a t i o n a l add ( R a t i o n a l r ) {
return new R a t i o n a l ( // r u e c k g a b e d e s E r g e b n i s s e s a l s
neue r a t i o n a l e z a h l
z a e h l e r ∗ r . nenner + r . z a e h l e r ∗ nenner ,
nenner ∗ r . nenner ) ; // e r w e i t e r n und a d d i e r e n
} // k u e r z e n f i n d e t im k o n s t r u c t o r s t a t t
// m u l t i p l i z i e r e n von r mit d e r a k t u e l l e n Z a h l
public R a t i o n a l mul ( R a t i o n a l r ) {
return new R a t i o n a l ( z a e h l e r ∗ r . z a e h l e r , nenner ∗ r .
nenner ) ;
}
// s u b t r a h i e r e n von r von d e r a k t u e l l e n Z a h l durch A d d i t i o n von −r
public R a t i o n a l sub ( R a t i o n a l r ) {
return add ( r . mul (new R a t i o n a l ( −1) ) ) ;
}
// H i l f s f u n k t i o n f u e r D i v i s i o n . bestimmt Kehrwert d e r a k t u e l l e n Z a h l
public R a t i o n a l r e c i p r o c a l ( ) {
return new R a t i o n a l ( nenner , z a e h l e r ) ;
}
// D i v i s i o n d e r a k t u e l l e n Z a h l durch r durch Mult . mit Kehrwert von r
public R a t i o n a l d i v ( R a t i o n a l r ) {
return mul ( r . r e c i p r o c a l ( ) ) ;
}
// Umwandlung von z a e h l e r und nenner i n e i n e Gleitkommazahl
public double d e c i m a l ( ) {
return ( double ) z a e h l e r / ( double ) nenner ;
}
public int compareTo ( R a t i o n a l r ) {
// V o r a u s s e t z u n g : Nenner s i n d p o s i t i v
3
int z1 = z a e h l e r ∗ r . nenner ; // i m p l i z i t e s e r w e i t e r n d e r
aktuellen zahl
int z2 = r . z a e h l e r ∗ nenner ; // i m p l i z i t e s e r w e i t e r n von r
i f ( z1 < z2 ) { // v e r g l e i c h d e r e r w e i t e r t e n Z a e h l e r
return −1;
} e l s e i f ( z1 > z2 ) {
return 1 ;
}
return 0 ; // weder k l e i n e r noch g r o e s s e r
}
// G l e i c h h e i t s t e s t m i t t e l s compareTo
public boolean e q u a l s ( R a t i o n a l r ) {
return compareTo ( r ) == 0 ;
}
// e r z e u g e n e i n e r neuen r a t i o n a l e n z a h l mit dem z a e h l e r und
nenner d e r a k t u e l l e n z a h l
public R a t i o n a l c l o n e ( ) {
return new R a t i o n a l ( z a e h l e r , nenner ) ;
}
// k u e r z e n d e r a k t u e l l e n Z a h l durch D i v i s i o n durch den ggT von
Z a e h l e r und Nenner
public void k u e r z e n ( ) {
// ggT a u f r u f mit dem B e t r a g d e s z a e h l e r s und dem (
ohnehin p o s i t i v e n ) Nenner
int ggT = ggT ( I n t e g e r . signum ( z a e h l e r ) ∗ z a e h l e r , nenner ) ;
i f ( ggT > 1 ) { // k u e r z e n f a l l s n i c h t t r i v i a l e r ggT
vorhanden
z a e h l e r = z a e h l e r / ggT ;
nenner = nenner / ggT ;
}
}
// Umwandlung d e r Z a h l i n e i n e n
public S t r i n g t o S t r i n g ( )
i f ( nenner == 1 )
return z a e h l e r +
}
( formatierte ) Stringdarstellung
{
return ” ” + z a e h l e r ;
”/ ” + nenner ;
}
Aufgabe 7.2 (P) Einfach verkettete Liste
Einfach verkettete Integer-Listen bestehen aus einer Kette von Elementen. Jedes Element
besteht aus einer Zahl (info) und der Referenz (next) auf den Rest der Liste. Die leere
Liste wird durch null repräsentiert.
a) Erstellen Sie eine Klasse IntList. Implementieren Sie einen passenden Konstruktor,
der die Attribute info und next initialisiert.
b) Implementieren Sie eine Methode append(int info), die eine neue Liste zurückgibt,
die eine Kopie der aktuellen Liste ist, an deren Ende ein neues Element mit Zahl info,
angefügt wurde.
c) Implementieren Sie eine Methode public String toString(), die alle Elemente der
Liste als String zurückgibt.
d) Implementieren Sie eine Methode sum(), die die Summe aller Listenelemente zurück-
4
gibt.
e) Implementieren Sie eine Methode reverse(), die eine neue Liste zurückgibt, welche
die Zahlen der aktuellen Liste in umgekehrter Reihenfolge enthält.
Lösungsvorschlag 7.2
public c l a s s I n t L i s t {
private int
info ;
private I n t L i s t next ;
// t h e i n t d a t a o f t h i s l i s t e l e m e n t
// t h e r e s t o f t h e l i s t
/∗ ∗
∗ S e t s up a new i n s t a n c e o f I n t L i s t c o r r e s p o n d i n g t o t h e g i v e n
i n f o and
∗ next .
∗ @param i n f o t h e i n t d a t a o f t h i s l i s t e l e m e n t
∗ @param n e x t t h e r e s t o f t h e l i s t
∗/
public I n t L i s t ( int i n f o , I n t L i s t next ) {
this . i n f o = i n f o ;
t h i s . next = next ;
}
/∗ ∗
∗ A new l i s t where t h e g i v e n i n f o has been appended .
∗ @param i n f o t h e i n t d a t a o f t h e new l i s t e l e m e n t
∗ @return
a new i n s t a n c e o f I n t L i s t
∗/
public I n t L i s t append ( int i n f o ) {
i f ( next == null )
return new I n t L i s t ( t h i s . i n f o , new I n t L i s t ( i n f o , null ) ) ;
else
return new I n t L i s t ( t h i s . i n f o , next . append ( i n f o ) ) ;
}
/∗ ∗
∗ Computes t h e sum o f a l l e l e m e n t s o f t h i s l i s t .
∗ @return
t h e sum o f a l l e l e m e n t s
∗/
public int sum ( ) {
i f ( next == null )
return i n f o ;
else
return i n f o + next . sum ( ) ;
}
/∗ ∗
∗ Auxiliary function for the reversal of t h i s l i s t .
∗ @param acc
t h e l i s t e l e m e n t s a c c u m u l a t e d so f a r
∗ @return
a new i n s t a n c e o f I n t L i s t
∗/
private I n t L i s t r e v e r s e A u x ( I n t L i s t a c c ) {
i f ( next == null )
return new I n t L i s t ( i n f o , a c c ) ;
else
5
return next . r e v e r s e A u x (new I n t L i s t ( i n f o , a c c ) ) ;
}
/∗ ∗
∗ A new l i s t w i t h t h e e l e m e n t s o f t h i s l i s t i n r e v e r s e o r d e r .
∗ @return
a new i n s t a n c e o f I n t L i s t
∗/
public I n t L i s t r e v e r s e ( ) {
return r e v e r s e A u x ( null ) ;
}
/∗ ∗
∗ String representation of t h i s l i s t .
∗/
@Override
public S t r i n g t o S t r i n g ( ) {
i f ( next == null )
return ” ” + i n f o ;
else
return i n f o + ” , ” + next ;
}
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
I n t L i s t l s t = new I n t L i s t ( 1 , null ) ;
fo r ( int i = 2 ; i < 1 0 ; i ++)
l s t = l s t . append ( i ) ;
System . out . p r i n t l n ( l s t ) ;
System . out . p r i n t l n ( l s t . r e v e r s e ( ) ) ;
System . out . p r i n t l n ( l s t . sum ( ) ) ;
}
}
6
Aufgabe 7.3 (P) Binärer Suchbaum
Ein Binärbaum ist ein Baum, in dem alle Knoten einen Wert und 2 Teilbäume haben. Bei einem binären Suchbaum (BSB) gilt für jeden Knoten
des Baumes, dass sein Wert:
• grösser ist als die Werte aller Knoten in seinem linken Teilbaum;
• kleiner ist als die Werte aller Knoten in seinem rechten Teilbaum;
• maximal einmal im ganzen BSB vorkommt.
Beispiel: In der obigen Zeichnung finden Sie einen BSB für die Zahlen 1, 3, 6, 7, 8, 10, 13, 14.
Entwerfen und realisieren Sie die Datenstrukturen und Methoden für binäre Suchbäume in
Java!
a) Erstellen Sie eine Klasse BSB, mit der Sie binäre Suchbäume darstellen können.
Ergänzen Sie die Klasse BSB um folgende Methoden:
b) boolean contains(int n), die zurückgibt, ob die Zahl n im BSB enthalten ist.
c) void insert(int n), die – unter Erhalt der obigen Eigenschaften – einen neuen Knoten mit dem Wert n in den BSB einfügt, falls dieser Wert im BSB nicht schon vorhanden ist.
Beispiel: Die folgende Zeichnung illustriert einen Aufruf von insert(4):
insert(4)
−→
d) String toString(), die eine String-Darstellung der Baumstruktur zurückgibt.
Beispiel: toString() liefert für den obigen BSB den String:
[8 [3 [1] [6 [7]]] [10 [14 [13]]]]
Lösungsvorschlag 7.3
public c l a s s BSB {
private BSB l e f t ;
private BSB r i g h t ;
private int v a l u e ;
public BSB( int v ) {
value = v ;
}
/∗
p u b l i c boolean contains ( in t n) {
// . . . Aufgabe a )
}
p u b l i c void i n s e r t ( in t n) {
7
// . . . Aufgabe b )
}
}
∗/
/∗ ∗
∗ checks i f element n i s in t r e e
∗/
public boolean c o n t a i n s ( int n ) {
i f ( n == v a l u e ) {
return true ;
} e l s e i f ( n > v a l u e && r i g h t != null ) {
return r i g h t . c o n t a i n s ( n ) ;
} e l s e i f ( n < v a l u e && l e f t != null ) {
return l e f t . c o n t a i n s ( n ) ;
}
return f a l s e ;
}
/∗ ∗
∗ I n s e r t s a new node w i t h v a l u e n i n t o t h e BSB
∗/
public void i n s e r t ( int n ) {
i f ( ! contains (n) ){
i f (n > value ) {
i f ( r i g h t == null ) {
r i g h t = new BSB( n ) ;
} else {
right . insert (n) ;
}
} else {
i f ( l e f t == null ) {
l e f t = new BSB( n ) ;
} else {
l e f t . insert (n) ;
}
}
}
}
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
BSB b = new BSB( 5 ) ;
b . insert (7) ;
b . insert (2) ;
b . insert (8) ;
System . out . p r i n t l n ( b . c o n t a i n s ( 8 ) ) ;
System . out . p r i n t l n ( b ) ;
}
@Override
public S t r i n g t o S t r i n g ( ) {
return ”( ” + l e f t + ”) ” + v a l u e+ ” ( ” + r i g h t+ ”) ” ;
}
}
8
Aufgabe 7.4 [4 Punkte] (H) Binärer Suchbaum - Fortsetzung
Laden sie sich die Lösung zu Aufgabe 7.3 von der Homepage und erweitern Sie die Datenstrukturen und Methoden für binäre Suchbäume um
a) eine Objektmethode depth, die die Tiefe eines Suchbaumes berechnet und zurückgibt.
Hinweis: Die Tiefe eines Suchbaums ist die Anzahl der Kanten entlang des längsten
Pfades, der in Richtung der Pfeile gegangen werden kann .
b) eine Objektmethode size, die die Anzahl der Knoten in diesem Suchbaum berechnet
und zurückgibt.
c) eine Objektmethode getSortedArray, die ein Array zurückgibt, dass die Zahlen aus
den Knoten dieses Baums in aufsteigender Reihenfolge enthält.
Lösungsvorschlag 7.4
public int depth ( ) {
int depth = 1 ;
i f ( r i g h t != null ) depth+=r i g h t . depth ( ) ;
i f ( l e f t==null ) return depth ;
return Math . max( depth , l e f t . depth ( ) +1) ;
}
public int s i z e ( ) {
int s i z e = 1 ;
i f ( r i g h t != null ) s i z e+=r i g h t . s i z e ( ) ;
i f ( l e f t==null ) return s i z e ;
return s i z e+ l e f t . s i z e ( ) ;
}
public int [ ] g e t S o r t e d A r r a y ( ) {
int [ ] l=new int [ 0 ] , r=new int [ 0 ] ;
i f ( l e f t != null ) l= l e f t . g e t S o r t e d A r r a y ( ) ;
i f ( r i g h t != null ) r = r i g h t . g e t S o r t e d A r r a y ( ) ;
int [ ] r e t = new int [1+ l . l e n g t h+r . l e n g t h ] ;
for ( int i =0; i <l . l e n g t h ; i ++){
r e t [ i ]= l [ i ] ;
}
r e t [ l . l e n g t h ]= v a l u e ;
for ( int i =0; i <r . l e n g t h ; i ++){
r e t [ i+l . l e n g t h +1]= r [ i ] ;
}
return r e t ;
}
9
Aufgabe 7.5 [6 Punkte] (H) Einfache Listenfunktionen
Laden sie sich die Lösung zu Aufgabe 7.2 von der Homepage und erweitern Sie die Datenstrukturen und Methoden für einfach verkettete Integer-Listen. Implementieren Sie
a) eine statische Methode IntList fromArray(int [] values), die eine neue Liste mit
den im Array enthaltenen Werten erstellt.
b) eine Methode int length(), die die Länge der Liste zurückgibt.
c) eine Methode IntList get(int i), die eine Referenz auf das i-te Element der aktuellen Liste zurückgibt (Indizierung beginnt bei 0).
d) eine Methode IntList copyRange(int start,int end), die eine neue Liste zurückgibt, die die Elemente zwischen start und end (inklusive) enthält.
e) eine Methode IntList concat(IntList list), die eine neue Liste zurückgibt, in der
die Elemente von list an die Elemente der aktuellen Liste angehängt wurden.
f) eine Methode IntList remove(int i), die eine neue Liste zurückgibt, die bis auf das
i-te Element alle Elemente der aktuellen Liste enthält.
g) eine Methode IntList map(IntList list), die eine neue Liste zurückgibt, deren ites Element die paarweise Summe der i-ten Elemente der aktuellen Liste und der Liste
list ist.
Lösungsvorschlag 7.5
public c l a s s I n t L i s t {
private int
info ;
private I n t L i s t next ;
// t h e i n t i n f o o f t h i s l i s t e l e m e n t
// t h e r e s t o f t h e l i s t
public I n t L i s t ( int i n f o , I n t L i s t next ) {
this . i n f o = i n f o ;
t h i s . next = next ;
}
@Override
public S t r i n g t o S t r i n g ( ) {
i f ( next == null ) {
return ” ” + i n f o ;
} else {
return i n f o + ” , ” + next ;
}
}
public s t a t i c I n t L i s t fromArray ( int [ ] v a l u e s ) {
i f ( v a l u e s . l e n g t h == 0 ) {
return null ;
}
I n t L i s t r e s = new I n t L i s t ( v a l u e s [ 0 ] , null ) ;
I n t L i s t cur = r e s ;
fo r ( int i = 1 ; i < v a l u e s . l e n g t h ; i ++) {
c u r . next = new I n t L i s t ( v a l u e s [ i ] , null ) ;
c u r = c u r . next ;
}
return r e s ;
}
10
public int l e n g t h ( ) {
i f ( next == null ) {
return 1 ;
} else {
return 1 + next . l e n g t h ( ) ;
}
}
public I n t L i s t g e t ( int pos ) {
i f ( pos == 0 ) {
return t h i s ;
} e l s e i f ( next != null ) {
return next . g e t ( pos −1) ;
}
return null ;
}
public I n t L i s t copyRange ( int posa , int posb ) {
I n t L i s t s t a r t = g e t ( posa ) ;
I n t L i s t t o = new I n t L i s t ( s t a r t . i n f o , null ) ;
I n t L i s t r e s = to ;
I n t L i s t from = s t a r t . next ;
while ( from != null && posb >= posa ) {
t o . next = new I n t L i s t ( from . i n f o , null ) ;
t o = t o . next ;
from = from . next ;
posa++;
}
return r e s ;
}
public I n t L i s t copy ( ) {
return copyRange ( 0 , l e n g t h ( ) − 1 ) ;
}
public I n t L i s t l a s t ( ) {
i f ( next == null ) {
return t h i s ;
} else {
return next . l a s t ( ) ;
}
}
public I n t L i s t c o n c a t ( I n t L i s t l ) {
i f ( next == null ) {
return new I n t L i s t ( i n f o , l ) ;
} else {
return new I n t L i s t ( i n f o , next . c o n c a t ( l ) ) ;
}
}
public I n t L i s t remove ( int i ) {
11
I n t L i s t cp = copy ( ) ;
i f ( i == 0 ) {
return cp . next ;
} else {
I n t L i s t prev = cp . g e t ( i − 1 ) ;
i f ( prev == null | | prev . next == null ) {
return null ;
} else {
prev . next = prev . next . next ;
}
return cp ;
}
}
public I n t L i s t map( I n t L i s t b ) {
f i n a l int sum = i n f o + b . i n f o ;
i f ( next == null ) {
return new I n t L i s t ( sum , null ) ;
} else {
return new I n t L i s t ( sum , next . map( b . next ) ) ;
}
}
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
int [ ] v a l s 1 = { 1 , 4 , 3 , 5 , 6 , 8 , 9 , 3 , 4 5 } ;
I n t L i s t nums1 = I n t L i s t . fromArray ( v a l s 1 ) ;
int [ ] v a l s 2 = { 1 0 , 4 0 , 3 0 , 5 0 , 6 0 , 8 0 , 9 0 , 3 0 , 4 5 0 } ;
I n t L i s t nums2 = I n t L i s t . fromArray ( v a l s 2 ) ;
System . out . p r i n t l n ( nums1 ) ;
System . out . p r i n t l n ( nums2 ) ;
I n t L i s t cp = nums1 . copy ( ) ;
System . out . p r i n t l n ( cp ) ;
I n t L i s t nums3 = nums1 . c o n c a t ( nums2 ) ;
nums3 . g e t ( 5 ) . i n f o = −5;
i f ( nums1 . g e t ( 5 ) . i n f o == −5) {
System . out . p r i n t l n ( ” e r r o r , r e f e r e n c e i n s t e a d o f copy
g e n e r a t e d ”) ;
}
System . out . p r i n t l n ( nums3 ) ;
I n t L i s t nums4 = nums3 . remove ( 1 2 ) ;
System . out . p r i n t l n ( nums4 ) ;
I n t L i s t nums5 = nums3 . map( nums3 ) ;
System . out . p r i n t l n ( nums5 ) ;
}
}
Herunterladen