2
\$\begingroup\$

Hint: This question is a follow-up to my Code Review question from 09.01.2017: Class sort with BubbleSort algorithm

After been showed Mergesort and QuickSort as pseudo-code this week in lecture I had to re-implement my class Sort (which formerly used the BubbleSort algorithm). So that it now uses QuickSort as the sorting algorithm.

Here's my code. I have used the pseudo from the (German Wikipedia article) as an orientation. I have added comments with the detailed requirements for the mandatory methods.

package algorithm;

/*
    Task description:
    -----------------
    Implement the QuickSort algorithm within the 
    Java class "algorithm.Sort".
    Submit your solution to the JUnit system for
    automatic evaluation.
*/

public class Sort
{
    // Validate leftIndex and rightIndex concerning being within the
    //  array range.   
    public static void quickSort(int[] list, int leftIdx, int rightIdx)
    {
        if (leftIdx > list.length) 
        {
            throw new IllegalArgumentException("Left index invalid.");
        }

    if (rightIdx < 0 || rightIdx > list.length) 
    {
        throw new IllegalArgumentException("Right index invalid.");
    }

    if (leftIdx < rightIdx) 
    {
        int index = divide(list, leftIdx, rightIdx);

        quickSort(list, leftIdx, index - 1);          
        quickSort(list, index + 1, rightIdx);
    }
}

public static void quickSort(int[] list)
{
    Sort.quickSort(list, 0, list.length - 1);
}

// Choose the last element as the pivot-element.
// Left of the pivot-element have all elements to be smaller then the 
//   pivot-element. Right of the pivot-element have all elements to be
//   equal or greater then the pivot-element.
// Return the position of the pivot-element within the list.
public static int divide(int [] list, int leftIdx, int rightIdx)
{
    if (leftIdx < 0 || leftIdx > list.length - 1 
            || rightIdx < 0 || rightIdx > list.length - 1) 
    {
        throw new IllegalArgumentException("Left or right index invalid.");
    }

    int pivotItem = list[rightIdx];
    int i = leftIdx;
    int j = rightIdx - 1;

    do 
    {
        while (list[i] < pivotItem && i < rightIdx)
        {
            i++;
        }

        while (list[j] >= pivotItem && j > leftIdx) 
        {
            j--;
        }
        // As long as leftIdx have not overstep rightIdx ...
        if (i < j) 
        {
            int tmp = list[i];

            list[i] = list[j];
            list[j] = tmp;
        } 
    } while (i < j);

    if (list[i] > pivotItem) 
    {
        int tmp = list[i];
        list[i] = pivotItem;
        list[rightIdx] = tmp;
    }

    return i;
}

// Convert the array to a appropriate String representation!
// Parameter validity checks required.
public static String toString(int[] list, int start, int end)
{
    if (start < 0 || start > list.length - 1 
            || end < 0 || end > list.length - 1
            || start > end) 
    {
        throw new IllegalArgumentException("Left or right index invalid.");
    }
    // I use the StringBuilder as suggested in answer by mdfst13.
    //  https://codereview.stackexchange.com/questions/152137/write-a-java-class-sort-which-implements-the-bubblesort-algorithm
    //  The Array.stream suggestion I haven't understood well enough yet. But
    //  I keep it in mind for sometime in the future. ;)
    StringBuilder ret = new StringBuilder("[ ");

    for (int i = start; i <= end; i++) 
    {
        ret.append(list[i]).append(", ");
    }

    return ret.append(list[end]).append(" ]").toString();
}

// Return the complete array as an appropriate String representation.
public static String toString(int[] list)
{
    return Sort.toString(list, 0, list.length - 1);
}
}

My optional test-class which I have used while developing:

package test;

import algorithm.Sort;
import static java.lang.System.out;

public class SortTest
{
    public static void main(String[] args)
    {
        int[] test = { 9, 16, 17, 5, 3, 18, 14, 4, 14, 17 };
        out.println("Before: " + Sort.toString(test) + "\n");

        Sort.quickSort(test);

        out.println("After: " + Sort.toString(test));

        /*  RESULT :
            Before: [ 9, 16, 17, 5, 3, 18, 14, 4, 14, 17 ]

            After: [ 3, 4, 5, 9, 14, 14, 16, 17, 17, 18 ]        
        */
    }

}

It has passed the JUnit tests which the college employees use to evaluate our code.

But because I'm not convinced of that form of evaluation I would appreciate the comments and hints of real developer concerning my implementation.

Moreover: There are different implementations of QuickSort in which the Pivot-element is placed in the middle of the array: (leftIndex + rightIndex) / 2

What are the advantages / disadvantages of the two possible implementations?

Therefore: Looking forward to read your answers. :)

\$\endgroup\$
  • \$\begingroup\$ "I'm not convinced of that form of evaluation" what do you mean by that? Running UnitTest against your work? \$\endgroup\$ – Timothy Truckle Jan 15 '17 at 15:09
  • \$\begingroup\$ It just says: "You code is correct or your code has errors". I would prefer having feedback how I can improve my coding skills. \$\endgroup\$ – michael.zech Jan 15 '17 at 15:12
  • \$\begingroup\$ Having a comment with "everything" what it is there to accomplish is great - just turn your class&method comments into proper doc comments. \$\endgroup\$ – greybeard Jan 15 '17 at 17:41
  • \$\begingroup\$ @greybeard Thanks for the link. It's great. :) \$\endgroup\$ – michael.zech Jan 16 '17 at 6:44
2
\$\begingroup\$

Controll access to the recursive called methods by using private or no modifier. Using private would mean that only from inside the class containing the method it can be called. So you could add a method like

public static void initQuickSort(int[] list)
{
    quickSort(list, 0, list.length - 1);
}

and then add private and remove the throws from quickSort method itself since it does only get accessed by itself so itself controlls the input. If there is a reason the exception should be thrown you have a bug in your code.

private static void quickSort(int[] list, int leftIdx, int rightIdx)
{
    if (leftIdx < rightIdx) 
    {
        int index = divide(list, leftIdx, rightIdx);

        quickSort(list, leftIdx, index - 1);          
        quickSort(list, index + 1, rightIdx);
    }
}

Also the method call in the quickSort-Method outside your call of course has to be changed to

public static void quickSort(int[] list)
{
    Sort.initQuickSort(list);
}

It might be even possible to remove this step now since it does not add anything but might be necessary for the review-test so i will not say to remove but modify it.

Also i'd move the other static methods into your class and protecte them so fewer checks are needed. ASk yourself: what does the outside have to see, which methods need to be accessed from outside? And make access to the other methods as restricted as possible so they cannot be called from outside with corrupt arguments,

\$\endgroup\$
3
\$\begingroup\$
// Validate leftIndex and rightIndex concerning being within the
//  array range.   
public static void quickSort(int[] list, int leftIdx, int rightIdx)
{
    if (leftIdx > list.length) 

You missed to check leftIdx being < 0.


    if (i < j) 
    {
      // ...
    } 
} while (i < j);

You have the same condition in the if and in the while statement, maybe a head controlled while would have been the better choice over this tail controlled version.


  StringBuilder ret = new StringBuilder("[ ");
  for (int i = start; i <= end; i++) 
  {
      ret.append(list[i]).append(", ");
  }
  return ret.append(list[end]).append(" ]").toString();

This could be replaced by

 return Arrays.asList(list).toString();

No loop or stream needed as long as the elements are primitive types or their toString() method suits your needs.
The lesson is: "know your tools!"

\$\endgroup\$
  • 1
    \$\begingroup\$ [open coded toString()] could be replaced by [Arrays.asList(list).toString()] or even Arrays.toString(int[]). \$\endgroup\$ – greybeard Jan 15 '17 at 19:13
  • \$\begingroup\$ @Timothy Truckle Awesome hints. Thanks a lot. \$\endgroup\$ – michael.zech Jan 16 '17 at 6:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.