1

I am trying to implement the quicksort algorithm in Java:

// Sort parallel arrays with quick sort

import java.util.Scanner;
import java.text.DecimalFormat;

class FunRunQuiSort {
    static int iSize = 5; // Set value
    static double[] daFinishTime = new double[iSize];
    static String[] saRunnerName = new String[iSize];

static void getInput() {
    System.out.println("\n***** 5K RUNNERS *****");
    for(int i = 0; i < saRunnerName.length; i++) {
        Scanner input = new Scanner(System.in);

        System.out.print("Enter runner name: ");
        saRunnerName[i] = input.nextLine();

        System.out.print("Enter finish time: ");
        daFinishTime[i] = input.nextDouble();

        System.out.print("\r\n");
    }
}

static void doQuickSort(double[] daFinishTime) {
    int i = daFinishTime[0], j = daFinishTime.length - 1;
    double dTemp;
    String sTemp;
    // Pivot
    double dPivot = daFinishTime[(daFinishTime[0] + daFinishTime.length - 1) / 2];
    // Partition
    do {    
        while(daFinishTime[i] < dPivot) {
            i++;
        } 
        while(daFinishTime[j] > dPivot) {
            j--;
        }
        if(i <= j) {
            dTemp = daFinishTime[i];
            daFinishTime[i] = daFinishTime[j];
            daFinishTime[j] = dTemp;

            sTemp = saRunnerName[i];
            saRunnerName[i] = saRunnerName[j];
            saRunnerName[j] = sTemp;

            i++;
            j--;
        }
    } while(i <= j);
    // Recursion
    if(daFinishTime[0] < j) {
        doQuickSort(daFinishTime, daFinishTime[0], j);
    }
    if(i < daFinishTime.length - 1) {
        doQuickSort(daFinishTime, i, daFinishTime.length - 1);
    }
}

static void printOutput() {
    DecimalFormat df = new DecimalFormat("##.00");

    System.out.println("***** SORTED RUNTIMES *****");
    for(int i = 0; i < daFinishTime.length; i++) {
        System.out.println("[" + (i + 1) + "] " +
            df.format(daFinishTime[i]) + " mins. by " +
            saRunnerName[i]);
    }

    System.out.println("\n***** TOP 3 RUNTIMES *****");
    for(int i = 0; i < 3; i++) {
        System.out.println("#" + (i + 1) + " Place: " +
            df.format(daFinishTime[i]) + " mins. by " +
            saRunnerName[i]);
    }
}

public static void main(String[] args) {
    getInput();
    doQuickSort(daFinishTime);
    printOutput();
   }
}

It is returning loss of precision errors, but when I change the data type of the said line, it returns more loss of precision errors.

Can someone fix the code? I just need to see the quicksort in action.

4
  • 1
    Your code doesn't compile Commented Jul 19, 2013 at 6:24
  • 2
    Your method implementaion of doQuickSort accepts only one parameter and while calling you are pasiing three parameters, how can this be possible? Your code has many errors like this, do you want us to write QuickSort from scratch? Commented Jul 19, 2013 at 6:28
  • @Jaguar If it is not too much, would it be okay? Commented Jul 19, 2013 at 9:20
  • @Jaguar Now that I have seen the fixed code, I better understood what you were trying to say. From the quicksort snippet I got, I was assigning the first and last elements inside the doQuickSort method, which is evident in the erroneous code I posted (see all my replacements/assignments). I should have passed the arguments when I called doQuickSort in the main method, which Tobias showed. Sorry, I learn after I see my mistake haha. Commented Jul 20, 2013 at 1:54

4 Answers 4

2
double dPivot = daFinishTime[(daFinishTime[0] + daFinishTime.length - 1) / 2];

How you are selecting pivot element is confusing. if you want mid element as pivot, it should be

double dPivot = daFinishTime[(i+j)/2];

Update this method in @Tobias solution

 static void doQuickSort(double[] daFinishTime, int i, int j) {
        double dTemp;
        String sTemp;

        int start = i;
        int end = j;
        // Pivot
        double dPivot = daFinishTime[(i + j) / 2];

        // Partition
        while (start <= end) {
            while (daFinishTime[start] < dPivot) {
                start++;
            }
            while (daFinishTime[end] > dPivot) {
                end--;
            }
            if (start <= end) {
                dTemp = daFinishTime[start];
                daFinishTime[start] = daFinishTime[end];
                daFinishTime[end] = dTemp;

                sTemp = saRunnerName[start];
                saRunnerName[start] = saRunnerName[end];
                saRunnerName[end] = sTemp;

                start++;
                end--;
            }
        }

        // Recursion
        if (start < j) {
            doQuickSort(daFinishTime, start, j);
        }
        if (i < end) {
            doQuickSort(daFinishTime, i, end);
        }
    }
Sign up to request clarification or add additional context in comments.

4 Comments

Shouldn't it be daFinishTime[daFinishTime.length / 2]? You can't index based on values in the array.
nope. it's always mid of your partition. [if you are using recursion]. if i and j represent the start and end index of partition, the above one works correct
@Reddy If you check the code of Tobias below, it compiles. However it does not sort. What could be the problem with it?
@Reddy Thank you very much, it sorts now.
1

You had answers of how to change your quick-sort so I thought I'd introduce a few other suggestions and a slightly different approach. I'm not sure what your requirements for having two separate arrays are but it seems to me like bad practice maintaining the two - using their positions as identifiers. In my opinion, you need a Runner object, which perhaps contains some of their details (if needed). For my example, I've just created a 'RunnerTime' object which contains the two fields Name(String) and Time(Double).

I'v then populated an Array or RunnerTime objects to send into my quickSort method. Here is how it works.

I've tested this out locally adding 4 runners:

RunnerTime rt1 = new RunnerTime("Bob", 10.13);
RunnerTime rt3 = new RunnerTime("Craig", 11.65);
RunnerTime rt2 = new RunnerTime("Dave", 11.45);
RunnerTime rt4 = new RunnerTime("Marley", 5.62);

I've then added them to an array and sent them to the following method:

private static RunnerTime[] doSort(RunnerTime[] runnerTimes) {
        RunnerTime currentRunnerTime;
        RunnerTime nextRunnerTime;
        boolean swapped;

        do {
            swapped = false;
            for (int x = 0; x < runnerTimes.length - 1; x++) {
                currentRunnerTime = runnerTimes[x];
                nextRunnerTime = runnerTimes[x + 1];
                if (currentRunnerTime.time > nextRunnerTime.time) {
                    runnerTimes[x] = nextRunnerTime;
                    runnerTimes[x + 1] = currentRunnerTime;
                    swopped = true;
                }
            }
        } while (swapped);
        return runnerTimes;
    }

After doing this they sorted to:

Runner Name: Marley  Runner Time: 5.62
Runner Name: Bob     Runner Time: 10.13
Runner Name: Dave    Runner Time: 11.45
Runner Name: Craig   Runner Time: 11.65

The advantages of doing it this way are as follows:

  • Your name and time are united, so there's no chance of a time being mistakenly assigned so another runner.
  • Your sort method can be much shorter as you only need to swap one array.
  • The 'swapped' boolean means that your array is only looped through as many times as it needs to. Once there's has been a cycle that has not made any swaps (meaning that everyone is in order) - the loop will exit.

3 Comments

We are only taught until arrays as of now so I would not be going beyond the requirements for the meantime. The professor wants to see arrays and the quicksort algorithm. The quicksort algorithm is the only thing that's left to be fixed. Would you kindly assist with that?
I agree with Scott here, you should still look into doing it his way as it'll be easier later and will help you get used to using objects
@Malkin Indeed, I will look into it, I believe it is going to be our next lesson soon. I just do not want the professor thinking where I got the idea when he has not taught it yet haha. But I know Scott's approach is the essence of OOP. Thanks guys for your help.
0

If Possible Refer to Implementing quicksort algorithm . Moreover why are you complicating with ints and doubles in the program.As the comments on your code state correctly your program doesnt compile because of that.

1 Comment

The array to be sorted is double. The index is int.
0

I've made some changes in the doQuickSort-method. Now its compiling, and it seems to work.

// Sort parallel arrays with quick sort

import java.text.DecimalFormat;
import java.util.Scanner;

class FunRunQuiSort {
static int iSize = 5; // Set value
static double[] daFinishTime = new double[iSize];
static String[] saRunnerName = new String[iSize];

static void getInput() {
    System.out.println("\n***** 5K RUNNERS *****");
    for(int i = 0; i < saRunnerName.length; i++) {
        Scanner input = new Scanner(System.in);

        System.out.print("Enter runner name: ");
        saRunnerName[i] = input.nextLine();

        System.out.print("Enter finish time: ");
        daFinishTime[i] = input.nextDouble();

        System.out.print("\r\n");
    }
}

static void doQuickSort(double[] daFinishTime, int i, int j) {
    double dTemp;
    String sTemp;

    // Pivot
    double dPivot = daFinishTime[(i + j) / 2];

    // Partition
    while(i <= j) {
        while(daFinishTime[i] < dPivot) {
            i++;
        } 
        while(daFinishTime[j] > dPivot) {
            j--;
        }
        if(i <= j) {
            dTemp = daFinishTime[i];
            daFinishTime[i] = daFinishTime[j];
            daFinishTime[j] = dTemp;

            sTemp = saRunnerName[i];
            saRunnerName[i] = saRunnerName[j];
            saRunnerName[j] = sTemp;

            i++;
            j--;
        }
    }

    // Recursion
    if(i < i - 1) {
        doQuickSort(daFinishTime, i, i - 1);
    }
    if(i < j) {
        doQuickSort(daFinishTime, i, j);
    }
}

static void printOutput() {
    DecimalFormat df = new DecimalFormat("##.00");

    System.out.println("***** SORTED RUNTIMES *****");
    for(int i = 0; i < daFinishTime.length; i++) {
        System.out.println("[" + (i + 1) + "] " +
                df.format(daFinishTime[i]) + " mins. by " +
                saRunnerName[i]);
    }

    System.out.println("\n***** TOP 3 RUNTIMES *****");
    for(int i = 0; i < 3; i++) {
        System.out.println("#" + (i + 1) + " Place: " +
                df.format(daFinishTime[i]) + " mins. by " +
                saRunnerName[i]);
    }
}

public static void main(String[] args) {
        getInput();
        doQuickSort(daFinishTime, 0, daFinishTime.length - 1);
        printOutput();
    }
}

1 Comment

This compiles but it does not sort. Sorry, I overlooked it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.