Counting the comparisons and swaps in a quick sort - java

I am running a quick sort on 2000 integers read from a file but the number of comparisons and swaps i am getting seem high. Are my counters in the right place? or is something wrong with the sort?
public int partition(int array[], int low, int high)
{
int pivot = array[high];
int i = (low-1);
for (int j = low; j < high; j++)
{
compCounter++;
if (array[j] <= pivot)
{
i++;
int temp = array[i];
array[i] = array[j];
array[j] = temp;
SwapCounter++;
}
}
int temp = array[i+1];
array[i+1] = array[high];
array[high] = temp;
SwapCounter++;
return i+1;
}
public void quickSort(int array[], int low, int high)
{
if (low < high)
{
int pivotPoint = partition(array, low, high);
quickSort(array, low, pivotPoint-1);
quickSort(array, pivotPoint+1, high);
}
}

Your counters are correct.
Just a quick suggestion - move the swap code in a separate function swap(array, fromIndex, toIndex)

Related

What is wrong with this code when i sort only a portion of an array not starting from index 0?

When I use mergeSort to sort a portion of an array it gives ArrayIndexOutOfBoundsException but if I merge a portion starting from the index 0 to any other index it works why?
public static void mergeSort(int[] arr, int[] temp, int low, int high) {
if (low < high) {
int mid = low + (high - low) / 2;
mergeSort(arr, temp, low, mid);
mergeSort(arr, temp, mid + 1, high);
merge(arr, temp, low, mid, high);
}
}
public static void merge(int[] arr, int[] temp, int low, int mid, int high) {
for (int i = low; i <= high; i++) {
temp[i] = arr[i];
}
int i = low;
int j = mid + 1;
int k = low;
while (i <= mid && j <= high) {
if (temp[i] <= temp[j]) {
arr[k] = temp[i];
i++;
} else {
arr[k] = temp[j];
j++;
}
k++;
}
while (i <= mid) {
arr[k] = temp[i];
i++;
k++;
}
}
I get an error ArrayIndexOutOfBoundsException.
The argument high in your code is the index of the last element in the slice to be sorted or merged. Are you sure you pass array.length - 1 as the second argument to the topmost call to mergeSort()?
Also make sure you allocate the temp array with the same length as the array to be sorted.
This convention is confusing and does not allow sorting empty arrays. You might instead use a more consistent convention where high is the index of the element after the last one and you pass array.length to the topmost call.
Here is a modified version:
public static void mergeSort(int[] arr, int[] temp, int low, int high) {
if (high - low > 1) {
int mid = low + (high - low) / 2;
mergeSort(arr, temp, low, mid);
mergeSort(arr, temp, mid, high);
merge(arr, temp, low, mid, high);
}
}
public static void merge(int[] arr, int[] temp, int low, int mid, int high) {
for (int i = low; i < high; i++) {
temp[i] = arr[i];
}
int i = low;
int j = mid;
int k = low;
while (i < mid && j < high) {
if (temp[i] <= temp[j]) {
arr[k++] = temp[i++];
} else {
arr[k++] = temp[j++];
}
}
while (i < mid) {
arr[k++] = temp[i++];
}
}

Find the medium of an array by modifying quick sort that also has an average O(n) time complexity

Please help me. I need to modify quicksort with an average of O(n) time complexity that just sorts half of the array as I'm just trying to find the medium of the array.
Heres my quicksort algorithm before any changes:
static void swap(int[] arr, int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
static int partition(int[] arr, int low, int high){
int pivot = arr[high];
int i = (low - 1);
for(int j = low; j <= high - 1; j++){
if (arr[j] < pivot) {
i++;
swap(arr, i, j);
}
}
swap(arr, i + 1, high);
return (i + 1);
}
static void quickSort(int[] arr, int low, int high){
if (low < high) {
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}

trying to implement Quicksort Algorithm

Just started learning algorithms: trying to implement the quicksort algorithm with Java. But it's not showing anything in the output tried many times but unable to find the reason.
It is not showing anything.
public class Try {
public static void main(String[] args) {
int []arr= {22,9,8,45,28,7,1};
int len = arr.length;
quicksort(arr, 0, len-1);
for(int i = 0; i<len; i++)
System.out.print(arr[i]+" ");
}
static void quicksort(int [] arr, int low, int high) {
if (low < high) {
int index = partition(arr, low, high);
quicksort(arr, low, index -1);
quicksort(arr, index+1, high);
}
}
static int partition(int [] arr, int low, int high) {
int pivot = arr[low];
int i = low;
int j = high;
while(i<=j) {
while(arr[i]<pivot) i++;
while(arr[j]>pivot) j--;
if(i<=j) {
// swapping i with j
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
//swapping pivot(low) with j when i<j
int temp = arr[low];
arr[low] = arr[j];
arr[j] = temp;
}
return j;
}
}
Your problem comes from the partition method. You keep getting stuck in the second while loop. You should do it with a single loop, here's an exemple ( I personally prefer using a for loop ) :
int pivot = arr[high];
int i = (low - 1); // Index of smaller element and indicates the
// right position of pivot found so far
for (int j = low; j <= high- 1; j++)
{
// If current element is smaller than the pivot
if (arr[j] < pivot)
{
i++; // increment index of smaller element
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
int temp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = temp;
return (i + 1);

How do I fix my quicksort algorithm for larger values of n ? ( and when the array is not random)

My quicksort algorithm fails for larger values of n, and only if the array is not random. I've tried using the algorithm on various arrays. It works fine when I use a random array of numbers (for any value of n), but for an array that contains the same values or values in ascending order or descending order, It fails. And that too only when n is approximately abov 6000. ( It works perfectly when n is <5000)
I've already tried using a different version of quicksort. One that uses a while loop instead of recursion, and it works perfectly. And like I've said already my algorithm fails only when n is greater than 6000 for a nonrandomized array, for 5000 or below it works well.
void quicksort(int a[], int low, int high) {
if (low < high) {
int index = partition(a, low, high); // error
quicksort(a, low, index - 1); // error
quicksort(a, index + 1, high);
}
}
int partition(int arr[], int low, int high) {
int pivot = arr[high];
int i = low - 1;
//int j = low;
for (int j = low; j < high; j++) {
// If current element is smaller than or
// equal to pivot
if (arr[j] <= pivot) {
i++;
// swap arr[i] and arr[j]
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
int temp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = temp;
return (i + 1);
}
Above I have my quicksort algorithm. The one that fails for n>6000( and when the array is not random).
And below is the code that worked for all values of n and on any type of array.
public void quicksort(int[] data, int low, int high)
{ // 1 or 0 items are sorted by default
if(high - low < 1)
return;
int left = low;
int right = high;
int pivot = data[low + (high - low) / 2];
while(left <= right)
{ // Increment left pointer until left >= pivot
while(data[left] < pivot)
left++;
// Increment right pointer until right <= pivot
while(data[right] > pivot)
right--;
// If left < right; swap values
if(left <= right)
{ int temp = data[left];
data[left] = data[right];
data[right] = temp;
left++;
right--;
}
}
// quick_sort 'lesser values'
quicksort(data, low, right);
// quick_sort 'greater values'
quicksort(data, left, high);
}
static int partition(int[] array, int low, int high) {
int j, temp, i = low + 1;
Random random = new Random();
int x = random.nextInt(high - low) + low;
temp = array[low];
array[low] = array[x];
array[x] = temp;
for (j = low + 1; j <= high; j++) {
if (array[j] <= array[low] && j != i) {
temp = array[j];
array[j] = array[i];
array[i++] = temp;
} else if (array[j] <= array[low]) {
i++;
}
}
temp = array[i - 1];
array[i - 1] = array[low];
array[low] = temp;
return i - 1;
}
The terminal shows an error in two lines specifically. (The lines that I have marked as an error in the first quicksort method).
If the data is already in order, then using arr[high] (or arr[low]) results in worst case stack space overhead of O(n), which overflows the stack. The second example, uses the middle element (arr[low + (high-low)/2]), which will have best case stack space overhead for data already sorted or data already reverse sorted.
A workaround to limit stack space overhead to O(log(n)), is after doing partition, check to see which part is smaller, and only use recursion on the smaller part, then loop back to handle the larger part (update low or high as needed to exclude the now sorted smaller part before looping back).
public static void quicksort(int[] arr, int low, int high)
{
while (low < high) {
int index = partition(arr, low, high);
if((index-low) <= (high-index)){ // avoid stack overflow
quicksort(arr, low, index - 1); //
low = index+1; //
}else{ //
quicksort(arr, index + 1, high); //
high = index-1; //
} //
}
}
public static int partition(int[] arr, int low, int high)
{
int pivot = arr[high];
int i = low - 1;
for (int j = low; j < high; j++) {
if (arr[j] <= pivot) {
i++;
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
int tmp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = tmp;
return (i + 1);
}
If interested, Hoare partition scheme is faster:
public static void qsort(int[] a, int lo, int hi)
{
while(lo < hi){
int md = lo+(hi-lo)/2;
int ll = lo-1;
int hh = hi+1;
int p = a[md];
int t;
while(true){
while(a[++ll] < p);
while(a[--hh] > p);
if(ll >= hh)
break;
t = a[ll];
a[ll] = a[hh];
a[hh] = t;
}
ll = hh++;
if((ll - lo) <= (hi - hh)){
qsort(a, lo, ll);
lo = hh;
} else {
qsort(a, hh, hi);
hi = ll;
}
}
}

Counting comparisons and swaps in a quick sort

I'm running a quick sort on 2000 integers read from a file and count the comparisons and swaps but I'm not sure if my counters are in the right place as my numbers seem off, or is something wrong with the sort?
public int partition(int array[], int low, int high)
{
int pivot = array[low];
while(low < high)
{
while(pivot < array[high] && low < high)
{
high = high - 1;
compCounter++;
}
if(high != low)
{
array[low] = array[high];
SwapCounter++;
low++;
}
while(array[low] < pivot && low < high)
{
low = low +1;
compCounter++;
}
if(high != low)
{
array[high] = array[low];
SwapCounter++;
high--;
}
}
SwapCounter++;
int temp = array[high];
array[high] = pivot;
return high;
}
public void quickSort(int array[], int low, int high)
{
if (low < high)
{
int pivotPoint = partition(array, low, high);
quickSort(array, low, pivotPoint-1);
quickSort(array, pivotPoint+1, high);
}
}
I check your code but I think you do some more works (and maybe produce invalid result in some special case). I change your code in some how which is true and you can find it with some search and place counter in correct place.
private static int CompCounter, SwapCounter;
public static void main(String[] args) {
int[] a = {3, 2, 1, 5, 6, 7 , 4, -1};
quickSort(a, 0, a.length - 1);
System.out.println(Arrays.toString(a));
}
public static int partition(int array[], int low, int high) {
int pivot = array[high];
int lowBound = low;
for (int i = low; i < high; i++)
{
CompCounter++;
if (array[i] < pivot) {
int temp = array[lowBound];
array[lowBound] = array[i];
array[i] = temp;
lowBound++;
SwapCounter++;
}
}
SwapCounter++;
array[high] = array[lowBound];
array[lowBound] = pivot;
return lowBound;
}
public static void quickSort(int array[], int low, int high) {
if (low < high)
{
int pivotPoint = partition(array, low, high);
quickSort(array, low, pivotPoint - 1);
quickSort(array, pivotPoint + 1, high);
}
}
If you want, you can use another way to partition for sort (another algorithm):
public static int partitionSecondWay(int array[], int low, int high) {
int pivot = array[low];
int i = low - 1;
int j = high + 1;
while (true)
{
do
{
i++;
CompCounter++;
} while (array[i] < pivot);
do
{
j--;
CompCounter++;
} while (array[j] > pivot);
if (i >= j)
{
CompCounter++;
return j; // notice if you use this way, then in quicksort you
// must use quicksort(array, low, partition) and
// quicksort(array, partition + 1, high)
}
int temp = array[i];
array[i] = array[j];
array[j] = temp;
SwapCounter++;
}
}
I hope these helps you. If something is wrong, comment it.

Categories

Resources