java mergesort count homework - java

I am working on getting the counts of comparisons and movers when merge sorting. I think I have the recursion I need thanks to this Sort Comparisons Counter but I can not get it to print out. I am obviously very new at programming so I'd be appreciative if you could explain what it is that I am missing.
import java.util.Arrays;
public class MergeSort {
int count = 0;
/**
* #param args
*/
// Rearranges the elements of a into sorted order using
// the merge sort algorithm (recursive).
public int mergeSort(int[] a, int howMany) {
if (a.length >= 2) {
// split array into two halves
int[] left = Arrays.copyOfRange(a, 0, a.length/2);
int[] right = Arrays.copyOfRange(a, a.length/2, a.length);
// sort the two halves
howMany = mergeSort(left,howMany);
howMany = mergeSort(right, howMany);
// merge the sorted halves into a sorted whole
howMany = merge ( left, right, a, howMany);
}
return howMany;
}
// Merges the left/right elements into a sorted result.
// Precondition: left/right are sorted
public static int merge(int[] result, int[] left,
int[] right, int howMany) {
int i1 = 0; // index into left array
int i2 = 0; // index into right array
for (int i = 0; i < result.length; i++) {
if (i2 >= right.length ||
(i1 < left.length && left[i1] <= right[i2])) {
result[i] = left[i1]; // take from left
i1++;
} else {
result[i] = right[i2]; // take from right
i2++;
}
}
return howMany;
}
System.out.println(howMany); // ???
}

you need to call the method through its object wherever you wanna print. something like this (may be in your main method):
MergeSort mObj - new MergeSort();
int[] array = {1,2,3};
int count = mObj.mergeSort(array, 2);
System.out.println(count);

Basically, you need a driver method. When a java class is run, it will look for a public static void main(String[] args) method; if this method doesn't exist, nothing will happen. With what you have now, you should actually get a compile error from System.out.println(howMany); since the variable howMany only exists within the scope (brackets) of the merge method. To understand this better I'd review your notes on variable and method scope and class members. For a quick fix, remove the line at the bottom that I mentioned above, and place this method somewhere in your class:
public static void main(String[] args) {
int[] array = {2,5,8,1,3};
int howMany = mergeSort(array, 5);
System.out.println(howMany);
}
You also need to make your mergeSort method static, so change its definition to
public **static** int mergeSort(int[] a, int howMany)
I tested your code and I'm pretty sure that it doesn't give the answer you want, so be sure to check that. Best of luck learning object oriented programming!

Related

Sort object in ArrayList using Quick Sort without Comparable

I am trying to sort an object within an ArrayList in descending order using Quick Sort. I don't want to use the Comparable interface that java provides for classes. In the object, there is an average method, in the Team class, that I'd like to use to sort the objects by.
Below I have a Bubble Sort algorithm that I implemented within the main method, and it ended up working fine. The reason that I've gotten this to work rather than the Quick Sort is that it requires methods like partition and sort, for example. The primary issue that I am having is accessing the methods that I need from the Team class into the BubbleSort class. I have tried BubbleSort extends Team, but then the issue that I run into is it requires me to feed arguments to the BubbleSort class that originated from the Team class. Is there a way around me supplying those arguments in? What other approaches can I take?
for (int i = 0; i < team.size() - 1; i++) {
for (int j = 0; j < team.size() - i - 1; j++) {
if (team.get(j).getAverage() < team.get(j + 1).getAverage()) {
Team temp = team.get(j);
team.set(j, team.get(j + 1));
team.set(j + 1, temp);
}
}
}
Here is a repl.it of the program thus far.
You can use Comparator for custom sorting which is what you want by comparing getAverage() methods
Check out this QuickSort implementation: https://pdfbox.apache.org/docs/1.8.13/javadocs/org/apache/pdfbox/util/QuickSort.html
It takes list and Comparator as parameters for sorting. You could just use that.
QuickSort.sort(team, (t1, t2) -> Double.compare(t1.getAverage(), t2.getAverage());
I think this is the logic you are looking for, go through the code , have commented what you need to modify!! note that it sorts item in ascending order!!
public class QuickSort
{
int[] nums = null; //this should be the arrayList of Team class in your case, say ArrayList<Team>() teams = null;
/*this piece of code can be any where in your project, just placed it here in main function so that you could easily compile and run it*/
public static void main(String[] args)
{
int[] nums = {1,5,9,2,7,8,4,2,5,8,9,12,35,21,34,22,1,45};
QuickSort qs = new QuickSort(nums);
qs.quickSort(0,nums.length-1);
qs.print();
}
QuickSort(int[] nums)//this should be the arrayList of Team class in your case, say ArrayList<Team>() teams
{
this.nums = nums;
}
/**
* left and right are indices in array whereas
* pivot is one of the values stored in array; in your case,it should be averageValue of Team stored in the arrayList
* also, nums[leftIndex],nums[rightIndex],nums[right] should be replaced by
* teams.get(leftIndex).getAverage(),teams.get(rightIndex).getAverage(),teams.get(right).getAverage!!
*/
int partition(int left, int right , int pivot)
{
int leftIndex = left -1;
int rightIndex = right;
int temp = 0;
while(true)
{
while( nums[++leftIndex] < pivot );
while( rightIndex>0 && nums[--rightIndex] > pivot );
if( leftIndex >= rightIndex ) break;
else//swap value at leftIndex and rightIndex
{
temp = nums[leftIndex];
nums[leftIndex]= nums[rightIndex];
nums[rightIndex] = temp;
}
}
//swap value at leftIndex and initial right index
temp = nums[leftIndex];
nums[leftIndex]= nums[right];
nums[right] = temp;
return leftIndex;
}
void quickSort( int leftIndex , int rightIndex)
{
if( rightIndex-leftIndex <= 0 ) return;
else
{
int pivot = nums[rightIndex];
int partitionIndex = partition(leftIndex, rightIndex , pivot);
quickSort(leftIndex,partitionIndex-1);
quickSort(partitionIndex+1,rightIndex);
}
}
void print()
{
for( int i = 0 ; i < nums.length ; i++ )
{
System.out.print(nums[i]+", ");
}
}
}

Why my java program is showing StackOverflowError?

I have written a program to sort elements of an array based on the principle of quicksort. So what the program does is that it accepts an array, assumes the first element as the pivot and then compares it with rest of the elements of the array. If the element found greater then it will store at the last of another identical array(say b) and if the element is less than the smaller than it puts that element at the beginning of the array b. in this way the pivot will find its way to the middle of the array where the elements that are on the left-hand side are smaller and at the right-hand side are greater than the pivot. Then the elements of array b are copied to the main array and this whole function is called via recursion. This is the required code.
package sorting;
import java.util.*;
public class AshishSort_Splitting {
private static Scanner dogra;
public static void main(String[] args)
{
dogra=new Scanner(System.in);
System.out.print("Enter the number of elements ");
int n=dogra.nextInt();
int[] a=new int[n];
for(int i=n-1;i>=0;i--)
{
a[i]=i;
}
int start=0;
int end=n-1;
ashishSort(a,start,end);
for(int i=0;i<n;i++)
{
System.out.print(+a[i]+"\n");
}
}
static void ashishSort(int[]a,int start,int end)
{
int p;
if(start<end)
{
p=ashishPartion(a,start,end);
ashishSort(a,start,p-1);
ashishSort(a,p+1,end);
}
}
public static int ashishPartion(int[] a,int start,int end)
{
int n=start+end+1;
int[] b=new int[n];
int j=start;
int k=end;
int equal=a[start];
for(int i=start+1;i<=end;i++)
{
if(a[i]<equal)
{
b[j]=a[i];
j++;
}
else if(a[i]>equal)
{
b[k]=a[i];
k--;
}
}
b[j]=equal;
for(int l=0;l<=end;l++)
{
a[l]=b[l];
}
return j;
}
}
this code works fine when I enter the value of n up to 13930, but after that, it shows
Exception in thread "main" java.lang.StackOverflowError
at sorting.AshishSort_Splitting.ashishSort(AshishSort_Splitting.java:28)
at sorting.AshishSort_Splitting.ashishSort(AshishSort_Splitting.java:29)
I know the fact the error caused due to bad recursion but I tested my code multiple times and didn't find any better alternative. please help. thanks in advance.
EDIT: can someone suggest a way to overcome this.
I see perfrmance issues first. I see in your partition method:
int n = start+end+1
Right there, if the method was called on an int[1000] with start=900 and end=999, you are allocating an int[1900]... Not intended, I think...!
If you are really going to trash memory instead of an in-place partitioning,
assume
int n = end-start+1
instead for a much smaller allocation, and j and k indexes b[], they would be j=0 and k=n, and return start + j.
Second, your
else if(a[i]<equal)
is not necessary and causes a bug. A simple else suffice. If you don't replace the 0's in b[j..k] you'll be in trouble when you refill a[].
Finally, your final copy is bogus, from [0 to end] is beyond the bounds of the invocation [start..end], AND most importantly, there is usually nothing of interest in b[nearby 0] with your b[] as it is. The zone of b[] (in your version) is [start..end] (in my suggested version it would be [0..n-1])
Here is my version, but it still has the O(n) stack problem that was mentioned in the comments.
public static int ashishPartion(int[] a, int start, int end) {
int n = end-start + 1;
int[] b = new int[n];
int bj = 0;
int bk = n-1;
int pivot = a[start];
for (int i = start + 1; i <= end; i++) {
if (a[i] < pivot) {
b[bj++] = a[i];
} else {
b[bk--] = a[i];
}
}
b[bj] = pivot;
System.arraycopy(b, 0, a, start, n);
return start+bj;
}
If you are free to choose a sorting algo, then a mergesort would be more uniform on performance, with logN stack depth. Easy to implement.
Otherwise, you will have to de-recurse your algo, using a manual stack and that is a nice homework that I won't do for you... LOL

Write a recursive method called which takes in an array of integers and returns said array in reversed sorted order

I have a programming exam in a few days so I'm doing some exercises just to practice. However, I've been stuck with this problem and I started to doubt if it's possible to do it. Write a recursive method called arrayReverse which takes in an array of integers and returns said array in reversed sorted order. So an example would be:
input: [1,2,3]
output:[3,2,1]
I wasn't able to solve it. My intuition was to take the last element of the array, put it at the beginning, i,e: index[0] and then recursively call the rest of the array but then taking the new last element and put it on index[1]. Unfortunately, the implementation was harder than I thought but I (for the sake of trying) edited the question in a way that it accepts 2 arrays and this was my code:
import java.util.Arrays;
class Test {
int[] arrayReverse(int[] m, int[] mReverse) {
if (m.length == 1) {
mReverse[mReverse.length - 1] = m[0];
return mReverse;
} else {
int lastNum = m[m.length - 1];
mReverse[mReverse.length - m.length] = lastNum;
int[] arrayMinusOne = cropArray(m);
return arrayReverse(arrayMinusOne, mReverse);
}
}
int[] cropArray(int[] m) {
int[] mCropped = new int[m.length - 1];
for (int i = 0; i < m.length - 1; i++) {
mCropped[i] = m[i];
}
return mCropped;
}
}
void demo() {
int[] helpTest4 = new int[]{1, 2, 3};
int[] emptyArray = new int[helpTest4.length];
int[] test4 = arrayReverse(helpTest4, emptyArray);
System.out.println(Arrays.toString(test4));
}
public static void main(String[] args) {
new Test().demo();
}
}
It works perfectly but I'm not satisfied with the result because of two reasons:
I wasn't able to do it completely recursive. I used a for loop in cropArray.
I couldn't do it on one array.
How can this be done?
Option1: Using only one parameter (array) in the recursive function
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
public class MyClass {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
int[] reversed = reverseArray(arr);
System.out.println(Arrays.toString(reversed));
}
public static int[] reverseArray(int[] arr)
{
if (arr.length == 0)
return arr;
// remove first element
int first = arr[0];
int[] list = Arrays.copyOfRange(arr, 1, arr.length);
//Calling Function Recursively get reversed array
int[] returnArr = reverseArray(list);
//Add original first to the last of the arrayToReturn
returnArr = Arrays.copyOf(returnArr, returnArr.length + 1);
returnArr[returnArr.length - 1] = first;
return returnArr;
}
}
Option2:
void reverseArray(int[] x){
reverse(x, 0, x.length -1);
}
void reverse(int[] x, int i, int j){
if(i<j){//Swap ith with jth element where i and j are equidistant from ends
int tmp = x[i];
x[i] = x[j];
x[j] = tmp;
reverse(x, ++i, --j);//Recursive
}
}
Test:
int[] s = new int[]{1,2,3,4,5};
reverseArray(s);
System.out.println(Arrays.toString(s));//"5,4,3,2,1"
Recursive, O(n), no temporary Array needed.
Please try the code below:
import java.util.*;
public class HelloWorld{
public static void main(String []args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int arr[]= new int[n];
for(int i=0;i<n;i++)
{
arr[i] = sc.nextInt();
}
Printsum(arr,0);
}
public static void Printsum(int arr[], int idx)
{
if(idx == arr.length)
return ;
Printsum(arr,idx+1);
System.out.println(arr[idx]);
}
}
I don't think this is a particularly good question - there is obviously a direct and clear way to do it without recursion; so the question does little to demonstrate any useful knowledge of recursion.
That said I believe the algorithm they were seeking uses the facts that:
a) reversing a 1 length array is trivial
b) you can reverse an n length array by appending the first element to the reverse the the last n-1 elements.
So code for this solution will look much simpler that what you currently have.
Ruby:
def reverse(a)
if a.empty?
return []
else
return [a.last] + reverse(a[0..-2])
end
end
a = [1, 2, 3]
reverse(a)
Taking the request literally, I have come out with a solution which only needs ONE recursive function with just ONE input/output parameter:
public static void arrayReverse(int[] input)
{
if (input.length > 0)
{
// Store locally the fist element:
int firstElement=input[0];
// Creates a sub-array and reverses it:
int[] input2=new int[input.length - 1];
System.arraycopy(input, 1, input2, 0, input2.length);
arrayReverse(input2);
// Copies back the reversed array into the current array:
System.arraycopy(input2, 0, input, 0, input2.length);
// Puts the stored fist element in the last position:
input[input.length - 1]=firstElement;
}
}
This solution is based upon a stack structure, for which it takes advantage of the machine calling stack at runtime, where the local values are stored while the function is executing.
The base case of this recursion is, of corse, the empty array.
In the generic case, the function stores locally the first element, then re-invokes itself recursively to reverse the rest of the array, and last, puts back the first element in the last position.

Why is my bubble sort code printing out this weird stuff?

Ok, so here's my code. I think it should work fine to sort those numbers in the array. However, every time I attempt to run it, all it does is print "[I#178af9c0" or some weird variation on that. I have absolutely no idea what do about this and would appreciate any help that you can give me. Thank you very much!!!
public class BubbleSort {
public void Print(){
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] BubbleSort = {3, 4, 1, 2};
int lengthOfArray = BubbleSort.length;
for (int i = 0; i < lengthOfArray - 1; i++){
for (int n = 1; n < lengthOfArray - i; n++){
if (BubbleSort[n - 1] > BubbleSort[n]){
Swap(i, n , BubbleSort);
}
}
}
System.out.println(BubbleSort.toString());
}
private static void Swap(int index1, int index2, int[] array) {
int temp;
temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}
}
In Java, arrays are classes. So that string is the reference to the array, not the contents of the array. If you want to print the contents, probably the easiest way is to iterate over all the elements.
for(int i : BubbleSort) System.out.println(""+i);
(Tested on Java 8, twiddle for your version of Java.)
There are some logic errors in there, but as this looks like a homework question, I'll just mention that you are heading down the right lines, but may need to pencil out what you're actually doing and draw the flow.
To get a String representation of an Array, you can use Arrays.toString(yourArray);

recursion resulting in extra unwanted data

I'm writing a module to handle dice rolling. Given x die of y sides, I'm trying to come up with a list of all potential roll combinations.
This code assumes 3 die, each with 3 sides labeled 1, 2, and 3. (I realize I'm using "magic numbers" but this is just an attempt to simplify and get the base code working.)
int[] set = { 1, 1, 1 };
list = diceroll.recurse(0,0, list, set);
...
public ArrayList<Integer> recurse(int index, int i, ArrayList<Integer> list, int[] set){
if(index < 3){
// System.out.print("\n(looping on "+index+")\n");
for(int k=1;k<=3;k++){
// System.out.print("setting i"+index+" to "+k+" ");
set[index] = k;
dump(set);
recurse(index+1, i, list, set);
}
}
return list;
}
(dump() is a simple method to just display the contents of list[]. The variable i is not used at the moment.)
What I'm attempting to do is increment a list[index] by one, stepping through the entire length of the list and incrementing as I go.
This is my "best attempt" code. Here is the output:
Bold output is what I'm looking for. I can't figure out how to get rid of the rest. (This is assuming three dice, each with 3 sides. Using recursion so I can scale it up to any x dice with y sides.)
[1][1][1] [1][1][1]
[1][1][1] [1][1][2] [1][1][3] [1][2][3]
[1][2][1] [1][2][2] [1][2][3] [1][3][3]
[1][3][1] [1][3][2] [1][3][3] [2][3][3] [2][1][3]
[2][1][1] [2][1][2] [2][1][3] [2][2][3]
[2][2][1] [2][2][2] [2][2][3] [2][3][3]
[2][3][1] [2][3][2] [2][3][3] [3][3][3] [3][1][3]
[3][1][1] [3][1][2] [3][1][3] [3][2][3]
[3][2][1] [3][2][2] [3][2][3] [3][3][3]
[3][3][1] [3][3][2] [3][3][3]
I apologize for the formatting, best I could come up with.
Any help would be greatly appreciated. (This method was actually stemmed to use the data for something quite trivial, but has turned into a personal challenge. :)
edit: If there is another approach to solving this problem I'd be all ears, but I'd also like to solve my current problem and successfully use recursion for something useful.
edit2:
Running code including the "easy fix." Beware unused variables and weird hacks, I haven't cleaned it up yet.
package code.testing;
import java.util.ArrayList;
public class CodeTesting {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
int[] set = { 1, 1, 1 };
list = recurse(0,0, list, set);
}
public static ArrayList<Integer> recurse(int index, int i, ArrayList<Integer> list, int[] set){
if(index < 3){
// System.out.print("\n(looping on "+index+")\n");
for(int k=1;k<=3;k++){
// System.out.print("setting i"+index+" to "+k+" ");
set[index] = k;
if (index==2){
dump(set);
}
recurse(index+1, i, list, set);
}
}
return list;
}
static void dump(int[] arr) {
for (int s : arr) {
System.out.format("[%s]", s);
}
System.out.println();
}
}
I'm sorry I had to rewrite the code, but it's pretty much the same algorithm as yours with some corrections:
public class DiceRolls {
static void recurse(int diceNumber, int[] values, final int MAX) {
if (diceNumber == values.length) {
System.out.println(java.util.Arrays.toString(values));
} else {
for (int v = 1; v <= MAX; v++) {
values[diceNumber] = v;
recurse(diceNumber + 1, values, MAX);
}
}
}
public static void main(String[] args) {
recurse(0, new int[3], 4);
}
}
This is a standard tuplet recursive generator. If you want to add all the int[] into a List, then make sure to add(values.clone()) so they are independent int[] objects.
But what's with the extra output?
The problem is that you were dumping prematurely, before you're done throwing all the dices. In pseudocode, this is what you're doing:
if we're not done yet
trying all possibilities for this dice
dump result so far // premature dumping!
recurse for next dice
An easy fix to your code is to do the following:
if we're not done yet
trying all possibilities for this dice
recurse for next dice
else, we're done, so
dump result // timely!
So back to the Java implementation, the fix is merely moving dump(set); to an else case for the if (index < 3) statement.
Call dump() only when index == 2.
Incidentally, i and list seem unused. And the verb is "recur". :)
Here is a non-recursive alternative. Change the two constants to calculate all combinations for different dices and different numbers of dice.
package utils;
public class Dice {
private static int FACES = 3;
private static int NUMBER_OF_DICE = 3;
public static void main(String[] args) {
int start = createPair(1);
int end = createPair(FACES);
for (int i = start; i <= end; i++) {
String combination = Integer.toString(i, FACES+1);
if (combination.indexOf('0') < 0)
System.out.println(combination);
}
}
private static int createPair(int number) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < NUMBER_OF_DICE; i++) {
sb.append(number);
}
return Integer.parseInt(sb.toString(), FACES+1);
}
}

Categories