|
||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object SubArray
public class SubArray
Datentyp, der einen bestimmten (definierbaren) Teil eines Arrays darstellt. Dieser Teil wird Sub-Array genannt.
Ein Sub-Array ist eindeutig definiert durch drei Angaben:
In dieser Klasse wird diese Eindeutigkeit umgesetzt durch interne Speicherung
Alternativ zu Start-Stelle und Laenge des Sub-Arrays waeren natuerlich auch Start-Stelle und End-Stelle ausreichend, um den Sub-Array eindeutig zu definieren. Warum Start und Laenge besser sind als Beginn und Ende, beschrieb E. W. Dijkstra im Jahre 1982 recht anschaulich. [vgl. EWD831] Diese Klasse stellt der Bequemlichkeit halber Methoden zur Verfuegung, die direkt Beginn- und End-Stelle zurueckliefern, so dass eine entsprechende Umrechnung nur beim Setzen der End-Stelle notwendig ist. Diese Umrechnung ist weiter unten erklaert.
Bemerkenswert ist, dass die Summe der Elemente des Sub-Arrays diesen nicht definiert. Vielmehr ist die Summe eine Eigenschaft des Sub-Arrays. Immer, wenn man Start und Laenge des Sub-Arrays kennt, ist das Berechnen der Summe trivial. Aus einer Summe allein kann man aber selbst bei bekanntem Gesamt-Array oft nicht eindeutig auf das zugehoerige Sub-Array schliessen.
Um das Arbeiten mit der Summe zu erleichtern, verfuegt jede
Instanz dieser Klasse ueber einen Cache, der die aktuelle Summe
zwischenspeichert, wann immer sie bekannt ist. Dieser Cache bleibt
bis zur naechsten Aenderung der Definition des Sub-Arrays gueltig.
Die Objektmethoden setSum(int)
und getSum()
erlauben den direkten Zugruff auf den Cache. Falls beim Aufruf von
getSum()
der Cache gerade veraltet ist, wird die Summe
automatisch mit einer Schleife neu berechnet und der Cache aktualisiert.
Beim Arbeiten mit dieser Klassse wird man in der Regel zunaechst mit
einem Konstruktor und dem new
-Operator eine neue Instanz,
also ein neues Objekt vom Typ SubArray, erstellen. Auf diesem Objekt
wird man dann je nach Bedarf Objektmethoden aufrufen (das sind die
ohne static
),
z. B. variablenname.print();
.
Eine interessante Anwendung dieser Klasse besteht darin, den
Rueckgabe-Typ einer Methode als SubArray
zu definieren.
Dadurch wird es moeglich, statt etwa einer einzigen Zahl mehrere
Zahlen zuruckzugeben -- naemlich genau diejenigen Zahlen, durch
die ein Sub-Array definiert wird. Das Interface
MaximumSubArraySolver
wendet dieses Prinzip an.
Abgesehen von den Objektmethoden stehen auch einige Klassenmethoden zum
Aufruf zur Verfuegung (das sind die mit static
),
z. B. SubArray.createRandomArray();
. Die Klassenmethoden
erstellen Arrays oder Sub-Arrays anhand bestimmter Kriterien:
createRandomArray(...)
erstellen einen mit
zufaelligen Elementen gefuellten Array des Typs int[]
. Das
kann nutzlich sein, wenn man ohne grossen Aufwand schnell eine grosse
Anzahl von Testwerten braucht.
parseStringArray(String[])
erstellt einen Array
des Typs int[]
, der mit genau den Zahlen gefuellt ist, die
sich in den einzelnen String-Elementen des Arrays befinden. Das kann
nuetzlich sein beim Versuch, auf der Kommandozeile einen Array an das
Programm zu uebergeben.
findLeftEdgeMaximum(int[],int,int)
und
findRightEdgeMaximum(int[],int,int)
ermitteln innerhalb des
angegebenen Array-Teils das linke bzw. rechte Randmaximum und geben das
Ergebnis als Objekt vom Typ SubArray
zurueck. Das kann
nuetzlich sein bei Divide-and-Conquer--Algorithmen mit Sub-Arrays.
Beispiel. Die folgende Klasse ermittelt die rechte Haelfte
eines an der Kommandozeile eingegebenen Arrays und zeigt ihre Lage
im Gesamt-Array an:
public class RechteHaelfteFinder {
public SubArray findeRechteHaelfte (int[] array) {
// rechte Haelfte ermitteln:
int mitte = array.length / 2;
int startRechteHaelfte = mitte;
int laengeRechteHaelfte = array.length - mitte;
// SubArray-Objekt konstruieren und zurueckgeben:
SubArray ergebnis = new SubArray(array);
ergebnis.setStart(startRechteHaelfte);
ergebnis.setLength(laengeRechteHaelfte);
return ergebnis;
}
public static void main (String[] args) {
int[] eingabeArray = SubArray.parseStringArray(args);
// weil die Methode findeRechteHaelfte(int[]) eine
// Objektmethode ist (nicht static!), muessen wir
// erst ein neues Objekt konstruieren:
RechteHaelfteFinder finder = new RechteHaelfteFinder();
SubArray rechteHaelfte;
rechteHaelfte = finder.findeRechteHaelfte(eingabeArray);
rechteHaelfte.print();
}
}
Beim Aufruf von der Kommandozeile mit
java RechteHaelfteFinder 1 2 3 4 5 6
wird folgendes Ergebnis ausgegeben:
1 2 3 [4 5 6]
Hinweis. Soll ein Sub-Array subArray
anhand der
Indizes des ersten und letzten Elements (beginIndex
respektive endIndex
) definiert werden, koennen folgende
Objektmethoden-Aufrufe dazu verwendet werden:
subArray.setStart(beginIndex);
subArray.setLength(endIndex - beginIndex + 1);
(Die + 1
sind dabei notwendig, denn offensichtlich hat
ein Sub-Array, dessen erstes und letztes Element identisch sind
(endIndex == beginIndex
), immer die Laenge eins. Bei einer
einfachen Differenz endIndex - beginIndex
wuerde sich dann
jedoch faelschlich null fuer die Laenge ergeben. Folglich muss diese
Differenz um eins erhoeht werden.)
MaximumSubArraySolver
Field Summary | |
---|---|
protected static int |
DEFAULT_ARRAY_LENGTH
Standard-Laenge eines mit zufaelligen Werten erstellten Arrays. |
protected static int |
DEFAULT_LIMITS
Standard-Begrenzung der Werte in einem mit zufaelligen Werten erstellten Array. |
Constructor Summary | |
---|---|
SubArray(int[] array)
Konstruktor; erstellt ein neues SubArray-Objekt fuer den ganzen uebergebenen Array. |
|
SubArray(int[] array,
int subArrayStart,
int subArrayLength)
Konstruktor; erstellt ein neues SubArray-Objekt mit bestimmten Grenzen. |
|
SubArray(SubArray array,
int beginIndex,
int endIndex)
Konstruktor; erstellt eine Kopie der uebergebenen SubArray-Instanz mit veraenderten Sub-Array--Grenzen. |
Method Summary | |
---|---|
Object |
clone()
Erstellt eine exakte Bitkopie dieses SubArray-Objekts. |
static int[] |
createRandomArray()
Erstellt einen mit Zufallszahlen gefuellten Array mit einer Standard-Laenge von 12 Elementen. |
static int[] |
createRandomArray(int arrayLength)
Erstellt einen mit Zufallszahlen gefuellten Array mit definierter Laenge. |
static int[] |
createRandomArray(int arrayLength,
int limits)
Erstellt einen mit Zufallszahlen gefuellten Array mit definierter Laenge. |
static int[] |
createRandomArray(int arrayLength,
int lowerLimit,
int upperLimit)
Erstellt einen mit Zufallszahlen gefuellten Array mit definierter Laenge. |
boolean |
equals(Object obj)
Prueft, ob ein anderes Objekt gleich diesem ist. |
void |
findLeftEdgeMaximum()
Errechnet das linke Randmaximum dieses Sub-Arrays. |
static SubArray |
findLeftEdgeMaximum(int[] array,
int beginIndex,
int endIndex)
Errechnet das linke Randmaximum eines Arrays-Teils. |
void |
findRightEdgeMaximum()
Errechnet das rechte Randmaximum dieses Sub-Arrays. |
static SubArray |
findRightEdgeMaximum(int[] array,
int beginIndex,
int endIndex)
Errechnet das rechte Randmaximum eines Arrays-Teils. |
int |
getBeginIndex()
Liefert den auf den Gesamt-Array bezogenen Index des ersten Elements des Sub-Arrays. |
int |
getEndIndex()
Liefert den auf den Gesamt-Array bezogenen Index des letzten Elements des Sub-Arrays. |
int[] |
getFullArray()
Zugriffsmethode; liefert den bei der Instanziierung gesetzten Gesamt-Array. |
int |
getLength()
Zugriffsmethode; liefert die Laenge des Sub-Arrays. |
int |
getStart()
Zugriffsmethode; liefert den Index des Beginns des Sub-Arrays. |
int |
getSum()
Liefert die Summe aller Elemente des Sub-Arrays in seinen derzeitigen Grenzen. |
int |
hashCode()
Liefert den Hash-Code fuer diesen Sub-Array. |
static int[] |
parseStringArray(String[] args)
Erstellt einen Integer -Array, der mit den
umgewandelten Zahlen aus dem uebergebenen
String -Array gefuellt ist. |
void |
print()
Gibt eine String-Repraesentation dieses Objekts auf dem Standard-Ausgabe-Stream aus. |
void |
setLength(int subArrayLength)
Zugriffsmethode; setzt die Laenge des Sub-Arrays. |
void |
setStart(int subArrayStart)
Zugriffsmethode; setzt den Index des Beginns des Sub-Arrays. |
void |
setSum(int subArraySum)
Setzt den Cache der Summe des Sub-Arrays. |
(package private) int |
sum()
Deprecated. Verglichen mit dem Summen-Cache ist diese Methode unnoetig langsam und sollte nicht mehr verwendet werden. Statt dessen sollte ersatzweise getSum() verwendet
werden. |
int[] |
toArray()
Kopiert den Sub-Array in einen neu angelegten Integer-Array. |
String |
toString()
Liefert eine String-Repraesentation dieses Objekts. |
Methods inherited from class java.lang.Object |
---|
finalize, getClass, notify, notifyAll, wait, wait, wait |
Field Detail |
---|
protected static final int DEFAULT_LIMITS
10
liefert
Zufallszahlen aus dem Intervall [-10, 10].
createRandomArray(int,int)
,
Constant Field Valuesprotected static final int DEFAULT_ARRAY_LENGTH
createRandomArray(int,int)
,
Constant Field ValuesConstructor Detail |
---|
public SubArray(int[] array)
SubArray subArray = new SubArray(array);
subArray.setStart(0);
subArray.setLength(array.length);
Der Gesamt-Array kann in dieser Instanz nicht veraendert werden; noetigenfalls ist eine neue Instanz dieser Klasse mit einem anderen Array zu erstellen.
Beispiel:
int[] array = {1, 2, 3};
SubArray subArray = new SubArray(array);
System.out.println(subArray); // [1 2 3]
array
- der Gesamt-Array fuer die neue Instanz
NullPointerException
- falls array == null
setStart(int)
,
setLength(int)
public SubArray(int[] array, int subArrayStart, int subArrayLength)
SubArray subArray = new SubArray(array);
subArray.setStart(subArrayStart);
subArray.setLength(subArrayLength);
Der Gesamt-Array kann in dieser Instanz nicht veraendert werden; noetigenfalls ist eine neue Instanz dieser Klasse mit einem anderen Array zu erstellen.
Beispiel:
int[] array = {1, 2, 3};
SubArray subArray = new SubArray(array, 1, 1);
System.out.println(subArray); // 1 [2] 3
array
- der Gesamt-Array fuer die neue InstanzsubArrayStart
- der Index des Beginns des Sub-ArrayssubArrayLength
- die Laenge des Sub-Arrays
NullPointerException
- falls array == null
setStart(int)
,
setLength(int)
public SubArray(SubArray array, int beginIndex, int endIndex)
SubArray subArray = new SubArray(array.getFullArray());
subArray.setStart(beginIndex);
subArray.setLength(endIndex - BeginIndex + 1);
Im Gegensatz zu den meisten anderen Konstruktoren und Methoden
werden hier Indizes auf den Gesamt-Array als Parameter
gefordert. Die Indizes zaehlen dabei einschliesslich, so dass im
Falle beginIndex == endIndex
der neue Sub-Array die
Laenge 1 hat.
Der Gesamt-Array kann in dieser Instanz nicht veraendert werden; noetigenfalls ist eine neue Instanz dieser Klasse mit einem anderen Array zu erstellen.
Beispiel. In diesem Code-Schnipsel wird
array2
als exakte Kopie von array1
erstellt:
SubArray original = ...; // beliebiger Sub-Array
int beginIndex = original.getStart();
int endIndex = original.getStart() + original.getLength() - 1;
SubArray kopie = new SubArray(original, beginIndex, endIndex);
System.out.println(kopie.equals(original)); // true
array
- der Gesamt-Array fuer die neue InstanzbeginIndex
- der Index des ersten Elements im neuen
Sub-ArrayendIndex
- der Index des letzten Elements im neuen
Sub-Array
NullPointerException
- falls array == null
setStart(int)
,
setLength(int)
Method Detail |
---|
public int[] getFullArray()
public void setStart(int subArrayStart)
Beispiel:
int[] array = {1, 2, 3};
SubArray subArray = new SubArray(array, 1, 1);
System.out.println(subArray); // 1 [2] 3
subArray.setStart(0);
System.out.println(subArray); // [1] 2 3
Beim Aufruf dieser Methode wird der interne Cache der
Sub-Array--Summe als veraltet markiert. Ein anschliessender
Aufruf von getSum()
fuehrt zu einer Neuberechnung
der Sub-Array--Summe.
subArrayStart
- auf den Gesamt-Array bezogener Array-Index,
an dem der Sub-Array beginnen sollgetSum()
public int getStart()
Der zurueckgegebene Index ist so angepasst, dass sich immer eine gueltige Definition des Sub-Arrays ergibt.
Beispiel:
Wenn
System.out.println(subArray)
die Ausgabe "1 2 3 [4 5] 6
" erzeugt, hat
subArray.getStart()
genau den Wert
3
.
getLength()
public void setLength(int subArrayLength)
Beispiel:
int[] array = {1, 2, 3};
SubArray subArray = new SubArray(array, 1, 1);
System.out.println(subArray); // 1 [2] 3
subArray.setLength(2);
System.out.println(subArray); // 1 [2 3]
Beim Aufruf dieser Methode wird der interne Cache der
Sub-Array--Summe als veraltet markiert. Ein anschliessender
Aufruf von getSum()
fuehrt zu einer Neuberechnung
der Sub-Array--Summe.
subArrayLength
- Laenge des Sub-ArraysgetSum()
public int getLength()
Die zurueckgegebene Laenge ist so angepasst, dass sich immer eine gueltige Definition des Sub-Arrays ergibt.
Beispiel:
Wenn
System.out.println(subArray)
die Ausgabe "1 2 3 [4 5] 6
" erzeugt, hat
subArray.getLength()
genau den Wert
2
.
getStart()
public void setSum(int subArraySum)
Diese Methode kann bei bereits bekannter Summe aufgerufen
werden, um den internen Cache der Summe aufzufrischen. Beim
naechsten Aufruf von getSum()
wird direkt der
dieser Methode uebergebene Wert zurueckgeliefert, eine
Neuberechnung der Sub-Array--Summe findet dann nicht statt.
subArraySum
- Summe des Sub-ArraysgetSum()
public int getSum()
Um Rechenzeit zu sparen, wird nach Moeglichkeit der interne Cache der Summe verwendet. Ist der Cache jedoch nicht mehr frisch, muss die Summe neu berechnet werden. Dies geschieht mittels einer Iteration mit O(n)-Komplexitaet.
Diese Methoden frischen den Cache auf:
setSum(int)
getSum()
findLeftEdgeMaximum()
findRightEdgeMaximum()
Diese Methoden markieren den Cache als veraltet:
setStart(int)
setLength(int)
Beispiel:
int[] array = {1, 2, 3};
SubArray subArray = new SubArray(array, 1, 2);
System.out.println(subArray); // 1 [2 3]
System.out.println(subArray.getSum()); // 5
setSum(int)
int sum()
getSum()
verwendet
werden.
getSum()
/ setSum(int)
braucht diese
Methode nicht mehr verwendet zu werden.
getSum()
public int getBeginIndex()
subArray.getBeginIndex()
entspricht genau:
subArray.getStart()
Diese Methode ist nur ein Alias fuer die Methode
getStart()
. Sie stellt das Gegenstueck zu
getEndIndex()
dar.
getStart()
public int getEndIndex()
subArray.getEndIndex()
entspricht genau:
subArray.getStart() + subArray.getLength() - 1
public void findLeftEdgeMaximum()
Das zurueckgegebene Objekt hat einen erfrischten Cache der Sub-Array--Summe.
Beispiel:
int[] array = {1, -4, 2};
SubArray subArray = new SubArray(array);
System.out.println(subArray); // [1 -4 2]
subArray.findLeftEdgeMaximum();
System.out.println(subArray); // [1] -4 2
setSum(int)
public void findRightEdgeMaximum()
Das zurueckgegebene Objekt hat einen erfrischten Cache der Sub-Array--Summe.
Beispiel:
int[] array = {1, -4, 2};
SubArray subArray = new SubArray(array);
System.out.println(subArray); // [1 -4 2]
subArray.findRightEdgeMaximum();
System.out.println(subArray); // 1 -4 [2]
setSum(int)
public static SubArray findLeftEdgeMaximum(int[] array, int beginIndex, int endIndex)
array
den Index beginIndex
hat und dessen Summe der
Elemente so gross wie moeglich ist.
Das zurueckgegebene Objekt hat einen erfrischten Cache der Sub-Array--Summe.
Beispiel:
int[] array = {1, -4, 2};
SubArray subArray = SubArray.findLeftEdgeMaximum(array, 0, 2);
System.out.println(subArray); // [1] -4 2
array
- der Array, in dem sich der Array-Teil befindet,
von dem das Randmaximum zu ermitteln istbeginIndex
- der Index des ersten Elements des Array-TeilsendIndex
- der Index des letzten Elements des Array-Teils
findLeftEdgeMaximum()
,
setSum(int)
public static SubArray findRightEdgeMaximum(int[] array, int beginIndex, int endIndex)
array
den Index endIndex
hat und
dessen Summe der Elemente so gross wie moeglich ist.
Das zurueckgegebene Objekt hat einen erfrischten Cache der Sub-Array--Summe.
Beispiel:
int[] array = {1, -4, 2};
SubArray subArray = SubArray.findRightEdgeMaximum(array, 0, 2);
System.out.println(subArray); // 1 -4 [2]
array
- der Array, in dem sich der Array-Teil befindet,
von dem das Randmaximum zu ermitteln istbeginIndex
- der Index des ersten Elements des Array-TeilsendIndex
- der Index des letzten Elements des Array-Teils
findRightEdgeMaximum()
,
setSum(int)
public void print()
Beispiel:
int[] array = {1, 2, 3};
SubArray subArray = new SubArray(array);
subArray.print(); // [1 2 3]
Im vorstehenden Beispiel koennte man anstelle von
subArray.print();
genau so gut auch
System.out.println(subArray);
schreiben. Diese
beiden Schreibweisen sind genau gleichbedeutend.
toString()
,
PrintStream.println(Object)
public String toString()
toString
in class Object
public int[] toArray()
public Object clone()
Das Original-Objekt wird mit Hilfe der von der JVM zur Verfuegung gestellten Methode clone() geklont. Das erwartete Verhalten entspricht prinzipiell dem folgenden Code-Block. Allerdings werden die Werte der internen Felder keim klonen ohne jegliche Aenderung vom Original uebernommen (im folgenden Code findet eine implizite Wertekorrektur und eine Neuberechnung des Summen-Caches statt).
SubArray original = ...; // beliebiger Sub-Array
SubArray kopie = new SubArray(original.getFullArray());
kopie.setStart(original.getStart());
kopie.setLength(original.getLength());
kopie.setSum(original.getSum());
clone
in class Object
SubArray
Object.clone()
,
Cloneable
public boolean equals(Object obj)
equals
in class Object
obj
- das auf Gleichheit zu pruefende Objekt
true
, falls obj
gleich diesem
Objekt istpublic int hashCode()
hashCode
in class Object
Object.hashCode()
,
Arrays.hashCode(int[])
public static int[] createRandomArray(int arrayLength, int lowerLimit, int upperLimit)
Beispiel. Der folgende Code erstellt einen mit
Zufallszahlen zwischen -10 und +15 gefüllten Integer-Array
array
mit 5 Elementen:
int[] array = SubArray.createRandomArray(5, -10, 15);
arrayLength
- die Laenge des ArrayslowerLimit
- die kleinstmoegliche ZufallszahlupperLimit
- die groesstmoegliche Zufallszahlpublic static int[] createRandomArray(int arrayLength, int limits)
Dies entspricht genau:
int[] array = SubArray.createRandomArray(arrayLength, -limits, limits);
arrayLength
- die Laenge des Arrayslimits
- der maximale Abstand, den die Zufallszahlen von
der Zahl null (0
) haben sollencreateRandomArray(int, int, int)
public static int[] createRandomArray(int arrayLength)
Dies entspricht genau:
int[] array = SubArray.createRandomArray(arrayLength, 99);
arrayLength
- die Laenge des ArrayscreateRandomArray(int, int, int)
,
createRandomArray(int, int)
,
DEFAULT_LIMITS
public static int[] createRandomArray()
Dies entspricht genau:
int[] array = SubArray.createRandomArray(12);
createRandomArray(int, int, int)
,
createRandomArray(int)
,
DEFAULT_LIMITS
,
DEFAULT_ARRAY_LENGTH
public static int[] parseStringArray(String[] args)
Integer
-Array, der mit den
umgewandelten Zahlen aus dem uebergebenen
String
-Array gefuellt ist. Beide Arrays haben die
gleiche Laenge.
Beispiel:
Die folgende Klasse erstellt beim
Programmstart einen Array array
, der mit genau den
auf der Kommandozeile uebergebenen Werten gefuellt ist:
public class Beispiel {
public static void main (String[] args) {
int[] array = SubArray.parseStringArray(args);
// mehr code hierhin
}
}
Nun kann das Programm z. B. mit
java Beispiel 12 -56 47 8 -87
gestartet werden, um einen Array mit einer Laenge von fuenf
Elementen mit genau diesen Zahlenwerten zu erstellen.
args
- ein Array, dessen Elemente allesamt Ganzzahlen
beschreiben
NumberFormatException
- falls eines der Array-Elemente
sich nicht in eine Ganzzahl wandeln laesst
NullPointerException
- falls args == null
|
||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |