Professional Documents
Culture Documents
Java Developer Initial Programer
Java Developer Initial Programer
Mergesort
Mergesort
We now study a sorting algorithm called Mergesort that performs much better than
selection sort
To sort the array below
5 7 9 1 8
5 7 9 1 8
5 7 9 1 8 1 5 7
5 7 9 1 8 1 5 7 8
5 7 9 1 8 1 5 7 8 9
4 Foundations of Computer Science – A. Luchetta 2021-2022
Mergesort
In the general case, the two parts of the array are not already sorted
However, we can sort each part by repeating the process
we divide the array into two (approximately) equal parts
We suppose they are both sorted
So we can recombine the two parts in the way we have just seen
this phase is called merge
By continuing like this, we will certainly arrive at a situation where the two parts of the
array are really sorted
when they contain only one element!
// merge
merge(a, left, right); // the work is left to merge method
}
…
7 Foundations of Computer Science – A. Luchetta 2021-2022
public class ArrayAlgorithms
{ private static void merge(int[] a, int[] b, int[] c)
{ int ia = 0, ib = 0, ic = 0;
// until arrays b and c have elements to move
while (ib < b.length && ic < c.length)
if (b[ib] < c[ic])
a[ia++] = b[ib++];
else
a[ia++] = c[ic++];
9 8 5 7 6 8 9 5 7 6
8 9 5 7 6 5 8 9 7 6
5 8 9 7 6 5 7 8 9 6
5 7 8 9 6 5 6 7 8 9
Tw(n)∈ O (n2)
Ta(n)∈ O(n2)
If we know that the array is "almost" sorted, it is better to use insertion sort
Notable example: an array that is kept sorted for searching, inserting a new element
every so often and then sorted again
n n2 n log n n2 / n log n
10 100 33 3
100 10.000 664 15
1.000 1.000.000 9.966 100
10.000 100.000.000 132.877 753
100.000 10.000.000.000 1.660.964 6.021
1.000.000 1.000.000.000.000 19.931.569 50.172
10.000.000 100.000.000.000.000 232.534.967 430.043
package packageName;
To obtain, for example, random integers included in the interval [a, b], we have to do
some calculations ...
int n = (int)(a + (1 + b – a) * Math.random());
This code snippet does not work because the object of Scanner type uses as default
delimiter characters the whitespaces character set that does not contain the '/'
character
String line = “Buenos Aires/Los Angeles/La Paz”;
Scanner st = new Scanner(line);
st.useDelimiter(“[/]+”); // specifies the delimiters
while (st.hasNext())
System.out.println(st.next());
// NOW IT WORKS!
Buenos Aires Los
Angeles
La Paz
The character ‘+’ after the bracket pair means one or more occurrences since the
delimiters can also be repeated
Example: if we want to select as delimiters the characters ‘@’ ‘$’ and ‘#’, we must write
Scanner st = new Scanner();
st.useDelimiter(“[@$#]+”);
The two lines above are often merged in a single one
Scanner st = new Scanner()useDelimiter(“[@$#]+”);
43 Foundations of Computer Science – A. Luchetta 2021-2022
Regular expressions
Regular expression are used in service programs such as the Linux grep command
For example, to list all lines containing numbers in the MyClass.java file, we can
write
$ grep [0-9]+ grep MyClass.java
[0-9] indicates any character between ‘0’ and ‘9’, that is all numeric characters
If we want to exclude the lines where characters precede numbers, we can wright
$ grep [^A-Za-z][0-9]+ grep MyClass.java
[^A-Za-z] indicates any character except (^) those in the range [rom ‘A’ to ‘Z’]and
[from ‘a’ to ‘z’
As we expected, we simply copied much of the code written for BankAccount into
the definition of the SavingsAccount class
we added an instance variable interestRate
we renamed and changed the constructor
we added a new method addInterest()
interestRate 10
variabiles and method SavingsAccount(...)
Defined in SavingsAccount
addInterest()
We can use the objects of the SavingsAccount extended class as if they were
BankAccount objects, with a few more properties
SavingsAccount acct = new SavingsAccount(10);
acct.deposit(500);
acct.withdraw(200);
acct.addInterest();
System.out.println(acct.getBalance());
330
The derived class (SavingsAccount) is called a subclass, while the class that is
extended (BankAccount) is called a superclass
In Java, any class that does not explicitly derive from another class derives implicitly
from the root superclass of the class hierarchy, which is called Object
Hence, SavingsAccount derives from BankAccount, which in turn derives implicitly
from the java.lang.Object class
Object class has some methods, which we will see later (including toString()), which
are then inherited by all classes in Java
inheritance also occurs on multiple levels, so SavingsAccount also inherits the
properties of Object
Purpose: to define the SubclassName class that derives from the SuperclassName
class, defining new methods and / or new variables, as well as its constructors
Note: if the a superclass is not explicitly indicated, the compiler implicitly uses
java.lang.Object
When we define a subclass, three things can happen regarding its methods
1. in the subclass a method is defined that does not exist in the superclass:
in our example addInterest()
2, the subclass inherits a method from the superclass
in our example deposit(), withdraw(), getBalance()
3. a method of the sublass overrides the method in the superclass
The ability to override a method of the superclass, modifying its behavior when
used for the subclass, is one of the most powerful features of the object oriented
programming
To override a method, a method with the same signature as the one defined in the
superclass must be defined in the subclass
this method overrides that of the superclass when it is invoked with an reference to
an object of the subclass
We want to modify the SavingsAccount class so that each deposit transaction has a
(fixed) FEE cost, which is automatically debited from the account
Note that SavingAccount uses the deposit method inherited from BankAccount for
the deposit transaction, a method on which we have no control
Syntax:
super.methodName(arguments)
Purpose: to call the methodName method of the superclass instead of the method
with the same name (overridden) in the current class
We have already seen that the java.lang.Object class is the root superclass, that is,
all classes defined in Java implicitly inherit its methods, including
public String toString ()
The invocation of this method for any object returns the so-called standard text
description
BankAccount@111f71
the name of the class followed by the @ character and the address of the object in
memory
The fact that all classes derive (even indirectly) from Object and that Object defines
the toString() method allows the println() method of java.io.PrintStream to work
passing a reference to objects of any type to System.out.println(), we get the display
of the standard text description of the object referred to
how does println() work?
println() simply calls the object's toString() metod, and invocation is always possible
because all classes have the toString () method, possibly inherited from Object
If all classes already have the toString () method, inheriting it from Object, why
should we override it, redefine it?
BankAccount@111f71
The compiler implicitly invokes the toString() method of a class when concatenating
an object of the class with a string
BankAccount acct = new BankAccount();
String s = "Account " + acct;
This concatenation is syntactically correct, as we had already seen for numeric data
types, and the compiler interprets the concatenation as if it were written like this
The toString() method of a class should provide a string containing all the status
information of the object, that is
the value of all its instance variables
the value of any (non-constant) static variables of the class
This programming style is very useful for debugging and is used in the standard
library
In reality, the interpreter always calls the super() constructor when it build a
subclass
if the call to super (...) constructor is not explicitly indicated by the programmer, the
compiler automatically inserts the invocation of super() without parameters
this happens, for example, in the case of the first constructor of SavingsAccount
The explicit invocation of super (...), if present, must be the first statement of the
constructor
Syntax:
SubclassName(arguments)
{ super(possibleArguments);
...
}
BankAccounts
Object SavingsAccounts
The three variables, although of different types, point to the same object
sAcct SavingsAccount
bAcct balance 0
obj interestRate 10
The conversion between subclass reference and superclass reference can also occur
implicitly (as between int and double)
BankAccount other = new BankAccount(1000);
SavingsAccount sAcct = new SavingsAccount(10);
other.transferTo(sAcct, 500);
Since the transferTo() method requires a reference of type BankAccount, the compiler
verifies that the argument is of type BankAccount or any subclass of BankAccount
and, if the reference is of a type of a subclass, it automatically converts the
reference.
Now we can understand how it is possible to define methods which, like println(),
can receive as arguments objects of any type
a reference to an object of any type can always be automatically converted to a
reference of type Object
public void println(Object obj)
{ println(obj.toString()); // calls the method for strings
}
public void println(String s)
{ ... // this method can print strings
}
incompatible types
But does it make sense to try to found : BankAccount
required: SavingsAccount
make such a conversion? sAcct = bAcct;
^
1 error
We already know that a subclass object can be used as if it were a superclass object
We might think
acct is a variable declared as a BankAccount type, therefore the BankAccount
deposit() method is invoked (i.e. no fees are charged for the payment operation ...)
But acct contains a reference to an object which is actually of type SavingsAccount!
And the Java interpreter knows it (the compiler doesn't)
according to Java semantics, the SavingsAccount deposit() method is invoked
Syntax:
referenceVariableName instanceof ClassName
Purpose: it is a boolean operator that returns true if and only if the reference variable
points to an object that is an instance of the ClassName class (or one of its subclasses),
false otherwise
In the case of the assignment to reference variable af a variable of type ClassName, the
interpreter DOES NOT throw java.lang.ClassCastException, if the check with instanceof
has been positive
Note: the result does not depend on the type declared for the reference variable, but on
the type of the object to which the variable actually refers at the time of execution
We know that a subclass inherits the instance variables defined in the superclass
each object in the subclass has its own copy of these variables, as does each object
in the superclass
but if they are private, the subclass methods cannot access them!
public class SavingsAccount extends BankAccount
{ ...
public void addInterest()
{ deposit(getBalance() * interestRate/100);
}
}
Let's try to directly access directly: the compiler reports the error
balance has private access in BankAccount
Therefore, to access inherited private variables, we must use public methods made
available by the superclass, if any
public class SavingsAccount extends BankAccount
{ ...
public void addInterest()
{ deposit(balance * interestRate/100);
}
}
In this way, the compiler does not report any errors, but now SavingsAccount has
two variables called balance, one of its own and one inherited
there is no relationship between the two balance variables!
99 Foundations of Computer Science – A. Luchetta 2021-2022
Overshadowing the inherited instance variables
The existence of two distinct balance variables is a source of errors that are difficult
to diagnose
Changes to variable balance made by SavingsAccount methods are not visible to
BankAccount methods, and vice versa
for example, the invocation of withdraw() (defined in BankAccount) changes the
balance variable of BankAccount, but does not change the balance variable defined
in SavingsAccount
the interest calculation will be wrong