Merging 2 sorted arrays:
|
|
|
|
|
|
|
|
|
Both arrays are exhausted and the merge algorithm terminates !
We now write the merge( ) algorithm that merges 2 sorted arrays:
// merge(result, a, b): merge 2 sorted arrays a and b into array result
public static <T> void merge(T[] result, T[] a, T[] b)
{
int i = 0, j = 0, k = 0; // Indexes for arrays: a[i], b[j], result[k]
while ( i < a.length || j < b.length )
{
if ( i < a.length && j < b.length )
{ // Both array have elements
if ( a[i] < b[j] )
result[k++] = a[i++];
else
result[k++] = b[j++];
}
else if ( i == a.length ) // a is empty
result[k++] = b[j++];
else if ( j == b.length ) // b is empty
result[k++] = a[i++];
}
}
|
We parameterize the data type of the arrays... however...
We must limit the data type to a subclass of Comparable<T> because the objects must be comparable:
// merge(result, a, b): merge 2 sorted arrays a and b into array result
public static <T extends Comparable<T>> void merge(T[] result, T[] a, T[] b)
{
int i = 0, j = 0, k = 0; // Indexes for arrays: a[i], b[j], result[k]
while ( i < a.length || j < b.length )
{
if ( i < a.length && j < b.length )
{ // Both array have elements
if ( a[i] < b[j] )
result[k++] = a[i++];
else
result[k++] = b[j++];
}
else if ( i == a.length ) // a is empty
result[k++] = b[j++];
else if ( j == b.length ) // b is empty
result[k++] = a[i++];
}
}
|
We now proceed to write the merge algorithm.
We first define and initialize the indexes that points to the elements in the (3) arrays:
// merge(result, a, b): merge 2 sorted arrays a and b into array result
public static <T extends Comparable<T>> void merge(T[] result, T[] a, T[] b)
{
int i = 0, j = 0, k = 0; // Indexes for arrays: a[i], b[j], result[k]
while ( i < a.length || j < b.length )
{
if ( i < a.length && j < b.length )
{ // Both array have elements
if ( a[i] < b[j] )
result[k++] = a[i++];
else
result[k++] = b[j++];
}
else if ( i == a.length ) // a is empty
result[k++] = b[j++];
else if ( j == b.length ) // b is empty
result[k++] = a[i++];
}
}
|
We repeat as long as one of the array still has an unprocessed element:
// merge(result, a, b): merge 2 sorted arrays a and b into array result
public static <T extends Comparable<T>> void merge(T[] result, T[] a, T[] b)
{
int i = 0, j = 0, k = 0; // Indexes for arrays: a[i], b[j], result[k]
while ( i < a.length || j < b.length )
{
if ( i < a.length && j < b.length )
{ // Both array have elements
if ( a[i] < b[j] )
result[k++] = a[i++];
else
result[k++] = b[j++];
}
else if ( i == a.length ) // a is empty
result[k++] = b[j++];
else if ( j == b.length ) // b is empty
result[k++] = a[i++];
}
}
|
We must handle 3 cases:
// merge(result, a, b): merge 2 sorted arrays a and b into array result
public static <T extends Comparable<T>> void merge(T[] result, T[] a, T[] b)
{
int i = 0, j = 0, k = 0; // Indexes for arrays: a[i], b[j], result[k]
while ( i < a.length || j < b.length )
{
case 1: both a and b have unprocessed elements
case 2: array a is exhausted
case 3: array b is exhausted
}
}
|
Case 1: how to detect when both arrays have unprocessed elements:
// merge(result, a, b): merge 2 sorted arrays a and b into array result
public static <T extends Comparable<T>> void merge(T[] result, T[] a, T[] b)
{
int i = 0, j = 0, k = 0; // Indexes for arrays: a[i], b[j], result[k]
while ( i < a.length || j < b.length )
{
if ( i < a.length && j < b.length )
{ // Both arrays have unprocessed elements
if ( a[i] < b[j] )
result[k++] = a[i++];
else
result[k++] = b[j++];
}
else if ( i == a.length ) // a is empty
result[k++] = b[j++];
else if ( j == b.length ) // b is empty
result[k++] = a[i++];
}
}
|
Case 1: if a[i] < b[j], we copy a[i] over to result[k] (and increment i and k):
// merge(result, a, b): merge 2 sorted arrays a and b into array result
public static <T extends Comparable<T>> void merge(T[] result, T[] a, T[] b)
{
int i = 0, j = 0, k = 0; // Indexes for arrays: a[i], b[j], result[k]
while ( i < a.length || j < b.length )
{
if ( i < a.length && j < b.length )
{ // Both arrays have unprocessed elements
if ( a[i] < b[j] ) {
result[k] = a[i];
i = i + 1;
k = k + 1;
}
}
else if ( i == a.length ) // a is empty
result[k++] = b[j++];
else if ( j == b.length ) // b is empty
result[k++] = a[i++];
}
}
|
Shorthand: if we increase a variable by 1 after we used the variable, we can use var++ for short:
// merge(result, a, b): merge 2 sorted arrays a and b into array result
public static <T extends Comparable<T>> void merge(T[] result, T[] a, T[] b)
{
int i = 0, j = 0, k = 0; // Indexes for arrays: a[i], b[j], result[k]
while ( i < a.length || j < b.length )
{
if ( i < a.length && j < b.length )
{ // Both arrays have unprocessed elements
if ( a[i] < b[j] ) {
result[k] = a[i]; // Use i and k
i = i + 1; // After using i, increment i by 1
k = k + 1; // After using k, increment k by 1
}
}
else if ( i == a.length ) // a is empty
result[k++] = b[j++];
else if ( j == b.length ) // b is empty
result[k++] = a[i++];
}
}
|
Shorthand: if we increase a variable by 1 after we used the variable, we can use var++ for short:
// merge(result, a, b): merge 2 sorted arrays a and b into array result
public static <T extends Comparable<T>> void merge(T[] result, T[] a, T[] b)
{
int i = 0, j = 0, k = 0; // Indexes for arrays: a[i], b[j], result[k]
while ( i < a.length || j < b.length )
{
if ( i < a.length && j < b.length )
{ // Both arrays have unprocessed elements
if ( a[i] < b[j] )
result[k++] = a[i++];
else
result[k++] = b[j++];
}
else if ( i == a.length ) // a is empty
result[k++] = b[j++];
else if ( j == b.length ) // b is empty
result[k++] = a[i++];
}
}
|
Case 1: if a[i] ≥ b[j], we copy b[j] over to result[k] (and increment j and k):
// merge(result, a, b): merge 2 sorted arrays a and b into array result
public static <T extends Comparable<T>> void merge(T[] result, T[] a, T[] b)
{
int i = 0, j = 0, k = 0; // Indexes for arrays: a[i], b[j], result[k]
while ( i < a.length || j < b.length )
{
if ( i < a.length && j < b.length )
{ // Both arrays have unprocessed elements
if ( a[i] < b[j] )
result[k++] = a[i++];
else
result[k++] = b[j++];
}
else if ( i == a.length ) // a is empty
result[k++] = b[j++];
else if ( j == b.length ) // b is empty
result[k++] = a[i++];
}
}
|
Case 2: if array a is exhausted, we copy b[j] over to result[k] (and increment j and k):
// merge(result, a, b): merge 2 sorted arrays a and b into array result
public static <T extends Comparable<T>> void merge(T[] result, T[] a, T[] b)
{
int i = 0, j = 0, k = 0; // Indexes for arrays: a[i], b[j], result[k]
while ( i < a.length || j < b.length )
{
if ( i < a.length && j < b.length )
{ // Both arrays have unprocessed elements
if ( a[i] < b[j] )
result[k++] = a[i++];
else
result[k++] = b[j++];
}
else if ( i == a.length ) // a is exhausted (empty)
result[k++] = b[j++];
else if ( j == b.length ) // b is empty
result[k++] = a[i++];
}
}
|
Case 3: if array b is exhausted, we copy a[i] over to result[k] (and increment i and k):
// merge(result, a, b): merge 2 sorted arrays a and b into array result
public static <T extends Comparable<T>> void merge(T[] result, T[] a, T[] b)
{
int i = 0, j = 0, k = 0; // Indexes for arrays: a[i], b[j], result[k]
while ( i < a.length || j < b.length )
{
if ( i < a.length && j < b.length )
{ // Both arrays have unprocessed elements
if ( a[i] < b[j] )
result[k++] = a[i++];
else
result[k++] = b[j++];
}
else if ( i == a.length ) // a is exhausted (empty)
result[k++] = b[j++];
else if ( j == b.length ) // b is exhausted (empty)
result[k++] = a[i++];
}
}
|
DEMO: 14-sort/10-merge-sort/MergeSort.java --- see next slides for test programs
Test program that merges 2 arrays of (sorted) Integers:
public static void main(String[] args)
{
Integer[] list1 = {1, 3, 5, 7, 8}; // Sorted
Integer[] list2 = {2, 4, 8, 9}; // Sorted
Integer[] r = new double[list1.length + list2.length];
for(int i = 0; i < list1.length; i++)
System.out.print(list1[i] + " ");
System.out.println();
for(int i = 0; i < list2.length; i++)
System.out.print(list2[i] + " ");
System.out.println();
MergeSort.<Integer>merge(r, list1, list2);
for(int i = 0; i < r.length; i++)
System.out.print(r[i] + " ");
System.out.println();
}
|
DEMO: 14-sort/10-merge-sort/Demo.java + MergeSort.java
Test program that merges 2 arrays of (sorted) Strings:
public static void main(String[] args)
{
String[] list1 = {"abc", "klm", "pqr"};
String[] list2 = {"def", "ghi", "xyz"};
String[] r = new String[list1.length + list2.length];
for(int i = 0; i < list1.length; i++)
System.out.print(list1[i] + " ");
System.out.println();
for(int i = 0; i < list2.length; i++)
System.out.print(list2[i] + " ");
System.out.println();
MergeSort.<String>merge(r, list1, list2);
for(int i = 0; i < r.length; i++)
System.out.print(r[i] + " ");
System.out.println();
}
|
DEMO: 14-sort/10-merge-sort/Demo.java + MergeSort.java