I have been asked to implement quicksort (or mergesort) in an application,
and then remove any duplicates.
I have done just that, however, I have been further told that I should call
my sort method from within my remove duplicates method.
When my methods are called independently they work perfectly. However when
I call the sort method from within the remove duplicates method, the array
returned is not sorted correctly.
I am not allowed to use the Collections sort method, as that would defeat
the purpose of me implementing one of the sorting methods.
Here is my code (please keep the chuckles down ;-)
I have placed several superfluous System.out.println calls in the code for
help with [my] troubleshooting.
public class MyRemoveDup implements RemoveDup {
public int[] makeUnique(int[] AnArray) {
System.out.println("Step 1");
int i;
for (i =0;i<AnArray.length;i++){
System.out.println(i +" : "+AnArray[i]);
}
System.out.println("");
sort(AnArray);
for (i =0;i<AnArray.length;i++){
System.out.println(i +" : "+AnArray[i]);
}
System.out.println("\nmkUniq\n");
mkUniq(AnArray);
for (i =0;i<AnArray.length;i++){
System.out.println(i +" : "+AnArray[i]);
}
return AnArray;
}
public int[] mkUniq(int[] AnArray){
for (int i =0;i<AnArray.length;i++){
System.out.println(i +" : "+AnArray[i]);
}
int cloneCount = 1;
//Create another array, to copy the unique elements from the sorted to.
int [] myArray = new int[AnArray.length];
//Obviously the first element will be unique :-)
myArray[0]=AnArray[0];
for (int i = 1;i < AnArray.length;i++){
if (AnArray[i] != AnArray[i-1])
{
myArray[cloneCount] = AnArray[i];
cloneCount++;
}
}
int [] Clone = new int[AnArray.length -(AnArray.length-cloneCount)];
System.arraycopy(myArray, 0, Clone, 0, Clone.length);
return Clone;
}
public static int[] swapper(int []myArray, int x, int y){
//System.out.println("Start x: " + myArray[x] + " and y:" + myArray[y]);
int holder =0;
holder = myArray[x];
myArray[x] = myArray[y];
myArray[y] = holder;
//System.out.println("Finish x: " + myArray[x] + " and y:" + myArray[y]);
return myArray;
}
public static void quickSort(int []arr, int low, int high){
//set the pivot to the middle element
int middle = (low + high )/2;
if (low + 3 >= high){
// sort the low, high, and middle elements
if ( arr[middle]<(arr[low]))
arr = swapper(arr, middle, low);
if ( arr[high]<(arr[low]))
arr = swapper(arr, high, low);
if ( arr[high]<(arr[middle]))
arr = swapper(arr, high, middle);
}else{
//sort the low, high, and middle elements
if ( arr[middle]<(arr[low]))
arr = swapper(arr, middle, low);
if ( arr[high]<(arr[low]))
arr = swapper(arr, high, low);
if ( arr[high]<(arr[middle]))
arr = swapper(arr, high, middle);
//Place pivot at position 'high' -1
arr = swapper(arr, middle, high -1);
int pivot = middle;
//Sort the elements relative to the pivot
int i,j;
for (i = low, j = high -1; ;)
{
while(arr[++i]<pivot)
;
while(pivot < (arr[--j]))
;
if (i<j)
arr = swapper(arr, i, j);
else
break;
}
//Restore pivot
arr = swapper(arr, i, high -1);
quickSort(arr, low, i-1);
quickSort(arr, i+1, high);
}
}
public void sort(int[] AnArray) {
System.out.println("Sort");
quickSort(AnArray, 0, AnArray.length -1);
}
}

Signature
Q: What do you get when you cross a mosquito with a rock climber?
A: Nothing. You can't cross a vector and a scalar.
Patricia Shanahan - 21 Apr 2007 21:35 GMT
> I have been asked to implement quicksort (or mergesort) in an application,
> and then remove any duplicates.
[quoted text clipped - 3 lines]
> I call the sort method from within the remove duplicates method, the array
> returned is not sorted correctly.
...
I assume you are looking for advice on what to do next, when your
program does not do exactly what you want, and it is not obvious to you why.
I've written a description of one approach to debug, see
http://home.earthlink.net/~patricia_shanahan/debug/
Patricia
Shane - 21 Apr 2007 21:46 GMT
>> I have been asked to implement quicksort (or mergesort) in an
>> application, and then remove any duplicates.
[quoted text clipped - 13 lines]
>
> Patricia
Hi
In a way no. I do not understand why a module that works as desired
when "freestanding" is not behaving the same way when called from another
module.
This is the output of the code I have already presented, when called with
the following array:
int[] testArray = new int[10];
testArray[0] = 5;
testArray[1] = 9;
testArray[2] = 5;
testArray[3] = 2;
testArray[4] = 1;
testArray[5] = 12;
testArray[6] = 5;
testArray[7] = 28;
testArray[8] = 3;
testArray[9] = 4;
Output:
Sort
Step 1
0 : 1
1 : 2
2 : 3
3 : 4
4 : 5
5 : 5
6 : 5
7 : 9
8 : 12
9 : 28
0 : 1
1 : 2
2 : 3
3 : 5
4 : 4
5 : 5
6 : 5
7 : 12
8 : 9
9 : 28
mkUniq
0 : 1
1 : 2
2 : 3
3 : 5
4 : 4
5 : 5
6 : 5
7 : 12
8 : 9
9 : 28
0 : 1
1 : 2
2 : 3
3 : 5
4 : 4
5 : 5
6 : 5
7 : 12
8 : 9
9 : 28
As can be seen when the sort method is called on the unsorted array, it
returns a sorted array. When the sort method is called on what is then a
sorted array, it returns an unsorted array. My removal of duplicates
relies on the array being sorted.

Signature
Q: Why do you never hear the number 288 on television?
A: It's two gross.
Patricia Shanahan - 21 Apr 2007 22:15 GMT
>>> I have been asked to implement quicksort (or mergesort) in an
>>> application, and then remove any duplicates.
[quoted text clipped - 18 lines]
> when "freestanding" is not behaving the same way when called from another
> module.
...
In that situation, I would have two alternative theories:
1. A bug in the sort method that makes it fail for some inputs, but not
others.
2. A bug in how the sort method is being called when it is not
"freestanding".
You could find out which is true by replacing, just for debug purposes,
your sort with Arrays.sort. If it works with Arrays.sort, the problem is
in your sort code. If it does not work with Arrays.sort, the problem is
in how it is being called when it fails.
Patricia
Shane - 22 Apr 2007 05:07 GMT
>>>> I have been asked to implement quicksort (or mergesort) in an
>>>> application, and then remove any duplicates.
[quoted text clipped - 24 lines]
> 1. A bug in the sort method that makes it fail for some inputs, but not
> others.
I think this is my best place to start looking, specifically at input arrays
which are already sorted.
> 2. A bug in how the sort method is being called when it is not
> "freestanding".
This is what I was concerned about. I believe that when I call sort(int[]
AnArray) I am calling a 'driver' for quickSort(int []arr, int low, int
high)
I tried calling quickSort(int []arr, int low, int high) instead, but got the
same result.
> You could find out which is true by replacing, just for debug purposes,
> your sort with Arrays.sort. If it works with Arrays.sort, the problem is
> in your sort code. If it does not work with Arrays.sort, the problem is
> in how it is being called when it fails.
>
> Patricia
Z. - 22 Apr 2007 00:34 GMT
> I have been asked to implement quicksort (or mergesort) in an application,
> and then remove any duplicates.
Why reinvent sorting?
Why not just use Arrays.sort() ?
Patricia Shanahan - 22 Apr 2007 00:38 GMT
>> I have been asked to implement quicksort (or mergesort) in an
>> application,
[quoted text clipped - 3 lines]
>
> Why not just use Arrays.sort() ?
Shane explained later in the article "I am not allowed to use the
Collections sort method, as that would defeat the purpose of me
implementing one of the sorting methods.".
Patricia
Z. - 23 Apr 2007 23:17 GMT
>>> I have been asked to implement quicksort (or mergesort) in an
>>> application,
>>> and then remove any duplicates.
>> Why reinvent sorting?
>> Why not just use Arrays.sort() ?
> Shane explained later in the article "I am not allowed to use the
> Collections sort method, as that would defeat the purpose of me
> implementing one of the sorting methods.".
Oh, duh! How did I miss that?! (embarrassed look)
Shane - 23 Apr 2007 22:04 GMT
> //Place pivot at position 'high' -1
> arr = swapper(arr, middle, high -1);
[quoted text clipped - 8 lines]
> while(pivot < (arr[--j]))
> ;
I am doing two things wrong here. I am comparing arr[i] to pivot (pivot is
an index, not a value held at the index)
And pivot is pointing at the middle of the array, when it should be pointing
at the high-1 position (the value held at middle is moved to 'high -1' in
order to get it out of the way)