QuickSort in Java not delivering sorted results - java

I tried to implement the code for QuickSort using the algorithm which was mentioned on http://en.wikipedia.org/wiki/Quicksort#Algorithm .
But, I am not able to get a sorted output. Rather, I am only getting the same array as the output.
Can anybody review it for me and tell me what's wrong with my code?
public class QuickSort {
private int[] arr;
private void quick_sort(int[] input, int lo, int hi){
this.arr = input;
if(lo<hi){
int p = partition(arr, lo, hi);
if(lo < p-1)
quick_sort(arr, lo, p-1);
if(hi > p+1)
quick_sort(arr, p+1, hi);
}
}
private int partition(int[] arr, int lo, int hi){
int pivotIndex = hi; //last element
int pivotVal = arr[pivotIndex];
int j = lo;
for(int i = lo; i<hi; i++){
if(arr[i] < pivotVal){
swap(arr[j],arr[i]);
j++;
}
}
swap(arr[j],pivotVal);
return j;
}
private void swap(int l, int r){
l = l+r;
r = l-r;
l = l-r;
}
private void printArray(){
for(int i : arr)
System.out.print(i+", ");
}
public static void main(String[] args) {
QuickSort q = new QuickSort();
int[] input = {10, 5, 15, 3, 20, 30, 25, 19};
q.quick_sort(input, 0, input.length-1);
q.printArray();
}
};
Output:
10, 5, 15, 3, 20, 30, 25, 19,

Your swap method is incorrect. Java is always pass by value, and primitives can't be modified like that. Instead, pass in the array (the value of an array, as an Object instance, is its' reference) and the indexes to swap like
private void swap(int[] arr, int l, int r) {
int t = arr[l];
arr[l] = arr[r];
arr[r] = t;
}
And then you can call it like
private int partition(int[] arr, int lo, int hi) {
int pivotIndex = hi; // last element
int j = lo;
for (int i = lo; i < hi; i++) {
if (arr[i] < arr[pivotIndex]) {
swap(arr, j, i);
j++;
}
}
swap(arr, j, pivotIndex);
return j;
}
Output (with just those changes) is
3, 5, 10, 15, 19, 20, 25, 30,
Also, you could print the array like
System.out.println(Arrays.toString(arr));

Related

Recursive Insertion Sort

I have the following problem that I'm having trouble with, particularly in some of the parts where some of the code is given to me.
Problem Description: Given an array of integers, return an array containing the same integers sorted from the largest to the smallest using insertion sort. We'll use the convention of considering only part of the array that begins at a given index and ends at another. In this way, a recursive call can work through any part of the array. The initial call will pass in index 0 and the index to the last element.
insertionSort([2, 1, 3, -2, 8], 0, 4) → [8, 3, 2, 1, -2]
insertionSort([2, 6, -4], 0, 2) → [6, 2, -4]
insertionSort([2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22], 0, 10) → [22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2]
Code Given:
public int[] insertionSort(int[] nums, int begin, int end) {
}
void insert(int[] nums, int begin, int end, int element) {
int index=end;
while(index>=begin && nums[index]<element) {
index--;
}
for(int i=end; i>index; i--) {
nums[i+1] = nums[i];
}
nums[index+1] = element;
}
What I'm having trouble with is understanding what the "element" variable means in the "insert" method.
Here is the code I have written for it.
public int[] insertionSort(int[] nums, int begin, int end) {
if(begin >= end) return nums;
else if (begin < end){
int element = nums.length;
insert(nums, begin, end, element);
insertionSort(nums, begin, end);
}
return nums;
}
void insert(int[] nums, int begin, int end, int element) {
int index=end;
while(index>=begin && nums[index]<element) {
index--;
}
for(int i=end; i>index; i--) {
nums[i+1] = nums[i];
}
nums[index+1] = element;
}
This are the errors I get from my code:
Non recursive version:
public static int[] insertionSort(int[] nums, int begin, int end) {
for (int i = begin + 1; i <= end; i++) {
insert(nums, begin, i - 1, nums[i]);
}
return nums;
}
public static void insert(int[] nums, int begin, int end, int element) {
int index=end;
while(index>=begin && nums[index]<element) {
index--;
}
for(int i=end; i>index; i--) {
nums[i+1] = nums[i];
}
nums[index+1] = element;
}
public static void main(String[] args) {
int[] is = new int[]{5,6,7,2};
insertionSort(is, 0, is.length - 1);
System.out.println(Arrays.toString(is));
}
Recursive version:
public static int[] insertionSort(int[] nums, int begin, int end) {
if (begin>=end) {
return nums;
}
insertionSort(nums, begin, end-1);
insert(nums, begin, end-1, nums[end]);
return nums;
}
public static void insert(int[] nums, int begin, int end, int element) {
int index=end;
while(index>=begin && nums[index]<element) {
index--;
}
for(int i=end; i>index; i--) {
nums[i+1] = nums[i];
}
nums[index+1] = element;
}
public static void main(String[] args) {
int[] is = new int[]{5,6,7,2};
System.out.println();
insertionSort(is, 0, is.length - 1);
System.out.println(Arrays.toString(is));
}
so what you are doing wrong is passing the element as nums.length, element is the number to be inserted, that is after each recursive call it would be (begin+1)th element, and you will keep increasing begin by 1 as that part of array(0 to begin) would be already sorted.
SO the next time insertionsort would be called on begin+1 to end. Here is the working sample below.
public class Main
{
public static int[] insertionSort(int[] nums, int begin, int end) {
if(begin >= end) return nums;
else if (begin < end){
int element = nums[begin+1];
insert(nums, 0, begin, element);
insertionSort(nums, begin+1, end);
}
return nums;
}
static void insert(int[] nums, int begin, int end, int element) {
int index=end;
while(index>=begin && nums[index]<element) {
index--;
}
for(int i=end; i>index; i--) {
nums[i+1] = nums[i];
}
nums[index+1] = element;
}
public static void main(String[] args) {
int[] a = {3,41,0,10};
int[] t = insertionSort(a, 0, 3);
for (int i =0; i<4; i++){
System.out.println(t[i]);
}
}
}
I think this is more or less what you are trying to do.
class RecursiveInsertionSort {
public static void main(String[ ] args) {
int[] input1 = {2, 1, 3, -2, 8};
int[] input2 = {2, 6, -4};
int[] input3 = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22};
int[] res1 = insertionSort(input1, 0, 4);
// res1 = [8, 3, 2, 1, -2]
int[] res2 = insertionSort(input2, 0, 2);
// res2 = [6, 2, -4]
int[] res3 = insertionSort(input3, 0, 10);
// res3 = [22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2]
}
public static int[] insertionSort(int[] nums, int begin, int end) {
if(begin >= end) {
return nums; // We are done
}
// Sort the first n-1 elements
insertionSort(nums, begin, end - 1);
// Insert the nth element in the first n-1 elements array
insert(nums, begin, end - 1, nums[end]);
return nums;
}
static void insert(int[] nums, int begin, int end, int element) {
int index = end;
while(index >= begin && nums[index] < element) {
index--;
}
for(int i = end; i > index; i--) {
nums[i + 1] = nums[i];
}
nums[index + 1] = element;
}
}
The below solution is passing all your test cases. Your insert method should be something like this
public static int[] insertionSort(int[] nums, int begin, int end) {
if (begin >= end) {
return nums;
}
for (int i = 0; i < end; i++) {
insert(nums, i, end - 1, nums[end]);
}
return nums;
}
Below is the complete solution for your quick reference.
public class Solution {
public static void main(String[] args) {
int[] input1 = { 2, 1, 3, -2, 8 };
int[] result1 = insertionSort(input1, 0, 4);
printArray(result1);
int[] input2 = { 2, 6, -4 };
int[] result2 = insertionSort(input2, 0, 2);
printArray(result2);
int[] input3 = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22 };
int[] result3 = insertionSort(input3, 0, 10);
printArray(result3);
int[] input4 = { 6, 6, 6, };
int[] result4 = insertionSort(input4, 0, 2);
printArray(result4);
int[] input5 = { 8 };
int[] result5 = insertionSort(input5, 0, 0);
printArray(result5);
}
public static void printArray(int[] input) {
System.out.print("[ ");
for (int i = 0; i < input.length; i++) {
System.out.print(input[i] + " ");
}
System.out.println("]");
}
public static int[] insertionSort(int[] nums, int begin, int end) {
if (begin >= end) {
return nums;
}
for (int i = 0; i < end; i++) {
insert(nums, i, end - 1, nums[end]);
}
return nums;
}
static void insert(int[] nums, int begin, int end, int element) {
int index = end;
while (index >= begin && nums[index] < element) {
index--;
}
for (int i = end; i > index; i--) {
nums[i + 1] = nums[i];
}
nums[index + 1] = element;
}
}

Moving larger numbers to right, and smaller numbers to left of given value

I have a homework problem that gives me this array:
[3, 22, 1, 5, 6, 10, 4]
And I need to move all numbers that are larger than the last value, 4, to the right of the value and all of the values that are smaller to the left.
The numbers do not necessarily need to be in order. So, the output of the program would be:
[3, 1, 4, 22, 5, 6, 10]
For some reason I am really struggling to think of an algorithm that would allow for this to happen. I have tried creating a loop that swaps the last value with larger numbers, but if a smallest value is mixed in the array somewhere odd it will be to the right of the value which is not correct.
Can anyone help me with this?
I won't help you complete the home-work. But I will guide you to think where this example of yours is headed. It is the first step of quick sort - Partitioning the array.
public class QuickSortImpl {
private static void swap(int[] array, int l, int h) {
int temp = array[h];
array[h] = array[l];
array[l] = temp;
}
public static int partition(int[] array, int low, int high) {
int pivot = high;
int firsthigh = low;
int x,y;
for (int i = low; i < high; i++) {
x = array[i];
y = array[pivot];
if (array[i] < array[pivot]) {
swap(array, i, firsthigh);
firsthigh++;
}
}
swap(array, pivot, firsthigh);
return firsthigh;
}
private static void printArray(int[] arr ) {
for ( int i =0; i < arr.length; i++ ) {
System.out.print(" " + arr[i]);
}
System.out.println();
}
public static void quickSort(int[] array, int low, int high) {
if ( low < high ) {
int pivot = partition(array, low, high);
quickSort(array, low, pivot - 1);
quickSort(array, pivot + 1, high);
}
}
public static void main(String[] args) {
int[] arr = { 3, 22, 1, 5, 6, 10, 4};
quickSort(arr, 0, arr.length -1 );
printArray(arr);
}
}
#brent_mb, take a look at this simple example for your cause:
public static void main(String[] args) {
Integer[] listOfNumbers = {1,4,5,6,74,2,7,8,5,2,6,989,3};
//sort by number 6
FirstCustomComparator comparator = new FirstCustomComparator(6);
Arrays.sort(listOfNumbers, 0, listOfNumbers.length, comparator);
for (int number : listOfNumbers) {
System.out.print(number+" ");
}
}
FirstCustomComparator class:
public class FirstCustomComparator implements Comparator<Integer> {
private final int exception;
public FirstCustomComparator(int i)
{
exception = i;
}
#Override
public int compare(Integer a, Integer b)
{
if (a < exception)
{
return -1;
}
return a.compareTo(b);
}
}

Two different answers when using variables that should be the same (mergeSort)

I am a little confused and was looking for some clarification, so I am studying data structures and algorithms and was working on merge sort. Essentially I wanted to return the sorted list and print it to test to see if I had implemented the code correctly, however the lazy scientict I am decided not to copy the data back into the original array and instead just return the temp array. I noticed when I return temp at the end I'll get a different answer than if I returned the original array (named a) after copying back. Was wondering if someone could explain why this occurs. Thank you! Below is the code with the proper print, if you change the return to temp in the merge method you will notice the list stops sorting properly
public class mergeSort {
public static void main(String[] args) {
int[] a = new int[10];
for(int i = 0; i < a.length; i++) {
a[i] = (int)(Math.random()*30+1);
System.out.println(i + ": " + a[i]);
}
mergeSort(a);
}
public static void mergeSort(int[] a) {
int[] temp = new int[a.length];
a = mergeSort(a, 0, a.length, temp);
for(int i = 0; i < a.length; i++){
System.out.println(a[i]);
}
}
public static int[] mergeSort(int[] a, int start, int end, int[] temp) {
int mid;
//Recursive method
if(1 < end-start) {
mid = start + (end-start)/2;
mergeSort(a, start, mid, temp);
mergeSort(a, mid, end, temp);
a = merge(a, start, mid, end, temp);
}
return a;
}
public static int[] merge(int[] a, int start, int mid, int end, int[] temp) {
int currL = start;
int currR = mid;
int currT;
for(currT = start; currT < end; currT++) {
if(currL < mid && (currR >= end || a[currL] < a[currR])) {
temp[currT] = a[currL];
currL++;
}
else{
temp[currT] = a[currR];
currR++;
}
}
for(currT = start; currT < end; currT++) {
a[currT] = temp[currT];
}
return a;
}
}
Consider:
mergeSort(a, 0, 10, temp);
It calls:
mergeSort(a, 0, 5, temp);
mergeSort(a, 5, 10, temp);
a = merge(a, 0, 5, 10, temp);
After mergeSort(a, 0, 5, temp) returns, the sub-array a[0] to a[5] must be sorted, and after mergeSort(a, 5, 10, temp) returns, the sub-array a[5] to a[10] must be sorted.
This won't happen if merge doesn't modify the original array a is receives.
Note that the assignment a = merge(a, start, mid, end, temp); doesn't change the original array passed to the mergeSort method. Therefore merge itself must modify the array a passed to it, by copying the data from the temp array back to a.
EDIT:
BTW, note that it doesn't matter what merge returns as long as it copied the merged elements from the temp array back to the a array.
You can change its return type to void and the sort will still work:
public static void mergeSort(int[] a, int start, int end, int[] temp) {
int mid;
//Recursive method
if(1 < end-start) {
mid = start + (end-start)/2;
mergeSort(a, start, mid, temp);
mergeSort(a, mid, end, temp);
merge(a, start, mid, end, temp);
}
}
public static void merge(int[] a, int start, int mid, int end, int[] temp) {
int currL = start;
int currR = mid;
int currT;
for(currT = start; currT < end; currT++) {
if(currL < mid && (currR >= end || a[currL] < a[currR])) {
temp[currT] = a[currL];
currL++;
} else {
temp[currT] = a[currR];
currR++;
}
}
for(currT = start; currT < end; currT++) {
a[currT] = temp[currT];
}
}

Sorting index of array using merge Sort

I was trying to sort the index of an array using mergesort. The mergesort works perfectly , and the final answer is exactly correct but I am not sure why the indexes do not work out in correct positions. I do not want to sort the array, all I want to do is sort the perm[] array which is the index list.
To avoid confusions, Heres an example:
perm array holds the initial indices of the original array nums[] (i.e. 0 to nums.length - 1)
I want to move the indices in the perm array based on the data in the nums[] array such that the indices represent the sorted order.
For example :
Array -> (-1,9,-5,3,0)
Initial perm -> (0,1,2,3,4)
After sorting perm based on array - > (2,0,4,3,1)
Here's my code:
import java.util.Arrays;
public class IndexSort {
public boolean leq(Comparable u, Comparable v) {
return u.compareTo(v) <= 0;
}
public void merge(Comparable a[], int temp[], int perm[], int lo, int mid, int hi) {
int i = lo, j = mid + 1;
for (int k = lo; k <= hi; k++) {
temp[k] = perm[k];
}
for (int k = lo; k <= hi; k++) {
if (i > mid) {
perm[k] = temp[j++];
} else if (j > hi) {
perm[k] = temp[i++];
} else if (leq(a[perm[i]], a[perm[j]])) {
perm[k] = temp[i++];
} else {
perm[k] = temp[j++];
}
}
}
public void mergeSort(Comparable a[], int temp[], int perm[], int lo, int hi) {
if (hi <= lo)
return;
int mid = (hi + lo) / 2;
mergeSort(a, temp, perm, lo, mid);
mergeSort(a, temp, perm, mid + 1, hi);
merge(a, temp, perm, lo, mid, hi);
System.out.println(" lo = " + lo + " mid = " + mid + " hi = " + hi);
System.out.println(Arrays.toString(perm));
}
public void indexSort(Comparable nums[], int perm[]) {
int temp[] = new int[nums.length];
Comparable temp2[] = new Comparable[nums.length];
mergeSort(nums, temp, perm, 0, nums.length - 1);
}
public static void main(String[] args) {
IndexSort o1 = new IndexSort();
Comparable nums[] = { 12, -12, 0, 123, -123, 1, 2, 3, 4, -4, -4, -3, -2, 1 };
int perm[] = new int[nums.length];
for (int i = 0; i < perm.length; i++) {
perm[i] = i;
}
System.out.println(Arrays.toString(nums));
System.out.println(Arrays.toString(perm));
o1.indexSort(nums, perm);
System.out.println(Arrays.toString(perm));
}
}
I think this line needs to change from perm to temp:
} else if (leq(a[temp[i]], a[temp[j]])) {

Quick sort Error java

public int partition(int[]a,int i,int j){
int x=a[i];
int c=i;
for (int d = c+1; d < j; d++) {
if (a[d]<=x) {
c=c+1;
exchange(a, c, d);
}
}
exchange(a, c, i);
return c;
}
public void exchange(int[]a,int c,int d){
int temp=a[c];
a[c]=a[d];
a[d]=temp;
}
public void sort(int[]a,int i,int j){
int index;
if(i<j){
index=partition(a, i, j);
sort(a, i, index-1);
sort(a,index+1, j);
}
}
**strong text**public static void main(String[] args) {
// TODO code application logic here
QUICKSORT abir=new QUICKSORT();
abir.PRINT(abir.a);
abir.sort(abir.a, 0,10);
abir.PRINT(abir.a);
}
Here is my QuickSort code.
If i enter [6 10 13 5 8 3 2 11]
it prints [2 5 3 6 8 11 10 13]
Can anyone explain whats wrong with my code???
THank you
Your code seems quite strange to me, where did you take that?
Anyway why don't you take a look at this page for an explanation of quick sort?
http://www.algolist.net/Algorithms/Sorting/Quicksort
int partition(int arr[], int left, int right)
{
int i = left, j = right;
int tmp;
int pivot = arr[(left + right) / 2];
while (i <= j) {
while (arr[i] < pivot)
i++;
while (arr[j] > pivot)
j--;
if (i <= j) {
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
i++;
j--;
}
};
return i;
}
void sort(int arr[], int left, int right) {
int index = partition(arr, left, right);
if (left < index - 1)
sort(arr, left, index - 1);
if (index < right)
sort(arr, index, right);
}
static int[] a = {6, 10, 13, 5, 8, 3, 2, 11};
public static void main(String[] args) {
// TODO code application logic here
QUICKSORT abir=new QUICKSORT();
System.out.println(Arrays.toString(a));
abir.sort(a, 0, 7);
System.out.println(Arrays.toString(a));
}

Categories