Java quickSort algorithm indexoutofbounds - java

I'm trying to implement a quickSort algorithm after learning about it.
package qsort;
public class QuickSort {
public static void main(String[] args) {
int arr[] = {10,16,8,12,15,6,3,9,5,100};
quickSort(arr,0,(arr.length-1));
for(int number:arr) {
System.out.println(number);
}
}
public static void quickSort(int[] arr, int l, int h) {
if(l<h) {
int j=partition(arr,l,h); //pivot position as j retrieved as the one sorted element
int[] left = new int[j];
int[] right = new int[(arr.length-j)];
for(int index=0;index<j;index++) {
left[index]=arr[index];
}
for(int index=j;index<arr.length;index++) {
right[index-(j)]=arr[index];
}
quickSort(left,0,j); //Sorts the first half of the array (i.e the elements before pivot
quickSort(right,j+1,arr.length-1); //SOrts the second half after pivot
}
}
public static int partition(int[] arr, int l, int h) {
if(arr[l]>arr[h]) {
swap(arr[l],arr[h]);
}
int pivot = arr[l];
int i=l;
int j=h; //i starts from the first and increments; j starts from last and decrements
while(i<j) {
do {
i++;
}while(arr[i]<=pivot); //i keeps incrementing until i points to a value greater than pivot
do {
j--;
}while(arr[j]>pivot); //j keeps decrementing until it finds a value less than pivot
if(i<j) {
swap(arr[i],arr[j]);
}
}
swap(arr[l],arr[j]); // swapping the first element l with the element in j so that the pivotal element can be ordered
return j; //finally j points to the one sorted index where pivot should be placed
}
public static void swap(int a, int b){
int temp=a;
a=b;
b=temp;
}
}
And I've been clueless about IndexOutOfBoundsException and I'm not able to find out where or how it occurs. Any help would be much appreciated.

There are these issues:
swap doesn't swap. It just swaps the values of two local variables, but has no knowledge about an array. When swap exits, those two local variables are discarded and nothing really changed. You need to pass the array reference to swap and the two indices that are involved, and then swap should change the values in that array at those two given indices.
left gets j values, but then a recursive call is made with h equal to j, which is an index that is out of range. The left array has j elements, so its last index is j-1, not j.
right gets the remaining values, but then the recursive call is made with l equal to j+1, but that has no relation to right, whose relevant values start at index 0, not at index j+1.
The whole idea to copy values into new arrays left and right is wrong. This is not how quicksort is supposed to work. Even if left and right would be successfully sorted, this does not have any impact on arr, which remains unsorted. So you'd have done work for nothing. Quicksort is an inplace sorting algorithm, so you should always be working with arr, not with copies of partitions of it.
Here is the correction of the relevant functions:
public static void quickSort(int[] arr, int l, int h) {
if(l<h) {
int j=partition(arr,l,h);
// Don't create new arrays here, but sort the partition in-place:
quickSort(arr,l,j-1);
quickSort(arr,j+1,h);
}
}
public static int partition(int[] arr, int l, int h) {
if (arr[l]>arr[h]) {
swap(arr, l, h); // swap needs the array reference, and two indices
}
int pivot = arr[l];
int i=l;
int j=h;
while(i<j) {
do {
i++;
}while(arr[i]<=pivot);
do {
j--;
}while(arr[j]>pivot);
if(i<j) {
swap(arr, i, j); // see above
}
}
swap(arr, l, j); // see above
return j;
}
// swap needs the array reference and the indices to perform the swap in the array
public static void swap(int[] arr, int i, int j){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
I've been clueless about IndexOutOfBoundsException and I'm not able to find out where or how it occurs.
Debugging means you read the stack trace that includes this error message. It will give you the line number where it occurs (it was on the first line in partition). Then when you have identified that line, you can start to really use a debugger, setting breakpoints and inspecting variables. One of the first things you would notice, is that arr never changes: nothing gets moved in it. And so you would continue to debug and resolve one thing after the other. It is what I did with your code.

Related

What mistake am I making while memoizing this solution for Leetcode problem jump game 4

So the question is
You are given a 0-indexed integer array nums and an integer k.
You are initially standing at index 0. In one move, you can jump at most k steps forward without going outside the boundaries of the array. That is, you can jump from index i to any index in the range [i + 1, min(n - 1, i + k)] inclusive.
You want to reach the last index of the array (index n - 1). Your score is the sum of all nums[j] for each index j you visited in the array.
Return the maximum score you can get.
Example 1:
Input: nums = [1,-1,-2,4,-7,3], k = 2
Output: 7
Explanation: You can choose your jumps forming the subsequence [1,-1,4,3] (underlined above). The sum is 7.
I wrote a recursive solution in which we explore all the possibilies . If the function is called at index ind , then the value at index ind is added to a variable curSum for the next function call.
The base condition is when we reach the last index , we will return curSum+value of last index.
Here is the code:
class Solution {
static int min= Integer.MIN_VALUE;
public int maxResult(int[] nums, int k) {
return max(nums,0,k,0);
}
public int max(int [] nums, int ind, int k, int curSum)
{
if(ind==nums.length-1)
return curSum+nums[ind];
int max=Integer.MIN_VALUE;
for(int i=ind+1;i<=Math.min(nums.length-1,ind+k);i++)
max=Math.max(max, max(nums,i,k,curSum+nums[ind]));
return max;
}
}
Code works fine except the exponential complexity ofcourse.
I tried memoizing it as
class Solution {
static int[] dp;
static int min= Integer.MIN_VALUE;
public int maxResult(int[] nums, int k) {
dp=new int[nums.length];
Arrays.fill(dp,min);
return max(nums,0,k,0);
}
public int max(int [] nums, int ind, int k, int curSum)
{
if(ind==nums.length-1)
return curSum+nums[ind];
if(dp[ind]!=min)
return dp[ind];
int max=Integer.MIN_VALUE;
for(int i=ind+1;i<=Math.min(nums.length-1,ind+k);i++)
max=Math.max(max, max(nums,i,k,curSum+nums[ind]));
return dp[ind]=max;
}
}
But this solution gives the wrong max everytime and I am not quite able to figure out why.
Any hints will be appreciated.
Thanks
You only need to memoize dp[index] instead of calling f(index, currSum).
Take for example present arr.length = 5, k = 2
For index-2 you need wether index 3 or 4 gives better points to you irrespective of your present point.
Better way would be :
class Solution {
static int[] dp;
static int min= Integer.MIN_VALUE;
public int maxResult(int[] nums, int k) {
dp=new int[nums.length];
Arrays.fill(dp,min);
return max(nums,0,k,0);
}
public int max(int [] nums, int ind, int k, int curSum)
{
// base-case
if(ind==nums.length-1)
return curSum+nums[ind];
// if already memoized
if(dp[ind]!=min)
return dp[ind] + curSum;
// if not memoized, calculate value now
int max=Integer.MIN_VALUE;
for(int i=ind+1;i<=Math.min(nums.length-1,ind+k);i++)
max=Math.max(max, max(nums,i,k,nums[ind]);
// memoize here
dp[ind] = max
return dp[ind] + curSum;
}
}

Merge Sort Recursion

This is a code from Introduction to Java Programming about Merge Sort. This method uses a recursion implementation.
public class MergeSort {
2 /** The method for sorting the numbers */
3 public static void mergeSort(int[] list) {
4 if (list.length > 1) {
5 // Merge sort the first half
6 int[] firstHalf = new int[list.length / 2];
7 System.arraycopy(list, 0, firstHalf, 0, list.length / 2);
8 mergeSort(firstHalf);
9
10 // Merge sort the second half
11 int secondHalfLength = list.length - list.length / 2;
12 int[] secondHalf = new int[secondHalfLength];
13 System.arraycopy(list, list.length / 2,
14 secondHalf, 0, secondHalfLength);
15 mergeSort(secondHalf);
16
17 // Merge firstHalf with secondHalf into list
18 merge(firstHalf, secondHalf, list);
19 }
20 }
My question: is in Line 8 calls the recursion method back to "mergeSort"? If running from the beginning of the method, the "firstHalf" array will be created again and the length will be half short. I think the "firstHalf" can not created again and the length should not be changed if an array is defined already.
Here is the whole code link: Merge Sort Java.
This is beginner's way of thinking. Yes, exactly I thought the same when I encountered this before. I couldn't believe that the same array size can change dynamically. Understand this, in the below code, array l and array r are created with different sizes for every recursive call. Don't confuse on this.
Yes, this is never possible that the same array size changes dynamically for a beginner like you and me. But, there is an exception, well, there are exceptions. We will see them very often as we move forward.
Its recursion, in recursion things change dynamically and all this
changes are stored in a call stack.
Its confusing but its really interesting if you ponder over it. Its profound. Merge sort can be implemented in quite different ways, but the underlying concept of recursion is same. Don't get confused here, Its better you follow another way to do it, video:
Merge sort first takes a list or an array. Lets imagine the
a.length; #lenght of an array is 8
Now the end goal is to split the array recursively, till it reaches to a point where there are no-elements (only-one). And a single element is always sorted.
See the base case in the below code:
if(a.length<2) /*Remember this is the base case*/
{
return;
}
Once it reaches to single element, sort and merge them back. This way you get a complete sorted array which is easy to merge. The only reason we are doing all this non-sense is to get a better run-time algorithm which is O(nlogn).
Because, all the other sorting algos (insertion, bubble, and selection) will take O(n2), which is alot, too much indeed. So, humanity must figure out the better solution. Its a need for humanity, very important. I know its annoying, I had gone through this non-sense.
Please do some research on recursion before you attempt on this. Understand recursion clearly. Keep all this away. Take a simple recursion example and start working on it. Take a factorial example. Its a bad example but its easy to understand.
Top-down MergeSort
See my code, its nice and easy. Again, both are not easy to understand on your first attempt. You must get in touch with recursion before you attempt to understand these things. All the very best.
public class MergeSort
{
private int low;
private int high;
private int mid;
public static int[] a;
public MergeSort(int x)
{
a = new int[x];
a[0]=19;
a[1]=10;
a[2]=0;
a[3]=220;
a[4]=80;
a[5]=2000;
a[6]=56001;
a[7]=2;
}
public void division(int[] a)
{
low=0;
int p;
high = a.length;
mid = (high+low)/2;
if(a.length<2) /*Remember this is the base case*/
{
return;
}
else
{
int[] l = new int[mid];
int[] r = new int[high-mid];
/*copying elements from a into l and r*/
for(p=0;p<mid;p++)
l[p]=a[p];
for(int q=0;q<high-mid;q++, p++)
r[q]=a[p];
/*first recursive call starts from here*/
division(l);
division(r);
sortMerge(a, l, r);
}
}
public void sortMerge(int[] a, int[] l, int[] r)
{
int i=0, j=0, k=0;
/*sorting and then merging recursively*/
while(i<l.length && j<r.length)
{
if(l[i]<r[j])
{
a[k] = l[i]; /*copying sorted elements into a*/
i++;
k++;
}
else
{
a[k] = r[j];
j++;
k++;
}
}
/*copying remaining elements into a*/
while(i<l.length)
{
a[k] = l[i];
i++;
k++;
}
while(j<r.length)
{
a[k] = r[j];
j++;
k++;
}
}
/*method display elements in an array*/
public void display()
{
for(int newIndex=0;newIndex<a.length;newIndex++)
{
System.out.println(a[newIndex]);
}
}
public static void main(String[] args)
{
MergeSort obj = new MergeSort(8);
obj.division(a);
obj.display();
}
}
As it was pointed out by Emz: This is due to scope reasons. A local variable is a new object.
[
Local variables are declared by local variable declaration statements
(§14.4).
Whenever the flow of control enters a block (§14.2) or for statement
(§14.14), a new variable is created for each local variable declared
in a local variable declaration statement immediately contained within
that block or for statement.
A local variable declaration statement may contain an expression which
initializes the variable. The local variable with an initializing
expression is not initialized, however, until the local variable
declaration statement that declares it is executed. (The rules of
definite assignment (§16) prevent the value of a local variable from
being used before it has been initialized or otherwise assigned a
value.) The local variable effectively ceases to exist when the
execution of the block or for statement is complete.]1
Here is an alternative implementation of merge sort, this is bottom-up MergeSort
public class MergeSort {
public static void merge(int[]a,int[] aux, int f, int m, int l) {
for (int k = f; k <= l; k++) {
aux[k] = a[k];
}
int i = f, j = m+1;
for (int k = f; k <= l; k++) {
if(i>m) a[k]=aux[j++];
else if (j>l) a[k]=aux[i++];
else if(aux[j] > aux[i]) a[k]=aux[j++];
else a[k]=aux[i++];
}
}
public static void sort(int[]a,int[] aux, int f, int l) {
if (l<=f) return;
int m = f + (l-f)/2;
sort(a, aux, f, m);
sort(a, aux, m+1, l);
merge(a, aux, f, m, l);
}
public static int[] sort(int[]a) {
int[] aux = new int[a.length];
sort(a, aux, 0, a.length-1);
return a;
}
}
To understand how Merge Sort works you must understand two core data structures, Arrays and Stacks. Stacks are LIFO (Last in First Out). Method calls are executed using Stacks, so the last method call is executed first. Due to these factors, the Merge Sort has this unique behavior.
For example let's take an array as an input:
int[] input = new array[] {12, 11, 13, 5, 6, 7};
Now let's implement a Merge Sort on this array:
'''
class MergeSort
{
private static void merge_sort(int[] arr)
{
if (arr.length > 1)
{
int midpoint = arr.length / 2;
int[] l_arr = new int[midpoint];
int[] r_arr = new int[arr.length - midpoint];
int L_index = 0;
int R_index = 0;
// SORTING [ BEGIN ]
// [ BEGIN ]
// WHILE LOOP THAT IS FILLING THE LEFT ARRAY
//
while(L_index < l_arr.length )
{
l_arr[L_index] = arr[L_index];
if (L_index + 1 < l_arr.length)
{
l_arr[L_index + 1] = arr[L_index + 1];
L_index++;
}
L_index++;
}
// [ END ]
L_index = midpoint;
// [ BEGIN ]
// A WHILE LOOP THAT IS FILLING THE RIGHT ARRAY
//
while(R_index < r_arr.length)
{
r_arr[R_index] = arr[L_index];
if (R_index + 1 < r_arr.length)
{
r_arr[R_index + 1] = arr[L_index + 1];
L_index++;
R_index++;
}
L_index++;
R_index++;
}
// [ END ]
merge_sort(l_arr);
merge_sort(r_arr);
// SORTING [ END ]
// MEGING [ BEGIN ]
int l_index = 0;
int r_index = 0;
int index = 0;
while (l_index < l_arr.length && r_index < r_arr.length )
{
if (l_arr[l_index] <= r_arr[r_index])
{
arr[index] = l_arr[l_index];
l_index++;
}
else
{
arr[index] = r_arr[r_index];
r_index++;
}
index++;
}
while (l_index < l_arr.length)
{
arr[index] = l_arr[l_index];
l_index++;
index++;
}
while (r_index < r_arr.length)
{
arr[index] = r_arr[r_index];
r_index++;
index++;
}
// MEGING [ END ]
}
}
public static void main(String[] args)
{
int[] arr = new int[] {12, 11, 13, 5, 6, 7};
// BEGIN THE MERGE SORT
merge_sort(arr);
}
}
'''
When the merge sort is called the array is split into two arrays, the left array and right array. When the split happens, the left and right arrays are filled, and then recursion occurs.
The split happens always on the left until no split cannot be done, then the split transitions to the right half.
When the array reaches the size of one, the recursion stops, giving control to the previous method call. When no recursion cannot be performed, the code execution will go bellow the recursive method calls and the merge section of the algorithm will arrange the two halves in increasing / decreasing order and pass the control back to its own caller method instance.
Now the magic happens. When the array is given as a parameter to a method and it is sorted, the modifications done on the array parameter will affect the array that is within the caller method instance because, arrays are passed by reference and not by value. So this means that each time recursion occurs and it is passing the left or right half of the array, it is passing a reference to the left or right array and the modifications done by the called method instance will affect the array passed as a parameter in the caller method.

Can't change variable while doing recursion

public static void main(String[] args) {
int[] a = { 1, 2, 3, 4, 5 };
int[] b = new int[5];
rekursiq(a, b, 0, 0, 1);
}
static void rekursiq(int[] a, int[] b, int index, int start, int check) {
if (index == b.length){
System.out.println(java.util.Arrays.toString(b));
} else {
for (int i = start; i < a.length; i++) {
b[index] = a[i];
rekursiq(a, b, index + 1, i + 1, check + 1);
}
}
}
Now my question is: Instead of b.length in the recursion bottom I want to place an int check, and make check go +1 on every going there, and do something.
while (check < b.length) go the if statement, else return; but I can't seem to 1) increase the value properly and 2) make this while correctly. I don't know why.
I think my best try was
static void rekursiq(int[] a, int[] b, int index, int start, int check) {
if (check > b.length) {
return;
} else {
if (index == check) {
System.out.println(java.util.Arrays.toString(b));
} else {
for (int i = start; i < a.length; i++) {
b[index] = a[i];
rekursiq(a, b, index + 1, i + 1, check + 1);
}
}
}
}
But it did not work, and I hope some one of you can tell me why and how to fix it.
The value of check does increase when the method is called recursively. However, the problem you have is independent of check.
The Problem
Let me start by repeating what abhishrp already briefly mentioned: In this particular case, you want to either use a loop to iterate over all elements in the array, or recursion, but not use a loop inside of your recursive method. The reason is the following: At each step in the recursion, you look at exactly one element: the element at position index.
The Solution
So, how would you recursively copy an array? Let us assume you have a source array (in your code a) and an empty destination array (in your code b). Now, we know how to copy a single element of the array, namely destination[index] = source[index], and we can imagine copying the array as copying the first element, and then copying the subarray starting at the second element. Note that knowing how to copy a single element in an array implies knowing how to copy an array containing only one element.
This leads us to the following recursion, which we will turn to code shortly after:
if the given index dereferences the last element in the array, then copy this last element.
otherwise, copy the element at the current index, and copy the subarray starting at the next index.
Or expressed in Java:
static void copyValuesFromSourceToDestinationStartingAtIndex(int[] source, int[] destination, int index) {
if (isIndexOfLastElementInArray(index, destination)) {
destination[index] = source[index];
} else {
destination[index] = source[index];
copyValuesFromSourceToDestinationStartingAtIndex(source, destination, index + 1);
}
}
static boolean isIndexOfLastElementInArray(int index, int[] array){
return index == array.length - 1;
}
Note that you have too many parameters in your code: The parameter check is really just index, as you want to check whether the index is still inside the bounds of the array. I don't really know what you intended to do with the variable start though - seems like somehow you got confused there because of the loop.
Sidenote
Also, a small justification on why the true-branch of the if-statement in the above code does copy the last element instead of returning nothing if the index is out of bounds as in your code. It's perfectly reasonable to do it like you did. The argument "We trivially know how to copy an empty array" just didn't seem as natural as "knowing how to copy a single element implies knowing how to copy an array consisting of a single element". I encourage you however to adjust the code to "copy an empty array" as a base-case, because it removes the duplication, and more importantly, allows you to copy empty arrays (for which the above implementation would fail horribly).
Code
I also tried to give a comparison between the iterative and the recursive approach:
public static void main(String[] args) {
int[] a = {1, 2, 3, 4, 5};
int[] copyOfAUsingIteration = copyArrayUsingIteration(a);
int[] copyOfAUsingRecursion = copyArrayUsingRecursion(a);
assert(Arrays.equals(copyOfAUsingIteration, copyOfAUsingRecursion));
assert(copyOfAUsingIteration != a);
assert(copyOfAUsingRecursion != a);
System.out.println(java.util.Arrays.toString(copyOfAUsingIteration));
System.out.println(java.util.Arrays.toString(copyOfAUsingRecursion));
}
static int[] copyArrayUsingIteration(int[] arrayToCopy) {
int[] result = new int[arrayToCopy.length];
for(int index = 0; index < result.length; index++){
result[index] = arrayToCopy[index];
}
return result;
}
static int[] copyArrayUsingRecursion(int[] arrayToCopy){
if (arrayToCopy.length == 0){
return new int[0];
} else {
int[] result = new int[arrayToCopy.length];
copyValuesFromSourceToDestinationStartingAtIndex(arrayToCopy, result, 0);
return result;
}
}
static void copyValuesFromSourceToDestinationStartingAtIndex(int[] source, int[] destination, int index) {
if (isIndexOfLastElementInArray(index, destination)) {
destination[index] = source[index];
} else {
destination[index] = source[index];
copyValuesFromSourceToDestinationStartingAtIndex(source, destination, index + 1);
}
}
static boolean isIndexOfLastElementInArray(int index, int[] array){
return index == array.length - 1;
}
To copy one array to another you can use either iteration or recursion. There is no need to do both. By this I mean there is no need for the for loop inside the rekursiq method.

Equivalent java code statement for C code statement used in recursion

The code below does quick sort in C.I tried to translate the same code logic into java.But, i am unable to write the equivalent Java code statement for "partition(&arr[left+1],size-left-1);" in the partition function below.Can anyone help?
#include<stdio.h>
int main()
{
int arr[8]={4,8,1,6,3,7,2,5};
partition(arr,8);//Initial Calling of partition function
int i;
for(i=0;i<8;i++)
printf("%d ",arr[i]);
return 0;
}
void partition(int arr[],int size)
{
if(size<2)
return;
int pivot=arr[rand()%size];
int left=0,right=size-1,temp=0;
while(left<right)
{
while(arr[left]<pivot)
left++;
while(arr[right]>pivot)
right--;
temp=arr[left],arr[left]=arr[right],arr[right]=temp;//swapping values
}
//partitioning and recursive calling
partition(arr,left);
partition(&arr[left+1],size-left-1);//The problem is to write an equivalent code for this
//line in Java
}
To get rid of pointers you need to specify start and end by parameters. Define you function like the following:
void partition(int arr[],int start, int end)
and instead of:
int left=0,right=size-1,temp=0;
do
int left=start,right=end,temp=0;
C allows you to use pointers to refer to a different starting point in the same array. Java does not. You can only refer to the entire array.
But you can add the starting index as a parameter.
void partition(int arr[],int offset, int length) {
...
partition(arr[], left+1, size-left-1); // check calculation, might be wrong :)
}
A solution without needing to handle pointers is to change the header like this:
void partition(int array[], int firstElement, int lastElement);
You can also try the function copyOf described here:
copyOf
But you would have to reconstruct it back together since you're working on copies, and I doubt it would be much QUICKsort anymore
public static boolean[] copyOf(boolean[] original,
int newLength)
Copies the specified array, truncating or padding with false (if necessary) so the copy has the specified length. For all indices that are valid in both the original array and the copy, the two arrays will contain identical values. For any indices that are valid in the copy but not the original, the copy will contain false. Such indices will exist if and only if the specified length is greater than that of the original array.
Parameters:
original - the array to be copied
newLength - the length of the copy to be returned
Returns:
a copy of the original array, truncated or padded with false elements to obtain the specified length
Throws:
NegativeArraySizeException - if newLength is negative
NullPointerException - if original is null
Since:
1.6
The x argument refers to the "pivot " value. In any case you need to study how this algorithm works.
public static int partition(
int[] arr, int start, int end, int x)
{
int l = start,r = end;
while (l<r ) {
if (arr[l] < x)
{
l =l +1;
}
else {
int temp = arr[l];
arr[l] = arr[r-1];
arr[r-1] = temp;
r = r-1;
}
}
return l;
}
Below is the equivalent Java code for the above (problem) partition function written in C.The initial call to partition function,say,from inside main, may be somewhat like this:partition(arr,0,arr.length-1);
Thanks for all your support and guidance
static void partition(int arr[],int first,int last)
{
int left=first;
int right=last,temp=0;
if(left>=right)
return;
Random rnd=new Random();
int pivot = arr[left + rnd.nextInt(right - left)];
while(left<right)
{
while(arr[left]<pivot)
left++;
while(arr[right]>pivot)
right--;
temp=arr[left];
arr[left]=arr[right];
arr[right]=temp;
}
partition(arr,first,left);
partition(arr,left+1,last);
}

What is wrong with my Java quicksort implementation?

I'm pretty sure I understand how quicksort works, but I can't find the bug that's causing my attempt at implementing it to not work. I've looked through this for hours and can't figure out what's wrong. Please help me! Here is the entire file (It's just quicksort - nothing extra. The array is just random numbers for testing the quicksort.)
public class Quicksort{
public static void main(String args[]){
int[] arr = {5,1,4,3,7,0,9,2,6,8};
quicksort(arr, 0, arr.length-1);
for(int x : arr)
System.out.print(x+" ");
}
public static void quicksort(int[] arr, int start, int end){
if(end-start<2)
return;
int pivot = (end-start)/2;
int i = start;
int k = end;
while(k>i){
while(arr[i]<arr[pivot]&&k>i&&i<=end)
i++;
while(arr[k]>arr[pivot]&&k>=i)
k--;
if(k>i){
swap(arr, i, k);
}
}
swap(arr, pivot, i);
quicksort(arr, 0, i);
quicksort(arr, k, arr.length-1);
}
public static void swap(int[] a, int x, int y){
int temp = a[x];
a[x] = a[y];
a[y] = temp;
}
}
As it is right now, the loop never terminates... it's a forever infinite loop! Please help me figure out what's wrong.
Do yourself a favor and learn how to use a debugger. It makes solving this kind of problems very easy.
Your base case should be if(end-start<1) - You only want to stop sorting when the number of elements is 1 (i.e. if start and end are equal)
Your while loops should just be while(arr[i]<arr[pivot]) and while(arr[k]>arr[pivot])
This
if(k>i){
swap(arr, i, k);
}
should be
if(k>=i){
swap(arr, i, k);
i++;
k--;
}
swap(arr, pivot, i); is unnecessary.
Your recursive call should be quicksort(arr, start, k); and quicksort(arr, i, end);
Couple of things that stand out --
Your end condition seems incorrect. If your array has just 2 elements, it won't sort them.
Also, after you do the swap, you need to increment and i and decrement k.
while(arr[i]<arr[pivot]&&k>i&&i<=end)
Clearly you have had array index problems. All these tests aren't required in a working Quicksort, and the ones that are are in the wrong order.

Categories

Resources