#### You've reached the end of your free preview.

Want to read all 322 pages?

**Unformatted text preview: **BOOKS FOR PROFESSIONALS BY PROFESSIONALS ® RELATED Advanced Topics in Java
Over the years, Java’s popularity has grown to the point where it plays an important
role in most of our lives. From laptops to data centers, game consoles to scientific
supercomputers, cell phones to the Internet, Java is everywhere! There are tons of
applications and heaps of websites that will not work unless you have Java installed,
and more are created every day. And, of course, Java is used to power what has
become the world’s most dominant mobile platform, Android.
Advanced Topics In Java teaches the algorithms and concepts that any budding
software developer should know. You’ll delve into topics such as sorting, searching,
merging, recursion, random numbers and simulation, among others. You will increase
the range of problems you can solve when you learn how to create and manipulate
versatile and popular data structures such as binary trees and hash tables.
This book assumes you have a working knowledge of basic programming
concepts such as variables, constants, assignment, selection (if..else) and looping
(while, for). It also assumes you are comfortable with writing functions and working
with arrays. If you study this book carefully and do the exercises conscientiously,
you would become a better and more agile software developer, more prepared to
code today’s applications - no matter the language.
What You’ll Learn:
• How to use some advanced algorithms, implemented in Java
• How to create, manipulate and use linked lists, stacks and queues
• How to use random numbers to program games and simulations
• How to work with files, binary trees and hash tables
• Sophisticated sorting methods such as heapsort, quicksort and mergesort
• How to implement all of the above in Java Shelve in
Programming Languages/Java ISBN 978-1-4302-6619-8
54999 User level:
Intermediate SOURCE CODE ONLINE 9 781430 266198 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
About the Author���������������������������������������������������������������������������������������������������������������xiii
About the Technical Reviewers������������������������������������������������������������������������������������������ xv
Preface����������������������������������������������������������������������������������������������������������������������������� xvii
■■Chapter 1: Sorting, Searching, and Merging���������������������������������������������������������������������1
■■Chapter 2: Introduction to Objects����������������������������������������������������������������������������������29
■■Chapter 3: Linked Lists����������������������������������������������������������������������������������������������������71
■■Chapter 4: Stacks and Queues���������������������������������������������������������������������������������������111
■■Chapter 5: Recursion�����������������������������������������������������������������������������������������������������143
■■Chapter 6: Random Numbers, Games, and Simulation��������������������������������������������������167
■■Chapter 7: Working with Files���������������������������������������������������������������������������������������189
■■Chapter 8: Introduction to Binary Trees������������������������������������������������������������������������219
■■Chapter 9: Advanced Sorting�����������������������������������������������������������������������������������������259
■■Chapter 10: Hashing������������������������������������������������������������������������������������������������������287
Index���������������������������������������������������������������������������������������������������������������������������������309 v Chapter 1 Sorting, Searching, and Merging
In this chapter, we will explain the following:
• How to sort a list of items using selection sort • How to sort a list of items using insertion sort • How to add a new item to a sorted list so that the list remains sorted • How to sort an array of strings • How to sort related (parallel) arrays • How to search a sorted list using binary search • How to search an array of strings • How to write a program to do a frequency count of words in a passage • How to merge two sorted lists to create one sorted list 1.1 Sorting an Array: Selection Sort
Sorting is the process by which a set of values are arranged in ascending or descending order. There are many reasons
to sort. Sometimes we sort in order to produce more readable output (for example, to produce an alphabetical listing).
A teacher may need to sort her students in order by name or by average score. If we have a large set of values and we
want to identify duplicates, we can do so by sorting; the repeated values will come together in the sorted list.
Another advantage of sorting is that some operations can be performed faster and more efficiently with sorted
data. For example, if data is sorted, it is possible to search it using binary search—this is much faster than using a
sequential search. Also, merging two separate lists of items can be done much faster than if the lists were unsorted.
There are many ways to sort. In this chapter, we will discuss two of the “simple” methods: selection and insertion
sort. In Chapter 9, we will look at more sophisticated ways to sort. We start with selection sort.
Consider the following list of numbers stored in a Java array, num: 1 Chapter 1 ■ Sorting, Searching, and Merging Sorting num in ascending order using selection sort proceeds as follows:
1st pass
• Find the smallest number in the entire list, from positions 0 to 6; the smallest is 15,
found in position 4. • Interchange the numbers in positions 0 and 4. This gives us the following: 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 2 • 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: 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:
public static void selectionSort(int list, int lo, int hi) {
//sort list[lo] to list[hi] in ascending order
for (int h = lo; h < hi; h++) {
int s = getSmallest(list, h, hi);
swap(list, h, s);
}
}
The two statements in the for loop could be replaced by the following:
swap(list, h, getSmallest(list, h, hi));
We can write getSmallest and swap as follows:
public static int getSmallest(int list, int lo, int hi) {
//return location of smallest from list[lo..hi]
int small = lo;
for (int h = lo + 1; h <= hi; h++)
if (list[h] < list[small]) small = h;
return small;
}
public static void swap(int list, int i, int j) {
//swap elements list[i] and list[j]
int hold = list[i];
list[i] = list[j];
list[j] = hold;
}
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
// selectionSort, getSmallest and swap go here
} //end class SelectSortTest
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:
Type up to 10 numbers followed by 0
57 48 79 65 15 33 52 0
The sorted numbers are
15 33 48 52 57 65 79
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 1.1.1 Analysis of Selection Sort
To find the smallest of k items, we make k-1 comparisons. On the first pass, we make n-1 comparisons to find the
smallest of n items. On the second pass, we make n-2 comparisons to find the smallest of n-1 items. And so on, until
the last pass where we make one comparison to find the smaller of two items. In general, on the jth pass, we make n-j
comparisons to find the smallest of n-j+1 items. Hence, we have this:
total number of comparisons = 1 + 2 + …+ n-1 = ½ n(n-1) » ½ n2
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. 1.2 Sorting an Array: Insertion Sort
Consider the same array as before: 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 The numbers have been sorted in ascending order.
The method described illustrates the idea behind insertion sort. The numbers in the array will be processed one
at a time, from left to right. This is equivalent to picking up the numbers from the table one at a time. Since the first
number, by itself, is sorted, we will process the numbers in the array starting from the second.
When we come to process num[h], we can assume that num[0] to num[h-1] are sorted. We insert num[h] among
num[0] to num[h-1] so that num[0] to num[h] are sorted. We then go on to process num[h+1]. When we do so, our
assumption that num[0] to num[h] are sorted will be true.
Sorting num in ascending order using insertion sort proceeds as follows:
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: The rest of the array remains unchanged.
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: The rest of the array remains unchanged.
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: The rest of the array remains unchanged.
4th pass
• 6 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: Chapter 1 ■ Sorting, Searching, and Merging The insertion of 15 in its correct position proceeds as follows:
• Compare 15 with 79; it is smaller, so move 79 to location 4, leaving location 3 free.
This gives the following: • Compare 15 with 65; it is smaller, so move 65 to location 3, leaving location 2 free.
This gives the following: • Compare 15 with 57; it is smaller, so move 57 to location 2, leaving location 1 free.
This gives the following: • Compare 15 with 48; it is smaller, so move 48 to location 1, leaving location 0 free.
This gives the following: • There are no more numbers to compare with 15, so it is inserted in location 0,
giving the following: • 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: The array is now completely sorted.
The following is an outline of how to sort the first n elements of an array, num, using insertion sort:
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.
public static void insertionSort(int list, int n) {
//sort list[0] to list[n-1] in ascending order
for (int h = 1; h < n; h++) {
int key = list[h];
int k = h - 1; //start comparing with previous item
while (k >= 0 && key < list[k]) {
list[k + 1] = list[k];
--k;
}
list[k + 1] = key;
} //end for
} //end insertionSort
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:
while (k >= 0 && key > list[k])
Now, a key moves to the left if it is bigger.
We write Program P1.2 to test whether insertionSort works correctly. Only main is shown. Adding the function
insertionSort completes the program.
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
public static void insertionSort(int list, int n) {
//sort list[0] to list[n-1] in ascending order
for (int h = 1; h < n; h++) {
int key = list[h];
int k = h - 1; //start comparing with previous item
while (k >= 0 && key < list[k]) {
list[k + 1] = list[k];
--k;
} 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:
Type up...

View
Full Document

- Fall '15
- Bubble Sort, Insertion Sort, Selection Sort, The Bible, Comparison sort