JAVA-mergeSort returning array - java

I have been having trouble with my mergesort() implementation since im returning an array i get stackoverflow error in mergesotrt(). my merge() works fine this is a small clippet my entire program has an ArraytoString() which work fine and prints to console im adding in alsp im not allowed to change the implementation type like the basic format has to remain
{37, 27, 43, 3, 9, 81, 10}
public static int[] merge(int[] arr1, int start, int mid, int end, int[] temp) {
int beginHalf1 = start;
int endHalf1 = mid;
int beginHalf2 = mid+1;
int endHalf2 = end;
//if odd its mid half of
int index = 0;
//until arraysect runs out check which is smaller and send to temp
while (beginHalf1 <= endHalf1 && beginHalf2 <= endHalf2){
if(arr1[beginHalf1] <= arr1[beginHalf2]){
temp[index] = arr1[beginHalf1];
beginHalf1++;
}else {//>=
temp[index] = arr1[beginHalf2];
beginHalf2++;
}
index++;
}//pass leftover items to array
if(beginHalf1>endHalf1){//right half not done
while (beginHalf2<=endHalf2){
temp[index] = arr1[beginHalf2];
beginHalf2++;
index++;
}
}else if(beginHalf2>endHalf2){ //left half not done
while (beginHalf1<=endHalf1){
temp[index] = arr1[beginHalf1];
beginHalf1++;
index++;
}
}
return temp;
}
public static int[] mergeSort(int[] arr, int start, int end, int[] temp) {
//arr unsorted returns sorted copy of that array
//idk why it doesnt run
if (start < end) {
int mid = ((start + end) / 2)-1;//offset for mid for odd size
mergeSort(arr, start, mid, temp);
mergeSort(arr, mid + 1, end, temp);
merge(temp, start, mid, end, temp);
}
return temp;//what do i return
}
public static void main(String[] args) {
int[] arr = {37, 27, 43, 3, 9, 81, 10};//3,9,10,27,39,43
int length = sortedmerge.length/2-1;//-1 offset for mid
arrayToString(mergeSort(arr,0,arr.length,new int[arr.length]));
}

if (start < end) {
int mid = ((start + end) / 2) - 1; //offset for mid for odd size
mergeSort(arr, start, mid, temp);
mergeSort(arr, mid + 1, end, temp);
merge(temp, start, mid, end, temp);
}
start would never be less than mid so your first invokation of mergeSort(arr, start, mid, temp); seems to enter the infine loop which causes stackoverflow.

Related

My Quicksort implementation does not sort correctly

I have been looking around but my confusion remains. I changed some things which people suggested around here but that only made the code worse.
I am using this list as a test int [] testing = {5, 2, 9, 6, 1, 7, 8, 10, 4, 12, 3, 13, 11};
and I am getting < 1 2 3 5 4 6 7 8 10 9 11 12 13 > as a result. (I made the errors bold)
My main quicksort method.
public static void quickieSorty(int[] array, int start, int end) {
int pivot;
pivot = originalPivot(array, start, end);
if (start < end)
{
pivot = originalPivot(array, start, end);
quickieSorty(array, start, pivot - 1);
quickieSorty(array, pivot + 1, end);
}
}
Partition (Here is were I changed some things inside the for loop, but that just made the list even less sorted).
private static int originalPivot (int[] array, int start, int end) {
int pivotValue;
int endOfList;
int mid;
mid = (start + end) / 2;
swap(array, start, mid);
pivotValue = array[start];
endOfList = start;
for (int i = start + 1; i <= end; i++)
{
if (array[i] < pivotValue)
{
endOfList++;
swap(array, endOfList, i);
}
}
swap(array, start, endOfList);
return endOfList;
}
Swap is the generic swap code
private static void swap (int[] array, int a, int b) {
int temp;
temp = array[a];
array[a] = array[b];
array[b] = temp;
}
I used my textbook and called a helper, but they told me they do not know for sure.
Any help is welcomed, thanks in advance for your time, and help!

Correct conditions for quickselect

I am implementing the quick-select algorithm to get the kth element in an array, and I am stuck at a place where I don't know how to resolve. Here is my code that doesn't work:
public static void main (String[] args) {
int[] arr = new int[]{7,6,5,4,3,2,1};
int k = 4;
quickSort(arr, 0, arr.length - 1, k);
return arr[k];
}
private static void quickSelect(int[] nums, int start, int end, int k) {
if (start < end) {
int partitionIndex = getPartitionIndex(nums, start, end);
if (partitionIndex == k) {
return;
}
quickSelect(nums, start, partitionIndex - 1, k);
quickSelect(nums, partitionIndex + 1, end, k);
}
}
private int getPartitionIndex(int[] nums, int start, int end) {
int pivot = nums[end];
int index = start;
for (int i = start; i <= end; i++) {
int current = nums[i];
if (current < pivot) {
swap(nums, index, i);
index++;
}
}
swap(nums, index, end);
return index;
}
private void swap(int[] nums, int i, int j) {
if (i == j) {
return;
}
nums[i] = nums[i] ^ nums[j];
nums[j] = nums[i] ^ nums[j];
nums[i] = nums[i] ^ nums[j];
}
Sure, if I remove these lines:
if (partitionIndex == k) {
return;
}
It becomes quicksort and works fine. And I understand why it's not working, it is since the array I am getting from 0 to k might not be sorted as I return at the above condition. But I am not able to find the right conditions where I sort only the first k elements in the array and leave out the rest, so that I don't do any extra work. I've looked at some implementations online and spent some time on the above, but not able to figure it out, so reaching out for help.
If k < partitionIndex, only check the left partition, else only check the right partition.
if (k < partitionIndex)
quickSelect(nums, start, partitionIndex - 1, k);
else
quickSelect(nums, partitionIndex + 1, end, k);

Recursive Quick Sort in java

This is my quicksort Code. It gives me a wrong answer but i think my partition function is correct.
public class Quick_Sort {
public static void main(String[] args)
{
int a[] = {99,88,5,4,3,2,1,0,12,3,7,9,8,3,4,5,7};
quicksort(a, 0, a.length-1);
}
static int partition(int[] a, int low , int hi)
{
int pivot = hi;
int i =low;
int j = hi-1;
while(i<j)
{
if(a[i]<=a[pivot])
{
i++;
}
if(a[i]>a[pivot])
{
if((a[i]>a[pivot]) && (a[j]<=a[pivot]))
{
int temp= a[i];
a[i]=a[j];
a[j]=temp;
i++;
}
if(a[j]>a[pivot])
{
j--;
}
}
}
int temp= a[i];
a[i]=a[pivot];
a[pivot]=temp;
return i;
}
static void quicksort(int[] a, int low, int hi)
{
if(low>=hi)
{
return;
}
int split = partition(a, low, hi);
quicksort(a, low, split-1);
quicksort(a, split+1, hi);
}
}
This is the final output:
1 0 3 2 3 4 4 5 5 7 3 7 8 9 12 88 99
Tried dry running it, couldn't see the error
In your partition method you have assigned j to hi - 1. It should be set to hi only.
static int partition(int[] a, int low , int hi)
{
int pivot = hi;
int i =low;
// int j = hi-1; // CHANGE THIS TO
int j = hi; // THIS
while(i<j)
I got this output after I made that change:
[0, 1, 2, 3, 3, 3, 4, 4, 5, 5, 7, 7, 8, 9, 12, 88, 99]
Hope this helps!
This is C# code:
public void RecursiveQuickSort(int[] array, int start, int end)
{
if (start < end)
{
int pivot = start;
int left = start + 1;
int right = end;
while (true)
{
while (array[left] <= array[pivot] && left < right)
left++;
while (array[right] > array[pivot] && left < right)
right--;
if (left < right)
{
Swap(array, left, right);
}
else
{
pivot = (array[pivot] > array[left]) ? left : left - 1;
Swap(array, start, pivot);
RecursiveQuickSort(array, start, pivot - 1);
RecursiveQuickSort(array, pivot + 1, end);
return;
}
}
}
}
private void Swap(int[] array, int index1, int index2)
{
int temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}
This is a very good implementation and is much more Java standard. Maybe you want to take a look here, obviously all credits go to the original author.
http://www.vogella.com/tutorials/JavaAlgorithmsQuicksort/article.html
this is how I made it C:
private static List<Integer> recursive_quick_sort (List<Integer> list){
if (list.size()< 2){
return list;
}else {
int pivot = list.get(0);
List<Integer> less = list.stream().filter(element -> element < pivot ).collect(Collectors.toList());
List <Integer> greater = list.stream().filter(element -> element > pivot ).collect(Collectors.toList());
List<Integer> newList = Stream.of(recursive_quick_sort(less),List.of(pivot),recursive_quick_sort(greater))
.flatMap(Collection::stream)
.collect(Collectors.toList());
return newList;
}
}

Find Kth min elem by randomized pivot method. Some weird bug

I try to use "randomized pivot" method to find the Kth min elem among given array.
[The code]
public class FindKthMin {
// Find the Kth min elem by randomized pivot.
private static void exchange (int[] givenArray, int firstIndex, int secondIndex) {
int tempElem = givenArray[firstIndex];
givenArray[firstIndex] = givenArray[secondIndex];
givenArray[secondIndex] = tempElem;
}
private static int partition (int[] givenArray, int start, int end, int pivotIndex) {
// Debug:
//System.out.println("debug: start = " + start);
//System.out.println(">> end = " + end);
//System.out.println(">> pivotIndex = " + pivotIndex);
int pivot = givenArray[pivotIndex];
int left = start - 1;
int right = end;
boolean hasDone = false;
while (!hasDone) {
while (!hasDone) {
left ++;
if (left == right) {
hasDone = true;
break;
}
if (givenArray[left] >= pivot) {
// Exchange givenArray[left] and the givenArray[right].
exchange(givenArray, left, right);
break;
}
}
while (!hasDone) {
right --;
if (left == right) {
hasDone = true;
break;
}
if (givenArray[right] < pivot) {
// Exchange the givenArray[right] and the givenArray[left].
exchange(givenArray, right, left);
break;
}
}
}
givenArray[right] = pivot;
// Debug:
//System.out.println(">> split = " + right);
//System.out.println();
return right;
}
private static int findKthMin_RanP_Helper (int[] givenArray, int start, int end, int k) {
if (start > end) return -1;
// Generate a random num in the range[start, end].
int rand = (int)(start + Math.random() * (end - start + 1));
// Using this random num as the pivot index to partition the array in the current scope.
int split = partition(givenArray, start, end, rand);
if (k == split + 1) return givenArray[split];
else if (k < split + 1) return findKthMin_RanP_Helper(givenArray, start, split - 1, k);
else return findKthMin_RanP_Helper(givenArray, split + 1, end, k);
}
public static int findKthMin_RanP (int[] givenArray, int k) {
int size = givenArray.length;
if (k < 1 || k > size) return -1;
return findKthMin_RanP_Helper(givenArray, 0, size - 1, k);
}
// Main method to test.
public static void main (String[] args) {
// Test data: {8, 9, 5, 2, 8, 4}.
int[] givenArray = {8, 9, 5, 2, 8, 4};
// Test finding the Kth min elem by randomized pivot method.
System.out.println("Test finding the Kth min elem by randomized pivot method, rest = " + findKthMin_RanP(givenArray, 1));
}
}
But the result is unstable, sometimes right and sometimes wrong.
Please have a look at the 5th row of findKthMin_RanP_Helper method:
If I change this int split = partition(givenArray, start, end, rand); to int split = partition(givenArray, start, end, end);, the result is always correct. I really can not find what's wrong with this.
EDIT:
The problem comes from the "partition", the new partition should like this:
private static int partition_second_version (int[] givenArray, int start, int end, int pivotIndex) {
int pivot = givenArray[pivotIndex];
int left = start;
int right = end;
while (left <= right) {
while (givenArray[left] < pivot) left ++;
while (givenArray[right] > pivot) right --;
if (left <= right) {
// Exchange givenArray[left] and givenArray[right].
exchange(givenArray, left, right);
left ++;
right --;
}
}
return left;
}
And the findKthMin_RanP_Helper should be changed like this:
private static int findKthMin_RanP_Helper (int[] givenArray, int start, int end, int k) {
if (start > end) return -1;
// Generate a random num in the range[start, end].
int rand = start + (int)(Math.random() * ((end - start) + 1));
// Using this random num as the pivot index to partition the array in the current scope.
int split = partition_second_version (givenArray, start, end, rand);
if (k == split) return givenArray[split - 1];
else if (k < split) return findKthMin_RanP_Helper(givenArray, start, split - 1, k);
else return findKthMin_RanP_Helper(givenArray, split, end, k);
}
Your partition routine could be simplified...
private static int partition(int[] givenArray, int start, int end, int pivotIndex) {
final int pivot = givenArray[pivotIndex];
int left = start;
int right = end;
while (left < right) {
while (left < givenArray.length && givenArray[left] <= pivot) {
left++;
}
while (right > -1 && givenArray[right] > pivot) {
right--;
}
if (left >= right) {
break;
}
exchange(givenArray, right, left);
}
return right;
}
The one bug I see in your code is your partition routine. In the first exchange call, it is not guaranteed that the right index will always point to a value which is < pivot.

Cant get my mergeSort working after several hours

*Hey. So i got a problem with my mergeSorting. I have tried different approaches and methods but cant get it to work. I understand the principle of the mergeSorting so no problem there.
This is my my methods:
public static void TopDownMergeSort(int[] left, int[] right, int n){
TopDownSplitMerge(left, 0, n, right);
}
public static void CopyArray(int[] right, int start, int end, int[] left){
for (int i = start;i < end; i++){
right[i] = left[i];
}
}
public static void TopDownSplitMerge(int[] left, int start, int end, int[] right){
if (end - start < 2){
int middle = (end + start)/2;
TopDownSplitMerge(left, start, middle, right);
TopDownSplitMerge(left, middle, end, right);
TopDownMerge(left, start, middle, end, right);
CopyArray(right, start, end, left);
}
}
public static void TopDownMerge(int[]left, int start, int middle, int end, int[]right){
int i1 = start, i2 = middle;
for (int i = start; i < end; i++){
if (i1 < middle && (i2 >= end || left[i1] <= left[i2])){
right[i] = left[i1++];
}
else {
right[i] = left[i2++];
}
}
}
public static int[] mergeSort(int[] in) {
int[] arr = in.clone();
int[] temp = in.clone();
TopDownSplitMerge(arr,0,arr.length,temp);
return arr;
}
And this is how i test mergeSort.
int[] list = {2,5,8,6,9,7,3,4};
System.out.println("Before mergesort: "+Arrays.toString(list));
int[] ne = SortingAlgorithms.mergeSort(list);
System.out.println("After mergesort: "+Arrays.toString(ne));
if (end - start < 2)
is wrong. It should be
if (end - start > 2)
Some tips:
CopyArray can be replaced by System.arraycopy... Also rethink the: if (end - start < 2)
Instead of fix the code, I recommend you to check the book Introduction to Algorithms by Thomas H. Cornmen

Categories

Resources