Advanced Topics in Java Core Concepts in Data Structures 1st Edition Noel Kalicharan (Auth.) Download
Advanced Topics in Java Core Concepts in Data Structures 1st Edition Noel Kalicharan (Auth.) Download
https://ebookgate.com/product/advanced-topics-in-java-core-
concepts-in-data-structures-1st-edition-noel-kalicharan-auth/
https://ebookgate.com/product/java-structures-data-structures-in-java-
for-the-principled-programmer-2nd-edition-duane-bailey/
ebookgate.com
https://ebookgate.com/product/data-structures-outside-in-with-
java-1st-edition-sesh-venugopal/
ebookgate.com
https://ebookgate.com/product/caia-level-ii-advanced-core-topics-in-
alternative-investments-2nd-edition-caia-association/
ebookgate.com
https://ebookgate.com/product/core-topics-in-pain-1st-edition-anita-
holdcroft/
ebookgate.com
Java Software Structures Designing and Using Data
Structures 3rd Edition John Lewis
https://ebookgate.com/product/java-software-structures-designing-and-
using-data-structures-3rd-edition-john-lewis/
ebookgate.com
https://ebookgate.com/product/core-topics-in-mechanical-
ventilation-1st-edition-iain-mackenzie/
ebookgate.com
https://ebookgate.com/product/aagbi-core-topics-in-
anaesthesia-2015-1st-edition-griffiths/
ebookgate.com
https://ebookgate.com/product/data-structures-other-objects-using-
java-4th-edition-michael-mann/
ebookgate.com
For your convenience Apress has placed some of the front
matter material after the index. Please use the Bookmarks
and Contents at a Glance links to access them.
Contents at a Glance
Index���������������������������������������������������������������������������������������������������������������������������������309
v
Chapter 1
1
Chapter 1 ■ Sorting, Searching, and Merging
2nd pass
• Find the smallest number in positions 1 to 6; the smallest is 33, found in position 5.
• Interchange the numbers in positions 1 and 5. This gives us the following:
3rd pass
• Find the smallest number in positions 2 to 6; the smallest is 48, found in position 5.
• Interchange the numbers in positions 2 and 5. This gives us the following:
4th pass
• Find the smallest number in positions 3 to 6; the smallest is 52, found in position 6.
• Interchange the numbers in positions 3 and 6. This gives us the following:
5th pass
• Find the smallest number in positions 4 to 6; the smallest is 57, found in position 4.
• Interchange the numbers in positions 4 and 4. This gives us the following:
2
Chapter 1 ■ Sorting, Searching, and Merging
6th pass
• Find the smallest number in positions 5 to 6; the smallest is 65, found in position 6.
• Interchange the numbers in positions 5 and 6. This gives us the following:
The array is now completely sorted. Note that once the 6th largest (65) has been placed in its final position (5),
the largest (79) would automatically be in the last position (6).
In this example, we made six passes. We will count these passes by letting the variable h go from 0 to 5. On each
pass, we find the smallest number from positions h to 6. If the smallest number is in position s, we interchange the
numbers in positions h and s.
In general, for an array of size n, we make n-1 passes. In our example, we sorted 7 numbers in 6 passes.
The following is a pseudocode outline of the algorithm for sorting num[0..n-1]:
for h = 0 to n - 2
s = position of smallest number from num[h] to num[n-1]
swap num[h] and num[s]
endfor
We can implement this algorithm as follows, using the generic parameter list:
The two statements in the for loop could be replaced by the following:
3
Chapter 1 ■ Sorting, Searching, and Merging
To test whether selectionSort works properly, we write Program P1.1. Only main is shown. To complete the
program, just add selectionSort, getSmallest, and swap.
Program P1.1
import java.util.*;
public class SelectSortTest {
final static int MaxNumbers = 10;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int[] num = new int[MaxNumbers];
System.out.printf("Type up to %d numbers followed by 0\n", MaxNumbers);
int n = 0;
int v = in.nextInt();
while (v != 0 && n < MaxNumbers) {
num[n++] = v;
v = in.nextInt();
}
if (v != 0) {
System.out.printf("\nMore than %d numbers entered\n", MaxNumbers);
System.out.printf("First %d used\n", MaxNumbers);
}
if (n == 0) {
System.out.printf("\nNo numbers supplied\n");
System.exit(1);
}
//n numbers are stored from num[0] to num[n-1]
selectionSort(num, 0, n-1);
System.out.printf("\nThe sorted numbers are\n");
for (v = 0; v < n; v++) System.out.printf("%d ", num[v]);
System.out.printf("\n");
} //end main
The program requests up to 10 numbers (as defined by MaxNumbers), stores them in the array num, calls
selectionSort, and then prints the sorted list.
The following is a sample run of the program:
Note that if the user enters more than ten numbers, the program will recognize this and sort only the first ten.
4
Chapter 1 ■ Sorting, Searching, and Merging
We say selection sort is of order O(n2) (“big O n squared”). The constant ½ is not important in “big O” notation
since, as n gets very big, the constant becomes insignificant.
On each pass, we swap two items using three assignments. Since we make n-1 passes, we make 3(n-1)
assignments in all. Using “big O” notation, we say that the number of assignments is O(n). The constants 3 and 1 are
not important as n gets large.
Does selection sort perform any better if there is order in the data? No. One way to find out is to give it a sorted list
and see what it does. If you work through the algorithm, you will see that the method is oblivious to order in the data.
It will make the same number of comparisons every time, regardless of the data.
As we will see, some sorting methods (mergesort and quicksort; see Chapters 5 and 9) require extra array storage to
implement them. Note that selection sort is performed “in place” in the given array and does not require additional storage.
As an exercise, modify the programming code so that it counts the number of comparisons and assignments
made in sorting a list using selection sort.
Now, think of the numbers as cards on a table that are picked up one at a time in the order they appear in the
array. Thus, we first pick up 57, then 48, then 79, and so on, until we pick up 52. However, as we pick up each new
number, we add it to our hand in such a way that the numbers in our hand are all sorted.
When we pick up 57, we have just one number in our hand. We consider one number to be sorted.
When we pick up 48, we add it in front of 57 so our hand contains the following:
48 57
When we pick up 79, we place it after 57 so our hand contains this:
48 57 79
When we pick up 65, we place it after 57 so our hand contains this:
48 57 65 79
At this stage, four numbers have been picked up, and our hand contains them in sorted order.
When we pick up 15, we place it before 48 so our hand contains this:
15 48 57 65 79
When we pick up 33, we place it after 15 so our hand contains this:
15 33 48 57 65 79
Finally, when we pick up 52, we place it after 48 so our hand contains this:
15 33 48 52 57 65 79
5
Chapter 1 ■ Sorting, Searching, and Merging
1st pass
• Process num[1], that is, 48. This involves placing 48 so that the first two numbers are sorted;
num[0] and num[1] now contain the following:
2nd pass
• Process num[2], that is, 79. This involves placing 79 so that the first three numbers are sorted;
num[0] to num[2] now contain the following:
3rd pass
• Process num[3], that is, 65. This involves placing 65 so that the first four numbers are sorted;
num[0] to num[3] now contain the following:
4th pass
• Process num[4], that is, 15. This involves placing 15 so that the first five numbers are sorted.
To simplify the explanation, think of 15 as being taken out and stored in a simple variable
(key, say) leaving a “hole” in num[4]. We can picture this as follows:
6
Chapter 1 ■ Sorting, Searching, and Merging
• We can express the logic of placing 15 (key) by comparing it with the numbers to its left,
starting with the nearest one. As long as key is less than num[k], for some k, we move num[k] to
position num[k + 1] and move on to consider num[k-1], providing it exists. It won’t exist when
k is actually 0. In this case, the process stops, and key is inserted in position 0.
5th pass
• Process num[5], that is, 33. This involves placing 33 so that the first six numbers are sorted.
This is done as follows:
• Store 33 in key, leaving location 5 free.
• Compare 33 with 79; it is smaller, so move 79 to location 5, leaving location 4 free.
• Compare 33 with 65; it is smaller, so move 65 to location 4, leaving location 3 free.
• Compare 33 with 57; it is smaller, so move 57 to location 3, leaving location 2 free.
• Compare 33 with 48; it is smaller, so move 48 to location 2, leaving location 1 free.
7
Chapter 1 ■ Sorting, Searching, and Merging
• Compare 33 with 15; it is bigger, so insert 33 in location 1. This gives the following:
• We can express the logic of placing 33 by comparing it with the numbers to its left, starting
with the nearest one. As long as key is less than num[k], for some k, we move num[k] to
position num[k + 1] and move on to consider num[k-1], providing it exists. If key is greater
than or equal to num[k] for some k, then key is inserted in position k+1. Here, 33 is greater
than num[0] and so is inserted into num[1].
6th pass
• Process num[6], that is, 52. This involves placing 52 so that the first seven (all) numbers are
sorted. This is done as follows:
• Store 52 in key, leaving location 6 free.
• Compare 52 with 79; it is smaller, so move 79 to location 6, leaving location 5 free.
• Compare 52 with 65; it is smaller, so move 65 to location 5, leaving location 4 free.
• Compare 52 with 57; it is smaller, so move 57 to location 4, leaving location 3 free.
• Compare 52 with 48; it is bigger; so insert 52 in location 3. This gives the following:
for h = 1 to n - 1 do
insert num[h] among num[0] to num[h-1] so that num[0] to num[h] are sorted
endfor
Using this outline, we write the function insertionSort using the parameter list.
The while statement is at the heart of the sort. It states that as long as we are within the array (k >= 0) and
the current number (key) is less than the one in the array (key < list[k]), we move list[k] to the right
(list[k+1] = list[k]) and move on to the next number on the left (--k).
8
Chapter 1 ■ Sorting, Searching, and Merging
We exit the while loop if k is equal to -1 or if key is greater than or equal to list[k], for some k. In either case,
key is inserted into list[k+1].
If k is -1, it means that the current number is smaller than all the previous numbers in the list and must be
inserted in list[0]. But list[k + 1] is list[0] when k is -1, so key is inserted correctly in this case.
The function sorts in ascending order. To sort in descending order, all we have to do is change < to > in the while
condition, like this:
Program P1.2
import java.util.*;
public class InsertSortTest {
final static int MaxNumbers = 10;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int[] num = new int[MaxNumbers];
System.out.printf("Type up to %d numbers followed by 0\n", MaxNumbers);
int n = 0;
int v = in.nextInt();
while (v != 0 && n < MaxNumbers) {
num[n++] = v;
v = in.nextInt();
}
if (v != 0) {
System.out.printf("\nMore than %d numbers entered\n", MaxNumbers);
System.out.printf("First %d used\n", MaxNumbers);
}
if (n == 0) {
System.out.printf("\nNo numbers supplied\n");
System.exit(1);
}
//n numbers are stored from num[0] to num[n-1]
insertionSort(num, n);
System.out.printf("\nThe sorted numbers are\n");
for (v = 0; v < n; v++) System.out.printf("%d ", num[v]);
System.out.printf("\n");
} //end main
9
Chapter 1 ■ Sorting, Searching, and Merging
list[k + 1] = key;
} //end for
} //end insertionSort
} //end class InsertSortTest
The program requests up to ten numbers (as defined by MaxNumbers), stores them in the array num, calls
insertionSort, and then prints the sorted list.
The following is a sample run of the program:
Note that if the user enters more than ten numbers, the program will recognize this and sort only the first ten.
We could easily generalize insertionSort to sort a portion of a list. To illustrate, we rewrite insertionSort
(calling it insertionSort1) to sort list[lo] to list[hi] where lo and hi are passed as arguments to the function.
Since element lo is the first one, we start processing elements from lo+1 until element hi. This is reflected in the
for statement. Also now, the lowest subscript is lo, rather than 0. This is reflected in the while condition k >= lo.
Everything else remains the same as before.
Program P1.2a
import java.util.*;
public class InsertSort1Test {
final static int MaxNumbers = 10;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int[] num = new int[MaxNumbers];
System.out.printf("Type up to %d numbers followed by 0\n", MaxNumbers);
int n = 0;
int v = in.nextInt();
while (v != 0 && n < MaxNumbers) {
num[n++] = v;
v = in.nextInt();
}
10
Chapter 1 ■ Sorting, Searching, and Merging
if (v != 0) {
System.out.printf("\nMore than %d numbers entered\n", MaxNumbers);
System.out.printf("First %d used\n", MaxNumbers);
}
if (n == 0) {
System.out.printf("\nNo numbers supplied\n");
System.exit(1);
}
//n numbers are stored from num[0] to num[n-1]
insertionSort1(num, 0, n-1);
System.out.printf("\nThe sorted numbers are\n");
for (v = 0; v < n; v++) System.out.printf("%d ", num[v]);
System.out.printf("\n");
} //end main
∑ 2 ( j − 1) = ½ {1 + 2 + ... + n − 1} = ¼ n (n − 1) ≈ ¼ n
1 2
j =2
We say insertion sort is of order O(n2) (“big O n squared”). The constant ¼ is not important as n gets large.
Each time we make a comparison, we also make an assignment. Hence, the total number of assignments is also
¼ n(n-1) » ¼ n2.
We emphasize that this is an average for random data. Unlike selection sort, the actual performance of insertion
sort depends on the data supplied. If the given array is already sorted, insertion sort will quickly determine this by
making n-1 comparisons. In this case, it runs in O(n) time. One would expect that insertion sort will perform better
the more order there is in the data.
If the given data is in descending order, insertion sort performs at its worst since each new number has to travel
all the way to the beginning of the list. In this case, the number of comparisons is ½ n(n-1) » ½ n2. The number of
assignments is also ½ n(n-1) » ½ n2.
Thus, the number of comparisons made by insertion sort ranges from n-1 (best) to ¼ n2 (average) to ½ n2 (worst).
The number of assignments is always the same as the number of comparisons.
As with selection sort, insertion sort does not require extra array storage for its implementation.
As an exercise, modify the programming code so that it counts the number of comparisons and assignments
made in sorting a list using insertion sort.
11
Chapter 1 ■ Sorting, Searching, and Merging
Program P1.2b
import java.util.*;
public class InsertSort2Test {
final static int MaxNumbers = 10;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int[] num = new int[MaxNumbers];
System.out.printf("Type up to %d numbers followed by 0\n", MaxNumbers);
int n = 0;
int v = in.nextInt();
while (v != 0 && n < MaxNumbers) {
num[n++] = v;
v = in.nextInt();
}
if (v != 0) {
System.out.printf("\nMore than %d numbers entered\n", MaxNumbers);
System.out.printf("First %d used\n", MaxNumbers);
}
if (n == 0) {
System.out.printf("\nNo numbers supplied\n");
System.exit(1);
}
12
Chapter 1 ■ Sorting, Searching, and Merging
13
Chapter 1 ■ Sorting, Searching, and Merging
The function is pretty much the same as the previous ones except for the declaration of list and the use of
compareToIgnoreCase to compare two strings. If case matters, you can use compareTo.
We test insertionSort3 with Program P1.3.
Program P1.3
import java.util.*;
public class SortStrings {
final static int MaxNames = 8;
public static void main(String[] args) {
String name[] = {"Graham, Ariel", "Perrott, Chloe",
"Charles, Kandice", "Seecharan, Anella", "Reyes, Aaliyah",
"Graham, Ashleigh", "Reyes, Ayanna", "Greaves, Sherrelle" };
Charles, Kandice
Graham, Ariel
Graham, Ashleigh
Greaves, Sherrelle
Perrott, Chloe
Reyes, Aaliyah
Reyes, Ayanna
Seecharan, Anella
14
Chapter 1 ■ Sorting, Searching, and Merging
name id
Consider the problem of sorting the names in alphabetical order. At the end, we would want each name to have
its correct ID number. So, for example, after the sorting is done, name[0] should contain “Charles, Kandice” and id[0]
should contain 4455.
To achieve this, each time a name is moved during the sorting process, the corresponding ID number must also
be moved. Since the name and ID number must be moved “in parallel,” we say we are doing a “parallel sort” or we are
sorting “parallel arrays.”
We rewrite insertionSort3 to illustrate how to sort parallel arrays. We simply add the code to move an ID
whenever a name is moved. We call it parallelSort.
public static void parallelSort(String[] list, int id[], int lo, int hi) {
//Sort the names in list[lo] to list[hi] in alphabetical order,
//ensuring that each name remains with its original id number.
for (int h = lo + 1; h <= hi; h++) {
String key = list[h];
int m = id[h]; // extract the id number
int k = h - 1; //start comparing with previous item
while (k >= lo && key.compareToIgnoreCase(list[k]) < 0) {
list[k + 1] = list[k];
id[k+ 1] = id[k]; //move up id number when we move a name
--k;
}
list[k + 1] = key;
id[k + 1] = m; //store the id number in the same position as the name
} //end for
} //end parallelSort
Program P1.4
import java.util.*;
public class ParallelSort {
final static int MaxNames = 8;
public static void main(String[] args) {
String name[] = {"Graham, Ariel", "Perrott, Chloe",
"Charles, Kandice", "Seecharan, Anella", "Reyes, Aaliyah",
"Graham, Ashleigh", "Reyes, Ayanna", "Greaves, Sherrelle" };
int id[] = {3050,2795,4455,7824,6669,5000,5464,6050};
15
Chapter 1 ■ Sorting, Searching, and Merging
We note, in passing, that if we have several sets of related items to process, storing each set in a separate array
would not be the best way to proceed. It would be better to group the items in a class and work with the group as we
would a single item. We’ll show you how to do this in Section 2.14.
Suppose we were searching for 70. The search will proceed as described above until we compare 70 with 66
(in location 7).
• Since 70 is bigger, we know that if 70 is in the list at all, it must be after position 7, since the
numbers are in ascending order. In our next step, we confine our search to locations 8 to 8.
This is just one location.
• We compare 70 with item 8, that is, 72. Since 70 is smaller, we know that if 70 is in the list at
all, it must be before position 8. Since it can’t be after position 7 and before position 8, we
conclude that it is not in the list.
At each stage of the search, we confine our search to some portion of the list. Let us use the variables lo and hi
as the subscripts that define this portion. In other words, our search will be confined to num[lo] to num[hi].
Initially, we want to search the entire list so that we will set lo to 0 and hi to 12, in this example.
How do we find the subscript of the middle item? We will use the following calculation:
mid = (lo + hi) / 2;
Since integer division will be performed, the fraction, if any, is discarded. For example, when lo is 0 and hi is 12,
mid becomes 6; when lo is 7 and hi is 12, mid becomes 9; and when lo is 7 and hi is 8, mid becomes 7.
As long as lo is less than or equal to hi, they define a nonempty portion of the list to be searched. When lo is
equal to hi, they define a single item to be searched. If lo ever gets bigger than hi, it means we have searched the
entire list and the item was not found.
Based on these ideas, we can now write a function binarySearch. To be more general, we will write it so that the
calling routine can specify which portion of the array it wants the search to look for the item.
Thus, the function must be given the item to be searched for (key), the array (list), the start position of the
search (lo), and the end position of the search (hi). For example, to search for the number 66 in the array num, above,
we can issue the call binarySearch(66, num, 0, 12).
The function must tell us the result of the search. If the item is found, the function will return its location. If not
found, it will return -1.
public static int binarySearch(int key, int[] list, int lo, int hi) {
//search for key from list[lo] to list[hi]
//if found, return its location; otherwise, return -1
while (lo <= hi) {
int mid = (lo + hi) / 2;
if (key == list[mid]) return mid; // found
if (key < list[mid]) hi = mid - 1;
else lo = mid + 1;
}
return -1; //lo and hi have crossed; key not found
}
If we want to search for item from locations i to j, we can write the following:
17
Chapter 1 ■ Sorting, Searching, and Merging
Program P1.5
public class BinarySearchTest {
public static void main(String[] args) {
int[] num = {17, 24, 31, 39, 44, 49, 56, 66, 72, 78, 83, 89, 96};
int n = binarySearch(66, num, 0, 12);
System.out.printf("%d\n", n); //will print 7; 66 in pos. 7
n = binarySearch(66, num, 0, 6);
System.out.printf("%d\n", n); //will print -1; 66 not in 0 to 6
n = binarySearch(70, num, 0, 12);
System.out.printf("%d\n", n); //will print -1; 70 not in list
n = binarySearch(89, num, 5, 12);
System.out.printf("%d\n", n); //will print 11; 89 in pos. 11
} //end main
7
-1
-1
11
public static int binarySearch(String key, String[] list, int lo, int hi) {
//search for key from list[lo] to list[hi]
//if found, return its location; otherwise, return -1
while (lo <= hi) {
int mid = (lo + hi) / 2;
int cmp = key.compareTo(list[mid]);
if (cmp == 0) return mid; // search succeeds
if (cmp < 0) hi = mid -1; // key is ‘less than’ list[mid]
else lo = mid + 1; // key is ‘greater than’ list[mid]
}
return -1; //lo and hi have crossed; key not found
} //end binarySearch
Since we need to know whether one string is equal to, or less than, another, it is best to use the compareTo
method.
18
Chapter 1 ■ Sorting, Searching, and Merging
Note that we call compareTo only once. The value returned (cmp) tells us all we need to know. If we are
comparing words or names and we want the case of the letters to be ignored in the comparison, we can use
compareToIgnoreCase.
The function can be tested with Program P1.6.
Program P1.6
import java.util.*;
public class BinarySearchString {
final static int MaxNames = 8;
public static void main(String[] args) {
String name[] = {"Charles, Kandice", "Graham, Ariel",
"Graham, Ashleigh", "Greaves, Sherrelle", "Perrott, Chloe",
"Reyes, Aaliyah", "Reyes, Ayanna", "Seecharan, Anella"};
} //end main
This sets up the array name with the names in alphabetical order. It then calls binarySearch with various names
and prints the result of each search.
One may wonder what might happen with a call like this:
Here, we are telling binarySearch to look for "Perrott, Chloe" in locations 5 to 10 of the given array. However,
locations 8 to 10 do not exist in the array. The result of the search will be unpredictable. The program may crash or
return an incorrect result. The onus is on the calling program to ensure that binarySearch (or any other function) is
called with valid arguments.
19
Chapter 1 ■ Sorting, Searching, and Merging
This is a typical “search and insert” situation. We search for the next word among the words stored so far. If the search
succeeds, the only thing to do is increment its count. If the search fails, the word is put in the table and its count set to 1.
A major design decision here is how to search the table, which, in turn, will depend on where and how a new
word is inserted in the table. The following are two possibilities:
1. A new word is inserted in the next free position in the table. This implies that a sequential
search must be used to look for an incoming word since the words would not be in any
particular order. This method has the advantages of simplicity and easy insertion, but
searching takes longer as more words are put in the table.
2. A new word is inserted in the table in such a way that the words are always in alphabetical
order. This may entail moving words that have already been stored so that the new word
may be slotted in the right place. However, since the table is in order, a binary search can
be used to search for an incoming word.
For (2), searching is faster, but insertion is slower than in (1). Since, in general, searching is done more frequently
than inserting, (2) might be preferable.
Another advantage of (2) is that, at the end, the words will already be in alphabetical order and no sorting will be
required. If (1) is used, the words will need to be sorted to obtain the alphabetical order.
We will write our program using the approach in (2). The complete program is shown as Program P1.7.
Program P1.7
import java.io.*;
import java.util.*;
public class WordFrequency {
final static int MaxWords = 50;
public static void main(String[] args) throws IOException {
String[] wordList = new String[MaxWords];
int[] frequency = new int[MaxWords];
FileReader in = new FileReader("passage.txt");
PrintWriter out = new PrintWriter(new FileWriter("output.txt"));
20
Chapter 1 ■ Sorting, Searching, and Merging
int numWords = 0;
String word = getWord(in).toLowerCase();
while (!word.equals("")) {
int loc = binarySearch(word, wordList, 0, numWords-1);
if (word.compareTo(wordList[loc]) == 0) ++frequency[loc]; //word found
else //this is a new word
if (numWords < MaxWords) { //if table is not full
addToList(word, wordList, frequency, loc, numWords-1);
++numWords;
}
else out.printf("'%s' not added to table\n", word);
word = getWord(in).toLowerCase();
}
printResults(out, wordList, frequency, numWords);
in.close();
out.close();
} // end main
public static int binarySearch(String key, String[] list, int lo, int hi){
//search for key from list[lo] to list[hi]
//if found, return its location;
//if not found, return the location in which it should be inserted
//the calling program will check the location to determine if found
while (lo <= hi) {
int mid = (lo + hi) / 2;
int cmp = key.compareTo(list[mid]);
if (cmp == 0) return mid; // search succeeds
if (cmp < 0) hi = mid -1; // key is 'less than' list[mid]
else lo = mid + 1; // key is 'greater than' list[mid]
}
return lo; //key must be inserted in location lo
} //end binarySearch
public static void addToList(String item, String[] list, int[] freq, int p, int n) {
//adds item in position list[p]; sets freq[p] to 1
//shifts list[n] down to list[p] to the right
for (int h = n; h >= p; h--) {
list[h + 1] = list[h];
freq[h + 1] = freq[h];
}
list[p] = item;
freq[p] = 1;
} //end addToList
public static void printResults(PrintWriter out, String[] list, int freq[], int n) {
out.printf("\nWords Frequency\n\n");
for (int h = 0; h < n; h++)
out.printf("%-20s %2d\n", list[h], freq[h]);
} //end printResults
21
Chapter 1 ■ Sorting, Searching, and Merging
When Program P1.7 is run, it stores its output in output.txt. Here is the output:
Words Frequency
are 2
be 1
because 1
character 3
concerned 1
do 1
is 4
looking 1
merely 1
more 1
no 1
one 1
others 1
our 1
really 1
reputation 2
than 1
think 2
we 2
what 3
when 1
while 1
with 1
you 2
your 4
22
Chapter 1 ■ Sorting, Searching, and Merging
23
Chapter 1 ■ Sorting, Searching, and Merging
The top two cards are now 35 and 47. The smaller, 35, is removed and added to C, which now contains 16 21 25
28 35. This exposes the number 40.
The top two cards are now 40 and 47. The smaller, 40, is removed and added to C, which now contains 16 21 25
28 35 40. This exposes the number 61.
The top two cards are now 61 and 47. The smaller, 47, is removed and added to C, which now contains 16 21 25
28 35 40 47. This exposes the number 54.
The top two cards are now 61 and 54. The smaller, 54, is removed and added to C, which now contains 16 21 25
28 35 40 47 54. The list B has no more numbers.
We copy the remaining elements (61 75) of A to C, which now contains the following:
16 21 25 28 35 40 47 54 61 75
The merge is completed.
At each step of the merge, we compare the smallest remaining number of A with the smallest remaining number
of B. The smaller of these is added to C. If the smaller comes from A, we move on to the next number in A; if the smaller
comes from B, we move on to the next number in B.
This is repeated until all the numbers in either A or B have been used. If all the numbers in A have been used, we add
the remaining numbers from B to C. If all the numbers in B have been used, we add the remaining numbers from A to C.
We can express the logic of the merge as follows:
24
Chapter 1 ■ Sorting, Searching, and Merging
The function takes the arguments A, m, B, n, and C, performs the merge, and returns the number of elements,
m + n, in C.
Program P1.8 shows a simple main function that tests the logic of merge. It sets up arrays A and B, calls merge,
and prints C. When run, the program prints the following:
16 21 25 28 35 40 47 54 61 75
Program P1.8
public class MergeTest {
public static void main(String[] args) {
int[] A = {21, 28, 35, 40, 61, 75}; //size 6
int[] B = {16, 25, 47, 54}; //size 4
int[] C = new int[20]; //enough to hold all the elements
int n = merge(A, 6, B, 4, C);
for (int j = 0; j < n; j++) System.out.printf("%d ", C[j]);
System.out.printf("\n");
} //end main
The while loop expresses the following logic: as long as there is at least one element to process in either A or B,
we enter the loop. If we are finished with A (i == m), copy an element from B to C. If we are finished with B (j == n),
copy an element from A to C. Otherwise, copy the smaller of A[i] and B[j] to C. Each time we copy an element from
an array, we add 1 to the subscript for that array.
While the previous version implements the merge in a straightforward way, it seems reasonable to say that this
version is a bit neater.
25
Chapter 1 ■ Sorting, Searching, and Merging
EXERCISES 1
1. A survey of 10 pop artists is made. Each person votes for an artist by specifying the number
of the artist (a value from 1 to 10). Each voter is allowed one vote for the artist of their choice.
The vote is recorded as a number from 1 to 10. The number of voters is unknown beforehand,
but the votes are terminated by a vote of 0. Any vote that is not a number from 1 to 10 is
a spoiled vote. A file, votes.txt, contains the names of the candidates. The first name is
considered as candidate 1, the second as candidate 2, and so on. The names are followed by
the votes. Write a program to read the data and evaluate the results of the survey.
Print the results in alphabetical order by artist name and in order by votes received (most votes first).
Print all output to the file, results.txt.
2. Write a program to read names and phone numbers into two arrays. Request a name and
print the person’s phone number. Use binary search to look up the name.
3. Write a program to read English words and their equivalent Spanish words into two arrays.
Request the user to type several English words. For each, print the equivalent Spanish word.
Choose a suitable end-of-data marker. Search for the typed words using binary search.
Modify the program so that the user types Spanish words instead.
4. The median of a set of n numbers (not necessarily distinct) is obtained by arranging the
numbers in order and taking the number in the middle. If n is odd, there is a unique middle
number. If n is even, then the average of the two middle values is the median. Write a
program to read a set of n positive integers (assume n < 100) and print their median; n is not
given, but 0 indicates the end of the data.
5. The mode of a set of n numbers is the number that appears most frequently. For example, the
mode of 7 3 8 5 7 3 1 3 4 8 9 is 3. Write a program to read a set of n positive integers
(assume n < 100) and print their mode; n is not given, but 0 indicates the end of the data.
6. An array chosen contains n distinct integers arranged in no particular order. Another array
called winners contains m distinct integers arranged in ascending order. Write code to
determine how many of the numbers in chosen appear in winners.
7. A multiple-choice examination consists of 20 questions. Each question has five choices,
labeled A, B, C, D, and E. The first line of data contains the correct answers to the 20
questions in the first 20 consecutive character positions, for example:
BECDCBAADEBACBAEDDBE
Each subsequent line contains the answers for a candidate. Data on a line consists of a
candidate number (an integer), followed by one or more spaces, followed by the 20 answers
given by the candidate in the next 20 consecutive character positions. An X is used if a
candidate did not answer a particular question. You may assume all data is valid and stored
in a file exam.dat. A sample line is as follows:
4325 BECDCBAXDEBACCAEDXBE
There are at most 100 candidates. A line containing a “candidate number” 0 only indicates
the end of the data.
26
Chapter 1 ■ Sorting, Searching, and Merging
Points for a question are awarded as follows—correct answer: 4 points; wrong answer:
-1 point; no answer: 0 points.
Write a program to process the data and print a report consisting of candidate number and
the total points obtained by the candidate, in ascending order by candidate number. At the
end, print the average number of points gained by the candidates.
8. A is an array sorted in descending order. B is an array sorted in descending order. Merge A and
B into C so that C is in descending order.
9. A is an array sorted in descending order. B is an array sorted in descending order. Merge A and
B into C so that C is in ascending order.
10. A is an array sorted in ascending order. B is an array sorted in descending order. Merge A and
B into C so that C is in ascending order.
11. An array A contains integers that first increase in value and then decrease in value. Here’s an
example:
It is unknown at which point the numbers start to decrease. Write efficient code to code to
copy the numbers in A to another array B so that B is sorted in ascending order. Your code
must take advantage of the way the numbers are arranged in A.
12. Two words are anagrams if one word can be formed by rearranging all the letters of the
other word, for example: section, notices. Write a program to read two words and determine
whether they are anagrams.
Write another program to read a list of words and find all sets of words such that words
within a set are anagrams of each other.
27
Chapter 2
Introduction to Objects
29
Chapter 2 ■ Introduction to Objects
2.1 Objects
Java is considered an object-oriented programming language. The designers created it such that objects become the
center of attention. Java programs create and manipulate objects in an attempt to model how the real world operates.
For our purposes, an object is an entity that has a state and methods to manipulate that state. The state of an object is
determined by its attributes.
For example, we can think of a person as an object. A person has attributes such as name, age, gender, height,
color of hair, color of eyes, and so on. Within a program, each attribute is represented by an appropriate variable;
for instance, a String variable can represent name, an int variable can represent age, a char variable can represent
gender, a double variable can represent height, and so on.
We normally use the term field names (or, simply, fields) to refer to these variables. Thus, the state of an object is
defined by the values in its fields. In addition, we will need methods to set and/or change the values of the fields as
well as to retrieve their values. For example, if we are interested in a person’s height, we would need a method to “look
into” the object and return the value of the height field.
A car is another common example of an object. It has attributes such as manufacturer, model, seating capacity,
fuel capacity, actual fuel in the tank, mileage, type of music equipment, and speed. A book object has attributes such
as author, title, price, number of pages, type of binding (hardcover, paperback, spiral), and if it is in stock. A person,
a car, and a book are examples of concrete objects. Note, however, that an object could also represent an abstract
concept such as a department in a company or a faculty in a university.
In the previous example, we did not speak of a specific person. Rather, we spoke of a general category “person”
such that everyone in the category has the attributes mentioned. (Similar remarks apply to car and book.) In Java
terminology, “person” is a class. We think of a class as a general category (a template) from which we can create
specific objects.
An object, then, is an instance of a class; in this example, a Person object would refer to a specific person. To work
with two Person objects, we would need to create two objects from the class definition of Person. Each object would
have its own copy of the field variables (also called instance variables); the values of the variables in one object could
be different from the values of the variables in the other object.
Program P2.1
//prompt for two numbers and find their sum
import java.util.*;
public class Sum {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.printf("Enter first number: ");
int a = in.nextInt();
System.out.printf("Enter second number: ");
int b = in.nextInt();
System.out.printf("%d + %d = %d\n", a, b, a + b);
}
} //end class Sum
The program consists of one class (ProgramP1_1) and one method (main) within the class. The class is used
simply as the framework within which to write the logic of the program. We will now show how to define and use a
class to create (we say instantiate) objects.
30
Chapter 2 ■ Introduction to Objects
In Java, every object belongs to some class and can be created from the class definition only. Consider the
following (partial) definition of the class Book:
31
Chapter 2 ■ Introduction to Objects
Book b;
b = new Book();
The first statement declares b as a variable of type Book. From this, we see that a class name is considered to be a
type (similar to int or char) and can be used to declare variables. We say that b is an object variable of type Book.
The declaration of b does not create an object; it simply creates a variable whose value will eventually be a pointer
to an object. When declared as shown, its value is undefined.
The second statement finds some available memory where a Book object can be stored, creates the object, and
stores the address of the object in b. (Think of the address as the first memory location occupied by the object. If the
object occupies locations 2575 to 2599, its address is 2575.) We say that b contains a reference or pointer to the object.
Thus, the value of an object variable is a memory address, not an object. This is illustrated as shown in Figure 2-1.
32
Chapter 2 ■ Introduction to Objects
2575
author
title
price
pages
binding
2575 inStock
2599
b
As a shortcut, we can declare b and create a book object in one statement, like this:
It is a common error to think that the Book variable b can hold a Book object. It cannot; it can hold only a reference
to a Book object. (In a similar manner, we should be familiar with the idea that a String variable does not hold a
string but, rather, the address of where the string is stored.) However, where the distinction (between an object and a
reference to the object) does not matter, we will speak as if b holds a Book object.
Once an object b is created, we can refer to its instance fields like this:
However, we can do so from outside the class only if the fields are declared public. We will see later how to access
the fields indirectly when they are declared private.
When an object is created, unless we say otherwise, its instance fields are initialized as follows:
• Numeric fields are set to 0.
• Character fields are set to '\0' (Unicode '\u0000', to be precise).
• Boolean fields are set to false.
• Object fields are set to null. (A variable with the value null means that it does not reference or
point to anything.)
In our example, the following happens:
• b.author (of type String) is set to null; remember that String is an object type.
• b.title (of type String) is set to null.
• b.price (of type double) is set to 0.0.
• b.pages (of type int) is set to 0.
• b.binding (of type char) is set to '\0'.
• b.inStock (of type boolean) is set to false.
We could specify an initial value when we declare an instance variable. Consider this code:
33
Chapter 2 ■ Introduction to Objects
Now, when an object is created, author, binding, and inStock will be set to the specified values while title,
price, and pages will assume the default values. A variable is given a default value only if no explicit value is assigned
to it. Suppose we create an object b with this:
2.3 Constructors
Constructors provide more flexible ways of initializing the state of an object when it is created. In the following
statement, Book() is termed a constructor:
It is similar to a method call. But, you might say, we did not write any such method in our class definition. True,
but in such cases, Java provides a default constructor—one with no arguments (also called a no-arg constructor). The
default constructor is quite simplistic; it just sets the values of the instance variables to their default initial values.
Later, we could assign more meaningful values to the object’s fields, as in the following:
Now suppose that when we create a book object, we want Java to assign the author and title automatically.
We want to be able to use statements such as the following for creating new book objects:
34
Chapter 2 ■ Introduction to Objects
We can do this, but we must first write an appropriate constructor, one defined with two String parameters.
The following shows how it can be done:
The statement
35
Chapter 2 ■ Introduction to Objects
public Book() { }
36
Chapter 2 ■ Introduction to Objects
Observe that the body of the no-arg constructor consists of an empty block. When the following statement is executed,
the instance variables are set to their initial values (specified or default), and the constructor is executed. In this case,
nothing further happens.
Be warned that when we provide a constructor, the default no-arg constructor is no longer available. If we want to
use a no-arg constructor as well, we must write it explicitly, as in the previous example. We are free, of course, to write
whatever we want in the body, including nothing.
As a final example, we provide a constructor that lets us set all the fields explicitly when an object is created. Here
it is:
Part.NumParts = 25;
37
Chapter 2 ■ Introduction to Objects
This may not be desirable. Suppose NumParts is meant to count the number of objects created from Part. Any
outside class can set it to any value it pleases, so the writer of the class Part cannot guarantee that it will always reflect
the number of objects created.
An instance variable, as always, can be accessed via an object only. When a user class creates an object p of
type Part, it can use p.price (or p.name) to refer directly to the instance variable and can change it, if desired, with
a simple assignment statement. There is nothing to stop the user class from setting the variable to an unreasonable
value. For instance, suppose that all prices are in the range 0.00 to 99.99. A user class can contain the following
statement, compromising the integrity of the price data:
p.price = 199.99;
To solve these problems, we must make the data fields private; we say we must hide the data. We then provide
public methods for others to set and retrieve the values in the fields. Private data and public methods are the essence
of data encapsulation. Methods that set or change a field’s value are called mutator methods. Methods that retrieve
the value in a field are called accessor methods.
Let’s show how the two problems mentioned can be solved. First, we redefine the fields as private:
Now that they are private, no other class has access to them. If we want NumParts to reflect the number of
objects created from the class, we would need to increment it each time a constructor is called. We could, for example,
write a no-arg constructor as follows:
public Part() {
name = "NO PART";
price = -1.0; // we use –1 since 0 might be a valid price
NumParts++;
}
Whenever a user class executes a statement such as the following, a new Part object is created and 1 is added
to NumParts:
Hence, the value of NumParts will always be the number of Part objects created. Further, this is the only way to
change its value; the writer of the class Part can guarantee that the value of NumParts will always be the number of
objects created.
Of course, a user class may need to know the value of NumParts at any given time. Since it has no access to
NumParts, we must provide a public accessor method (GetNumParts, say; we use uppercase G for a static accessor, since
it provides a quick way to distinguish between static and non-static), which returns the value. Here is the method:
The method is declared static since it operates only on a static variable and does not need an object
to be invoked. It can be called with Part.GetNumParts(). If p is a Part object, Java allows you to call it with
p.GetNumParts(). However, this tends to imply that GetNumParts is an instance method (one that is called via an
38
Chapter 2 ■ Introduction to Objects
object and operates on instance variables), so it could be misleading. We recommend that class (static) methods be
called via the class name rather than via an object from the class.
As an exercise, add a field to the Book class to count the number of book objects created and update the
constructors to increment this field.
The constructor will dutifully set price to the invalid value 199.99. However, we can do more in a constructor
than merely assign values to variables. We can test a value and reject it, if necessary. We will take the view that if an
invalid price is supplied, the object will still be created but a message will be printed and the price will be set to –1.0.
Here is the new version of the constructor:
39
Chapter 2 ■ Introduction to Objects
725
name getName()
Think of the fields name and price as locked inside a box, and the only way the outside world can see them is via
the methods getName and getPrice.
p.setPrice(24.95);
40
Chapter 2 ■ Introduction to Objects
This sets the price of Part object p to 24.95. As before, the method will not allow an invalid price to be set. It will
validate the supplied price and print an appropriate message, if necessary. Using the constants declared in Section
2.4.1, here is setPrice:
725
name getName()
price getPrice()
725
p
setPrice()
Observe the direction of the arrow for setPrice; a value is being sent from the outside world to the private field
of the object.
Again, we emphasize the superiority of declaring a field private and providing mutator/accessor methods for it
as opposed to declaring the field public and letting a user class access it directly.
We could also provide methods to increase or decrease the price by a given amount or by a given percentage.
These are left as exercises.
As another exercise, write mutator methods for the price and inStock fields of the Book class.
p.printPart();
When printPart is called via af, the references in printPart to the fields name and price become references to
the fields of af. This is illustrated in Figure 2-4.
printPart()
The field names have to be qualified with the object variable p. Without p, we would have the case of a static
method referring to a non-static field, which is forbidden by Java.
If c is a Part object created in a user class, we will have to use the following to print its fields:
Part.printPart(c);
This is slightly more cumbersome than using the instance method, shown previously. By comparison, you can
use, for instance, Character.isDigit(ch) to access the static method isDigit in the standard Java class Character.
System.out.printf("%s", p);
42
Chapter 2 ■ Introduction to Objects
Since it is not clear what it means to print an arbitrary object, Java will look for guidance in the class itself.
Presumably, the class will know how to print its objects. If it provides a toString method, Java will use it. (If it
doesn’t, Java will print something generic like the name of the class and the address, in hexadecimal, of the object, for
instance: Part@72e15c32.) In our example, we could add the following to the class Part:
If af is the Air Filter part, then the following statement would invoke the call af.toString():
System.out.printf("%s", af);
System.out.printf("%s", af.toString());
43
Another Random Scribd Document
with Unrelated Content
the Emperor Alexander to his late Majesty, which cost
upwards of 1000 guineas, was knocked down at £125."
Proclamation of William IV. — The Beer Act — The Queen and gas — Burial of
George IV. — The King and the Duke of Cumberland — The King as a soldier
— He meddles with the uniforms of the army.
Chorus:
The King as "bon bourgeois" — Mobbed — Street song about him — A sailor in
Guildhall — Behaviour of the public at Windsor — Charles X. in England —
The "New Police" — A modest advertisement.
"'He says you drew a knife upon him,' said the alderman.
"'Your honour knows I can't spin a long yarn like this here
chap,' replied the old tar, 'but I never hurted man, woman, or
child in my life, barring 'twas a frog-eater; but I was a lad
then, and it was in the cause of old England; and d—e, I
don't think I'd hurt him neither, after a glass of grog or two.'
"'Only two hours ashore, your honour,' replied Will. 'I'd just
come from China, and got taking a glass with one messmate
and a glass with another.'
"Bunce. 'I did not mind the assault, but I thought it was
better to put him in a place of safety for his own sake.'
"'D—e, you're an honest fellow, after all,' exclaimed the tar,
seizing the officer's hand and squeezing it till the tears started
into Bunce's eyes. 'Come, and we'll make it right over a glass
of grog, old boy.'
"Will felt in his pockets, and could not find a copper. 'All
gone! all gone!' exclaimed the tar, mournfully.
"'It's all right—I've got his money safe,' said Bunce, drawing
forth an ample handful of silver and gold.
ebookgate.com