I have to make a 3 way merge sort of an array. the array length is a in a power of 3, i.e. 3,9,27 etc. So I can use only one split function and not "left","mid","right".
Would like to get an answer how to repair it and why does not it work.
I have written the code, however don't know how to get it to work.
Here it is:
EDITED THE CODE, STILL DOES NOT WORK
public class Ex3 {
public static void main(String[] args) { //main function
Scanner in = new Scanner(System.in); //scanner
int size = in.nextInt();
int[] arr = new int[size];
for (int i = 0; i<arr.length; i++){
arr[i] = in.nextInt();
}
in.close();
arr = merge3sort (arr); //send to the function to merge
for (int i = 0; i<arr.length; i++){ //printer
System.out.print(arr[i]+ " ");
}
}
static int[] split(int[] m, int thirdNum) { //split function that splits to 3 arrays
int third[] = new int[m.length/3];
int third1[]=new int[m.length/3];
int third2[]=new int[m.length/3];
for(int i = 0; i<=m.length/3; i++)
third[i]=m[i];
for(int i=0; i<=m.length/3;i++)
third1[i]=m[i+thirdNum];
for(int i=0; i<=m.length/3;i++)
third2[i]=m[i+2*thirdNum];
return merge(third,third1,third2);
//return null;
}
static int minOf3(int[] a3) { //function that finds out how what is the index of the smallest number
int num0 = a3[0];
int num1 = a3[1];
int num2 = a3[2];
int idx = 0;
if(num0<num1 && num1<num2)
idx=0;
if(num1<num0 && num0<num2)
idx=1;
else
idx=2;
return idx;
}
static int[] merge(int[] th0, int[] th1, int[] th2) { //function that sorts the numbers between 3 arrays
int len0=th0.length;
int len1=th1.length;
int len2=th2.length;
int[] united = new int[len0+len1+len2];
int ind = 0; int i0=0; int i1=0; int i2=0;
while(i0<len0 && i1<len1 && i2<len2){
if(th0[i0]<th1[i1]){
if(th0[i0]<th2[i2]){
united[ind]=th0[i0];
i0=i0+1;
}//end inner if
else{
united[ind]=th2[i2];
i2=i2+1;
}//end inner else
}//end outer if
else{
united[ind]=th1[i1];
i1=i1+1;
}//end outer else
ind=ind+1;
}//end while
for (int i = i0; i < len0; i = i + 1) {
united[ind] = th0[i];
ind = ind + 1;
}
for (int i = i1; i < len1; i = i + 1) {
united[ind] = th1[i];
ind = ind + 1;
}for (int i = i2; i < len2; i = i + 1) {
united[ind] = th2[i];
ind = ind + 1;
}
return united;
}
static int[] merge3sort(int[] m) { //function that glues all together
if (m.length == 1) {
return m;
}
else{
return merge(merge3sort(split(m,m.length/3)),merge3sort(split(m,m.length/3)),merge3sort(split(m,m.length/3))); }
}
I get the following exception:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at ololosh1.Ex3.split(Ex3.java:27)
at ololosh1.Ex3.merge3sort(Ex3.java:98)
at ololosh1.Ex3.main(Ex3.java:15)
Look at this part of your code:
for(int i = 0; i<=m.length/3; i++)
third[i]=m[i];
for(int i=0; i<=m.length/3;i++)
third1[i]=m[i+thirdNum];
for(int i=0; i<=m.length/3;i++)
third2[i]=m[i+2*thirdNum];
Arrays are indexed from 0 to length-1. Each third* array has length m.length/3. Therefore their index can only go up to m.length/3 - 1. Yet you are indexing up to and including m.length/3.
Once you get your application working correctly, you really should clean it up. There is a lot of redundancy. For example, you are using the expression m.length/3 multiple times in method split() but you are also passing that same value to it as an argument.
Related
For school, i have to build myself a method in java that compresses an array using RLE(run-length encoding). I can't find a solution online because my teacher wants me to solve the problem myself. I, unfortunately, cannot do this for i am a busy man with some busy plans.
RLE turns this: {1,1,1,1,2,2,3,3,6,6,6,7,8,8,8}
into this: {4,1,2,2,2,3,3,6,1,7,3,8}
it basically makes a new array that follows this formula {# of this value, this value, # of this value, this value, cont...} there are 4 1's so {4,1} you get my drift.
Here is what i tried to do(forgive me for my crappy code, i am merely a high school student):
public class tester{
public static void main(String[] args){
int[] potato = {1,1,1,2,2,4,4,4,6,6,6,6};
printArray(compress(potato));
}
public static void printArray(int[] arr){
for(int i = 0; i < arr.length; i++){
System.out.println(arr[i]);
}
}
public static int[] compress(int[] a) {
//figure out how many different numbers there are.
int diffNums = 1;
for(int i = 0; i < a.length; i++){
if(i != a.length-1 && a[i] != a[i+1]){
diffNums++;
}
}
//make compressed array at the correct length.
int[] compressed = new int[diffNums * 2];
//figure out what each number is.
int[] nums = new int[diffNums];
nums[0] = a[0];
int spot = 0;
for(int i = 0; i < a.length; i++){
if(i != a.length-1 && a[i] != a[i+1]){
nums[spot] = a[i+1];
}
}
//figure out quantity of each number.
int[] quantities = new int[diffNums];
int spot2 = 0;
int spotcur = 0;
for(int i = 0; i < diffNums; i++){
int quant = 0;
while(a[spotcur] == a[spot2]){
quant++;
spotcur++;
}
spot2 = spotcur;
quantities[i] = quant;
}
//add them together and return compressed array
int spotter = 0;
for(int i = 0; i < diffNums; i++){
compressed[spotter] = quantities[i];
spotter++;
compressed[spotter] = nums[i];
spotter++;
}
return compressed;
}
}
Does anyone know how i can fix this crappy code? i am stuck on it
I think this problem could be solved with a lot less code. You could use an outer/inner loop construct something like the following:
public static int[] compress(int[] a) {
List<Integer> encoded = new ArrayList<>();
for (int i=0; i<a.length; i++) {
int num = a[i];
int count = 1;
for (int j=i+1; j<a.length; j++) {
int nextNum = a[j];
if (nextNum != num)
break;
count++;
i++;
}
encoded.add(count);
encoded.add(num);
}
return encoded.stream().mapToInt(i->i).toArray();
}
Also, the Arrays class contains a useful toString method already defined.
System.out.println(Arrays.toString(compress(potato)));
so when I go to compile this Eclipse says, that the numbers for Insertionct and Shakerct are 0 and prints out a tie. I know for a fact that both methods are sorting correctly, but for some reason it doesn't return the amount of comparisons that they are making to main in order to decide which one sorted the array faster. Thanks for any help in advance.
import java.io.*;
import java.util.*;
public class Sorts {
private static Scanner in;
public static void main(String[] args) throws Exception {
in = new Scanner(System.in);
System.out.print("How many strings will you be entering? ");
int sz = Integer.parseInt (in.nextLine());
String[] A = new String[sz];
String[] B = new String[sz];
for (int i = 0; i < sz; i++){
System.out.print ("Enter String #"+(i+1)+": ");
A[i] = in.nextLine();// sets the array at i equal to a string
B[i] = A[i]; // sets array B to the same as array A so I can use it in the shaker sort method
}
int Insertionct = 0;
int Shakerct = 0;
System.out.println(Insertionct);
System.out.println(Shakerct);
if (Shakerct > Insertionct) {
System.out.println("Insertion Sort was faster!");
} else if (Shakerct < Insertionct) {
System.out.println("Shaker Sort was faster!");
} else {
System.out.println("It was a tie");
}
}
public static int InsertionSort (int Insertionct, String[] A) throws Exception { //sorts the array of strings with the insertion sort.
// initializes the count variable
int sz = A.length; // sets size equal toe array A
for (int i = 0; i < sz-1; i++)
for (int j = i; j >= 0 && A[j].compareTo (A[j+1]) > 0; j--) {
Insertionct++;
String t = A[j]; //switch A[j], A[j+1]
A[j] = A[j+1];
A[j+1] = t;
}
return Insertionct;
}
public static int ShakerSort (int Shakerct, String[] B) throws Exception {//Uses the ShakerSort in order to order the array.
int sz = B.length;
for (int i = 0; i < sz; i++){
int nsct = 0;
for(int j = nsct+sz-1; j > i; j--){//runs through the array backwards and then swaps if it needs to
Shakerct++;
if (B[j].compareTo(B[j-1]) < 0) {
nsct = 0;
String t = B[j];
B[j] = B[j-1];
B[j-1] = t;
} else {
nsct++; // if no swap happens it increases no swap to increment the starting points.
}
}
for (int j = nsct; j > sz-i-1; j++){
if (B[j].compareTo(B[j+1]) > 0){//runs through the array going forward swaps if needed
Shakerct++;
nsct = 0;
String t = B[j];
B[j] = B[j+1];
B[j+1] = t;
} else {
nsct++;// increases no-swap count if no swap happens and changes the starting point.
}
}
}
return Shakerct;
}
}
You don't call InsertionSort and ShakerSort in main.
I have created my version of the merge sort algorithm in java code. My issues are these: when I run the code as is, I get a NullPointerExecpetion in the main on line 27 (see commented line). And I know there is way to make the method calls and instantiate newArray without them being static but Im not quite sure how.. can someone help fix these? I am still relatively new to java so be nice :)
Main:
import java.util.Random;
public class MergeSort_main
{
public static void main(String[] args)
{
int[] originalArray = new int[1000];
Random rand = new Random();
for (int i = 0; i < originalArray.length; i++)
{
int randNum = rand.nextInt(1000)+1;
originalArray[i] = randNum;
}
for(int i = 0; i < originalArray.length; i++)
{
System.out.println(i+"." + originalArray[i]);
}
System.out.println("---------------------End Random Array-------\n");
MergeSortAlgorithm.mergeSortAlg(originalArray);
int[] sortedArray = MergeSortAlgorithm.getSortedArray();
for(int i = 0; i < sortedArray.length; i++) //NULL POINTER EXCEPTION HERE
{
System.out.println(i+ "." + sortedArray[i]);
}
}
}
Algorithm Class:
public class MergeSortAlgorithm
{
private static int[] newArray;
public static void mergeSortAlg(int[] randomNums)
{
int size = randomNums.length;
if (size < 2)
{
return; //if the array can not be split up further, stop attempting to split.
}
int half = size / 2;
int firstHalfNums = half;
int secondHalfNums = size - half;
int[] firstArray = new int[firstHalfNums];
int[] secondArray = new int[secondHalfNums];
for (int i = 0; i < half; i++)
{
firstArray[i] = randomNums[i];
}
for (int i = half; i < size; i++)
{
secondArray[i - half] = randomNums[i];
}
mergeSortAlg(firstArray);
mergeSortAlg(secondArray);
merge(firstArray, secondArray, randomNums);
}
public static void merge(int[] firstArray, int[] secondArray, int[] newArray)
{
int firstHalfNums = firstArray.length;
int secondHalfNums = secondArray.length;
int i = 0; //iterator for firstArray
int j = 0; //iterator for second array
int k = 0; //interator for randomNums array
while (i < firstHalfNums && j < secondHalfNums)
{
if (firstArray[i] <= secondArray[j])
{
newArray[k] = firstArray[i];
i++;
k++;
}
else
{
newArray[k] = secondArray[j];
k++;
j++;
}
}
while (i < firstHalfNums)
{
newArray[k] = firstArray[i];
k++;
i++;
}
while (j < firstHalfNums)
{
newArray[k] = secondArray[j];
k++;
j++;
}
}
public static int[] getSortedArray()
{
return newArray;
}
}
Basically, the only problem with your code is that you don't initialize newArray with any values, resulting in a null.
You are also redefining newArray at the top of your merge function .
The problem is that newArray[] is never instantiated i.e. newArray reference is pointing to null. And, no change is made in the newArray so value or reference returned to main is null. And, then you are performing sortedArray.length where sorted array having a null value.
You have to make newArray[] point to randomNums[].
Below is my code for the merge sort algorithm in java. It takes a string and an int array because I need to sort a string array with the int array. This implementation also counts inversions. My issue is that it's counting inversions fine, but when I print out the arrays themselves, it hasn't been changed at all.
the main method is me testing a 6 long array and printing out the inversions and arrays. when i run this test i get the following printed out.
4
1, 3, 4, 6, 2, 5
1, 3, 4, 6, 2, 5
public class Test {
private static int[] intSorted;
private static String[] stringSorted;
public static void main(String[] args) {
//Creates new string to sort
String[] string3 = {"1","3","4","6","2","5"};
//Creates new int to sort
int[] intt3 = {1,3,4,6,2,5};
//Calls sortAndCount on int and prints the number of inversions
System.out.println(sortAndCount(intt3, string3));
//Turns the int array into a string to print
StringBuilder intBuild = new StringBuilder();
for(int i = 0; i < intSorted.length; i++){
if(i+1 == intSorted.length){
intBuild.append(intSorted[i]);
}
else{
intBuild.append(intSorted[i] + ", ");
}
}
//Turns the string array into a string to print
StringBuilder stringBuild = new StringBuilder();
for(int i = 0; i < stringSorted.length; i++){
if(i+1 == stringSorted.length){
stringBuild.append(stringSorted[i]);
}
else{
stringBuild.append(stringSorted[i] + ", ");
}
}
System.out.println(intBuild);
System.out.println(stringBuild);
}
private static int sortAndCount(int intToSort[], String stringToSort[]){
int inversionsLeft;
int inversionsRight;
int inversionsMerged;
if(intToSort.length == 1){
return 0;
}
int m = intToSort.length/2;
int[] intLeft = new int[m];
String[] stringLeft = new String[m];
int[] intRight = new int[intToSort.length-m];
String[] stringRight = new String[intToSort.length-m];
for (int i=0; i < m; i++){
intLeft[i] = intToSort[i];
stringLeft[i] = stringToSort[i];
}
for (int i = 0;i < intRight.length; i++){
intRight[i] = intToSort[m+i];
stringRight[i] = stringToSort[m+i];
}
inversionsLeft = sortAndCount(intLeft, stringLeft);
inversionsRight = sortAndCount(intRight, stringRight);
intSorted = new int[intToSort.length];
stringSorted = new String[stringToSort.length];
inversionsMerged = mergeAndCount(intLeft, intRight, stringLeft, stringRight);
return(inversionsLeft + inversionsRight + inversionsMerged);
}
private static int mergeAndCount(int[] intLeft, int[] intRight, String[] stringLeft, String[] stringRight){
int count = 0;
int i = 0;
int j = 0;
int k = 0;
while(i < intLeft.length && j < intRight.length){
if(intLeft[i] < intRight[j]){
intSorted[k] = intLeft[i];
stringSorted[k] = stringLeft[i];
i++;
}
else{
intSorted[k] = intRight[j];
stringSorted[k] = stringRight[j];
count += intLeft.length - i + 1;
j++;
}
k++;
}
while (i < intLeft.length)
{
intSorted[k] = intLeft[i];
stringSorted[k] = stringLeft[i];
k++;
i++;
}
while (j < intRight.length)
{
intSorted[k] = intRight[j];
stringSorted[k] = stringRight[j];
j++;
k++;
}
return count;
}
I think the problem is here (comments added by me):
// Create some arrays into which we write the result of merging the
// arrays intLeft, intRight, stringLeft, stringRight.
intSorted = new int[intToSort.length];
stringSorted = new String[stringToSort.length];
// Do the merging into intSorted and stringSorted.
inversionsMerged = mergeAndCount(intLeft, intRight, stringLeft, stringRight);
// Oops... we haven't updated intToSort and stringToSort!
// We need to copy the sorted values from intSorted and stringSorted
// back into intToSort and stringToSort before we return.
return(inversionsLeft + inversionsRight + inversionsMerged);
I'll leave it up to you to fill in the gap.
I took your code, filled in the gap myself, and ran it. It seemed to work; this was the output I got:
7
1, 2, 3, 4, 5, 6
1, 2, 3, 4, 5, 6
Good luck!
Well the reason that your arrays don't get sorted is that your recursive algorithm keeps recreating the intSorted [] and stringSorted [] with each invocation.
Also your recursive method just returns an int (the number of inversions performed). In order of the recursive approach to work each sortAndCount must return it's piece of the array sorted. This makes it difficult to attempt to sort two different arrays in the same algorithm.
I have made a few minor tweaks to your code and now it sorts the int[] correctly.
If you want to count inversions at the same time that you sort, I would suggest adding a passByReference to a Counter object that does nothing but count inversions (like a visitor pattern).
Here is my code:
public class Test {
private static int[] intSorted;
public static void main(String[] args) {
//Creates new string to sort
//Creates new int to sort
int[] intt3 = {1,3,4,6,2,5};
//Calls sortAndCount on int and prints the number of inversions
System.out.println(sortAndCount(intt3));
//Turns the int array into a string to print
StringBuilder intBuild = new StringBuilder();
for(int i = 0; i < intSorted.length; i++){
if(i+1 == intSorted.length){
intBuild.append(intSorted[i]);
}
else{
intBuild.append(intSorted[i] + ", ");
}
}
//Turns the string array into a string to print
System.out.println(intBuild);
}
private static int[] sortAndCount(int intToSort[]){
int inversionsLeft;
int inversionsRight;
int inversionsMerged;
if(intToSort.length == 1){
return intToSort;
}
int m = intToSort.length/2;
int[] intLeft = new int[m];
String[] stringLeft = new String[m];
int[] intRight = new int[intToSort.length-m];
String[] stringRight = new String[intToSort.length-m];
for (int i=0; i < m; i++){
intLeft[i] = intToSort[i];
}
for (int i = 0;i < intRight.length; i++){
intRight[i] = intToSort[m+i];
}
intLeft = sortAndCount(intLeft);
intRight = sortAndCount(intRight);
intSorted = new int[intToSort.length];
intSorted = mergeAndCount(intLeft, intRight);
return intSorted;
}
private static int[] mergeAndCount(int[] intLeft, int[] intRight){
int count = 0;
int i = 0;
int j = 0;
int k = 0;
while(i < intLeft.length && j < intRight.length){
if(intLeft[i] < intRight[j]){
intSorted[k] = intLeft[i];
i++;
}
else{
intSorted[k] = intRight[j];
count += intLeft.length - i + 1;
j++;
}
k++;
}
while (i < intLeft.length)
{
intSorted[k] = intLeft[i];
k++;
i++;
}
while (j < intRight.length)
{
intSorted[k] = intRight[j];
j++;
k++;
}
return intSorted;
}
}
public class AssignmentChapter8
{
public static void main(String[] args)
{
int randomNumbers = new int[100];
int counter = 0;
while(counter < randomNumbers.length)
{
randomNumbers[counter] = (int)(Math.random() * 25);
counter++;
}
int oddNumbers[] = new int[100];
oddNumbers[] = getOddNumbers(randomNumbers);
int evenNumbers[] = new int[100];
evenNumbers[] = getEvenNumbers(randomNumbers);
System.out.println("The odd numbers are:");
for(int k = 0; k < oddNumbers.length; k++)
System.out.print("\t" + oddNumbers[k]);
System.out.println("The even numbers are:");
for(int l = 0; l < evenNumbers.length; l++)
System.out.print("\t" + evenNumbers[l]);
}
public static int getOddNumbers(int randomNumbers)
{
int oddNumbers[] = new int[100];
int counterA = 0;
int counterB = 0;
int counter = 0;
int placeholder;
while(counter < randomNumbers.length)
{
if(randomNumbers[counterA] % 2 > 0)
{
oddNumbers[counterB] = randomNumbers[counterA];
counterB++;
}
counterA++;
counter++;
}
return oddNumbers;
}
public static int getEvenNumbers(int randomNumbers)
{
int evenNumbers[] = new int[100];
int counterA = 0;
int counterB = 0;
int counter = 0;
int placeholder;
while(counter < randomNumbers.length)
{
if(randomNumbers[counterA] % 2 > 0)
{
evenNumbers[counterB] = randomNumbers[counterA];
counterB++;
}
counterA++;
counter++;
}
return evenNumbers;
}
}
I have been trying to execute a program to sort variables in arrays, but I keep getting a ';' expected error in the line after declaration of the array where the program is supposed to retrieve an array from a function. Any help would be appreciated.
This is bad syntax (which causes the ';' expected error ):
oddNumbers[] = getOddNumbers(randomNumbers);
The brackets are not needed. You can do this:
oddNumbers = getOddNumbers(randomNumbers);
Besides that, you have plenty of errors:
int randomNumbers[] = new int[100]; // you need the brackets
Your return value in the method declaration is wrong (you are returning an array, not an int):
public static int[] getEvenNumbers(int randomNumbers)
int oddNumbers[] = new int[100];
By initializing oddNumbers become an array. when you want to assign values,
oddNumbers={elements of array}
Both left and right hand side both should arrays.
May be you should use IDE for coding then it may help you to understand some issues like this.