I'm stuck on the final part of my program which involves comparing two separate sorting algorithms.
I am unable to call my other two classes within my main and I'm not entirely sure why.
import java.util.Random;
import java.util.Arrays;
import java.util.Scanner;
// Implement two separate sorting classes
// Compare both classes and see how they stack up
// based off their results.
//QuickSort + BubbleSort
public class a8main{
public static void main(String[] args)
{
Scanner userInput = new Scanner(System.in);
System.out.println("Type in array size.");
System.out.println("5,000 10,000 30,000");
int input = userInput.nextInt();
//Test smaller arrays starting at 5,000
//Test larger arrays. (30,000 or more)
byte[] c = new byte[input];
new Random().nextBytes(c);
//Begin QuickSorting + BubbleSorting
for (int j=1;j<6;j++)
{
byte[] c1 = Arrays.copyOfRange(c, 0, 5000*j);
long startTime = System.currentTimeMillis();
quickSort(c1,0,5000*j-1);
long endTime = System.currentTimeMillis();
long totalTime = endTime - startTime;
byte[] c2 = Arrays.copyOfRange(c, 0, 5000*j);
startTime = System.currentTimeMillis();
bubbleSort(c2);
long endTime = System.currentTimeMillis();
long totalTime = endTime - startTime;
System.out.println("Amount of time taken for first array "+5000*j+" elements for quickSort: "+totalTime+" miliseconds.");
System.out.println("Amount of time taken for second array "+5000*j+" elements for bubbleSort: "+totalTime+" miliseconds.");
}
}
}
I've got the main code here and I'm going to include my other two classes just to give you a clue on what I'm dealing with here.
public class bubbleSort
{
static void bubbleSorter(byte[] args)
{
int n = args.length;
byte temp = 0;
for(int i=0; i < n;i++)
{
for(int j=1; j < (n-i); j++)
{
if(args[j-1] > args[j])
{
temp = args[j-1];
args[j-1] = args[j];
args[j] = temp;
}
}
}
}
}
Bubble Sort
public class quickSort
{
static void quickSorter(byte[]args,int low,int high)
{
if (args == null || args.length == 0)
return;
if (low >= high)
return;
int center = low + (high - low) / 2;
byte pivot = args[center];
int i = low, j = high;
while (i <= j)
{
while (args[i] < pivot)
{
i++;
}
while (args[j] > pivot)
{
j--;
}
}
if (low < j)
quickSorter(args, low, j);
if (high > i)
quickSorter(args, i, high);
}
}
And QuickSort
What am I doing wrong?
I just need some clues.
You need to call methods by the class name as you defined them as static methods like this
quickSort.quickSorter(parameter1,parameter2,parameter3);
bubbleSort.bubbleSorter(parameter);
You have a few issues.
First, Java recommendations are to use PascalCase for class names; for example, BubbleSort. Method names are camel case like bubbleSorter. It's way easier to read this way.
Second, you were re-declaring endTime and totalTime in your Main main() method. Take out the long before them after your bubbleSorter() method call.
Third, you should force your static classes to have a private constructor. Some people throw an exception if anyone tries to initialize the private constructor. This can only really be done within the class, so I opt to just write a comment since people could just remove the exception anyway.
Fourth, when calling static methods of a class you need to include the class of the static method. This will be way easier to read when you do the first point in this answer.
Here's what your classes could look like.
Bubble Sort Class:
public class BubbleSort
{
private BubbleSort() {
//This is a static class - no instantiation needed
}
public static void bubbleSorter(byte[] args)
{
int n = args.length;
byte temp = 0;
for (int i = 0; i < n; i++)
{
for (int j = 1; j < (n - i); j++)
{
if (args[j - 1] > args[j])
{
temp = args[j - 1];
args[j - 1] = args[j];
args[j] = temp;
}
}
}
}
}
Quick Sort Class:
public class QuickSort
{
private QuickSort() {
//This is a static class - no instantiation needed
}
public static void quickSorter(byte[]args,int low,int high)
{
if (args == null || args.length == 0)
return;
if (low >= high)
return;
int center = low + (high - low) / 2;
byte pivot = args[center];
int i = low, j = high;
while (i <= j)
{
while (args[i] < pivot)
{
i++;
}
while (args[j] > pivot)
{
j--;
}
}
if (low < j)
quickSorter(args, low, j);
if (high > i)
quickSorter(args, i, high);
}
}
Main Class:
public class Main {
public static void main(String[] args) {
Scanner userInput = new Scanner(System.in);
System.out.println("Type in array size.");
System.out.println("5,000 10,000 30,000");
int input = userInput.nextInt();
//Test smaller arrays starting at 5,000
//Test larger arrays. (30,000 or more)
byte[] c = new byte[input];
new Random().nextBytes(c);
//Begin QuickSorting + BubbleSorting
for (int j=1;j<6;j++)
{
byte[] c1 = Arrays.copyOfRange(c, 0, 5000*j);
long startTime = System.currentTimeMillis();
QuickSort.quickSorter(c1,0,5000*j-1);
long endTime = System.currentTimeMillis();
long totalTime = endTime - startTime;
byte[] c2 = Arrays.copyOfRange(c, 0, 5000*j);
startTime = System.currentTimeMillis();
BubbleSort.bubbleSorter(c2);
endTime = System.currentTimeMillis();
totalTime = endTime - startTime;
System.out.println("Amount of time taken for first array "+5000*j+" elements for quickSort: "+totalTime+" miliseconds.");
System.out.println("Amount of time taken for second array "+5000*j+" elements for bubbleSort: "+totalTime+" miliseconds.");
}
}
}
Related
I'm learning about parallel programming in Java using fork join pool. I know how it works internally and decided to write a very simple program using it to calculate the max value for a large array. However, when I ran it I found that it would take so long that the program would hang and never complete. When I just calculate the max without using parallelism though it was much faster and finished in milliseconds! Also, when I use Runtime.getRuntime().availableProcessors() my computer returns 8, so it's not like I'm using a 1 core computer that can't handle it. Can somebody tell me if they are getting similar results on their own computer? If so, can you explain what is wrong with my code, i'm very confused. Thanks.
import java.util.concurrent.*;
public class ParralleMax {
private static int numberOfCores = Runtime.getRuntime().availableProcessors();
public static void main(String[] args) {
int[] list = new int[9_000_000];
for (int i = 0; i < list.length; i++)
list[i] = i;
System.out.println("Array created. Program now starting...");
long startTime = System.currentTimeMillis();
int max = calculateMax(list);
long endTime = System.currentTimeMillis();
System.out.println("This computer has " + numberOfCores + " cores.");
System.out.println("The max value " + max + " was calculated in " + (endTime - startTime) + "
miliseconds.");
}
public static int calculateMax(int[] list) {
RecursiveTask<Integer> maxTask = new MaxTask(list, 0, list.length);
ForkJoinPool pool = new ForkJoinPool();
return pool.invoke(maxTask);
}
private static class MaxTask extends RecursiveTask<Integer> {
private final static int THRESHOLD = 1000;
private int[] list;
private int low;
private int high;
public MaxTask(int[] list, int low, int high) {
this.list = list;
this.low = low;
this.high = high;
}
#Override
public Integer compute() {
if (high - low < THRESHOLD) {
int max = list[0];
for (int i = low; i < high; i++)
if (list[i] > max)
max = list[i];
return new Integer(max);
}
else {
int mid = (high + low) / 2;
RecursiveTask left = new MaxTask(list, 0, mid);
RecursiveTask right = new MaxTask(list, mid, high);
right.fork();
left.fork();
Integer leftMax = (Integer)left.join();
Integer rightMax = (Integer)right.join();
return new Integer(Math.max(leftMax.intValue(), rightMax.intValue()));
}
}
}
}
Am I missing something? The source is short, ready to run and commented for better understanding. I need to know what I'm doing wrong.
package com.company;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
public class Main {
public static ArrayList<Integer> randomArrayList(int n)
{
ArrayList<Integer> list = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < n; i++)
{
list.add(random.nextInt(n));
}
return list;
}
public static List<Integer> MergeSort(List<Integer> A) throws Exception{
if (A.size()==1)
return A;
int mid = A.size()/2;
List<Integer> left = A.subList(0,mid);
List<Integer> right = A.subList(mid,A.size());
left = MergeSort(left);
right = MergeSort(right);
A = Merge(left,right);
return A;
}
public static List<Integer> Merge(List<Integer> L,List<Integer> R) throws Exception{
List<Integer> output = new ArrayList<Integer>(Collections.nCopies(L.size() + R.size(), 0));
int i = 0; int j = 0; int k = 0;
while (i < L.size() && j < R.size()) {
if (L.get(i) < R.get(j)) {
output.set(k, L.get(i));
i=i+1;
}
else {
output.set(k, R.get(j));
j=j+1;
}
k++;
}
while (i < L.size()) {
output.set(k, L.get(i));
i=i+1;
k++;
}
while (j < R.size()) {
output.set(k, R.get(j));
j=j+1;
k++;
}
return output;
}
public static List<Integer> QuickSort(List<Integer> A) throws Exception{
if (A.size()==1 || A.size()==0)
return A;
//The pivot is a random element of the array A
int randomIndex = new Random().nextInt(A.size());
Integer P = A.get(randomIndex);
//Swap first element of A with selected pivot
Integer tmp;
A.set(randomIndex,A.get(0));
A.set(0, P);
//Initiate i and l (partition analysis progress counters)
int l = 0, i = l + 1, r = A.size();
for (int j = l + 1; j < r; j++ ){
if (A.get(j)< P ){
//Swap A[j] and A[i]
tmp = A.get(j);
A.set(j,A.get(i));
A.set(i,tmp);
//Increase i by 1 (counting the pos of already partitioned)
i = i + 1;
}
}
//Swap A[l] (Pivot) and A[i-1] most left element bigger than pivot
tmp = A.get(l);
A.set(l,A.get(i-1));
A.set(i - 1, tmp);
QuickSort(A.subList(0,i-1));
QuickSort(A.subList(i,A.size()));
return A;
}
In the main function I run 20 times both methods to compare. You can copy the two sections of the code and run it
public static void main(String[] args) throws Exception{
long startTime, endTime, duration;
//Compare 20 times QuickSort vs MergeSort
for (int i=0;i<20;i++){
List<Integer> arreglo = randomArrayList(100000);
startTime = System.nanoTime();
QuickSort(arreglo);
endTime = System.nanoTime();
duration = (endTime - startTime)/1000000;
System.out.println("Quicksort: " + Long.toString(duration));
startTime = System.nanoTime();
MergeSort(arreglo);
endTime = System.nanoTime();
duration = (endTime - startTime)/1000000;
System.out.println("MergeSort: "+Long.toString(duration));
//System.out.println(Arrays.toString(QuickSort(arreglo).toArray()));
//System.out.println(Arrays.toString(MergeSort(arreglo).toArray()));
}
}
}
Here's my comment as an answer: You are sorting the same list twice, so the second sort is always sorting an already-sorted list (which is almost always not the same list as was fed to the first sort).
Try this variant of your main code:
public static void main(String[] args) throws Exception{
long startTime, endTime, duration;
//Compare 20 times QuickSort vs MergeSort
for (int i=0;i<20;i++){
List<Integer> arreglo = randomArrayList(100000);
List<Integer> arreglo2 = new ArrayList<>(arreglo); // Make a copy
startTime = System.nanoTime();
QuickSort(arreglo); // Sort the original
endTime = System.nanoTime();
duration = (endTime - startTime)/1000000;
System.out.println("Quicksort: " + Long.toString(duration));
startTime = System.nanoTime();
MergeSort(arreglo2); // Sort the copy
endTime = System.nanoTime();
duration = (endTime - startTime)/1000000;
System.out.println("MergeSort: "+Long.toString(duration));
}
}
Using an int[] array instead of the ArrayList wrapper class will probably gain you a bit of performance. There is overhead with the generic List classes that may not get optimized away.
Substituting something like (left + right) / 2 for your Random pivot code will also remove some overhead which will improve performance.
QuickSort specific, using InsertionSort on smaller sub arrays is more efficient than the partitioning.
Finally, avoiding recursive calls will lower stack usage which can benefit performance.
Here's some Javascript (sorry I don't have a Java version, you can translate it if you'd like). The implementation should be very fast.
/*
QUICK SORT IN PLACE
Use iterative approach with stack
Use insertion sort for small subsets
*/
function quickSortIP(arr) {
var stack = [];
var left = 0;
var right = arr.length - 1;
var i, j, swap, temp;
while(true) {
if(right - left <= 25){
for(j=left+1; j<=right; j++) {
swap = arr[j];
i = j-1;
while(i >= left && arr[i] > swap) {
arr[i+1] = arr[i--];
}
arr[i+1] = swap;
}
if(stack.length === 0) break;
right = stack.pop();
left = stack.pop();
} else {
var median = (left + right) >> 1;
i = left + 1;
j = right;
swap = arr[median]; arr[median] = arr[i]; arr[i] = swap;
if(arr[left] > arr[right]) {
swap = arr[left]; arr[left] = arr[right]; arr[right] = swap;
} if(arr[i] > arr[right]) {
swap = arr[i]; arr[i] = arr[right]; arr[right] = swap;
} if(arr[left] > arr[i]) {
swap = arr[left]; arr[left] = arr[i]; arr[i] = swap;
}
temp = arr[i];
while(true){
do i++; while(arr[i] < temp);
do j--; while(arr[j] > temp);
if(j < i) break;
swap = arr[i]; arr[i] = arr[j]; arr[j] = swap;
}
arr[left + 1] = arr[j];
arr[j] = temp;
if(right - i + 1 >= j - left){
stack.push(i);
stack.push(right);
right = j - 1;
}else{
stack.push(left);
stack.push(j - 1);
left = i;
}
}
}
return arr;
}
I am working on a exercise but I am stuck on one point
I want to measure the sorting times of 3 sorting algorithms (bubble,insertion and selection) using seven different arrays. I have tried multiple ways but I can't measure the sorting time of all three algorithms in a single step for all the arrays. My programme should:
randomly fill the array with integers
sort them
measure the times
print the times
The results are always coming 0 millisecond but it can not be like that because I tried 1million integer array so, there is no possibility for coming 0 millisecond for it.Finally, I tried "for loop " for achieving the what will I do.
I should write the all my methods because you may find another errors in other methods.
public static void randomlyFillArray(int[] array, int a, int b) {
for (int i = 0; i < array.length; i++) {
array[i] = randomInt(a, b);
}
}
public static int randomInt(int a, int b) {
return (int) ((b - a + 1) * Math.random() + a);
}
public static void SelectionSort(int[] array) {
for (int i = 0; i < array.length - 1; i++) {
for (int j = i + 1; j < array.length; j++) {
if (array[i] > array[j]) {
// ... Exchange elements
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
}
public static void insertionSort(int[] array) {
int i, j, temp;
for (i = 1; i < array.length; i++) {
temp = array[i];
j = i;
while (j > 0 && array[j - 1] > temp) {
array[j] = array[j - 1];
j--;
}
array[j] = temp;
}
}
public static void bubbleSort(int[] array) {
boolean swapped = true;
int j = 0;
int temp;
while (swapped) {
swapped = false;
j++;
for (int i = 0; i < array.length - j; i++) {
if (array[i] > array[i + 1]) {
temp = array[i];
array[i] = array[i + 1];
array[i + 1] = temp;
swapped = true;
}
}
}
}
public static void main(String[] args) {
// int[] array500 = new int[500]; //These are my arrays that I should do the process for //each one.
// int[] array1000 = new int[1000];
// int[] array5000 = new int[5000];
// int[] array10000 = new int[10000];
// int[] array50000 = new int[50000];
// int[] array100000 = new int[100000];
// int[] array500000 = new int[500000];
// int[] array1000000 = new int[1000000];
for (int i = 0; i < 4; i++) {
int[] array = new int[500];
if (i == 1) {
randomlyFillArray(array, 1, 1000);
SelectionSort(array);
long startTime = System.currentTimeMillis();
long total = 0;
long stopTime = System.currentTimeMillis();
long elapsedTime = stopTime - startTime;
SelectionSort(array);
System.out.println("SelectionSort for 500 integer : "
+ elapsedTime);
} else if (i == 2) {
randomlyFillArray(array, 1, 1000);
insertionSort(array);
long startTime = System.currentTimeMillis();
long total = 0;
long stopTime = System.currentTimeMillis();
long elapsedTime = stopTime - startTime;
insertionSort(array);
System.out.println("InsertionSort for 500 integer : "
+ elapsedTime);
} else if (i == 3) {
randomlyFillArray(array, 1, 1000);
bubbleSort(array);
long startTime = System.currentTimeMillis();
long total = 0;
long stopTime = System.currentTimeMillis();
long elapsedTime = stopTime - startTime;
bubbleSort(array);
System.out.println("BubbleSort for 500 integer : "
+ elapsedTime);
}
}
}
Thank you for your all advices stackoverflow family.
Sincerely.
All your timing blocks look like this:
randomlyFillArray(array, 1, 1000);
SelectionSort(array);
long startTime = System.currentTimeMillis();
long total = 0;
long stopTime = System.currentTimeMillis();
long elapsedTime = stopTime - startTime;
SelectionSort(array);
System.out.println("SelectionSort for 500 integer : " + elapsedTime);
You sort, then take the start time, then immediately take the end time, then sort again, then print the times. You have to take the end time after the sort. If you have a reason for sorting twice ('warming up' the JVM?), make sure that you re-randomize the array before you do the timed sort. An algorithm's performance for sorting an already sorted array might be much different.
randomlyFillArray(array, 1, 1000);
long startTime = System.currentTimeMillis();
long total = 0; // this thing is never used...
SelectionSort(array); // move this line between start time and end time!
long stopTime = System.currentTimeMillis();
long elapsedTime = stopTime - startTime;
System.out.println("SelectionSort for 500 integer : " + elapsedTime);
Also, much of that code is the same for each of those sorts. You can move those parts out of the if/else blocks and into the loop, making the whole code more compact and easier to maintain. Also, you can create another loop around that one for the different array sizes.
for (int num : new int[] {500, 1000, 5000, ...}) {
for (int i = 0; i < 4; i++) {
String sort = null;
int[] array = new int[num];
randomlyFillArray(array, 1, 1000);
long startTime = System.currentTimeMillis();
if (i == 1) {
sort = "SelectionSort";
SelectionSort(array);
} else if (i == ...) {
// analogeous for other sorts
}
long stopTime = System.currentTimeMillis();
long elapsedTime = stopTime - startTime;
System.out.println(sort + " for " + num + " integers: " + elapsedTime);
}
}
creating microbenchmarks can be tricky, because the JIT compiles frequently used code, which takes some time of its own...
so my approach is usually like this:
public void measureSorting(int[] array) {
// this should be sufficiently large
long start, end;
randomlyFillArray(array, 1, 1000);
// warm up JIT - execute without measuring
SelectionSort(array);
randomlyFillArray(array, 1, 1000);
// stop the time
start = System.currentTimeMillis();
SelectionSort(array);
end = System.currentTimeMillis();
System.out.printf("SelectionSort for %d integer : %d milliseconds", array.length, end-start);
// repeat for other algorithms
}
If you are using Java8, you can even create something like this:
public static void measureSorting(int[] array, Consumer<int[]> sortingFunction) {
// this should be sufficiently large
long start, end;
randomlyFillArray(array, 1, 1000);
// warm up JIT - execute without measuring
sortingFunction.accept(array);
randomlyFillArray(array, 1, 1000);
// stop the time
start = System.currentTimeMillis();
sortingFunction.accept(array);
end = System.currentTimeMillis();
// repeat for other algorithms
System.out.printf("%s for %d integer : %d milliseconds", sortingFunction, array.length, end-start);
}
public static void main(String[] args) {
// assuming the enclosing class is Sorter
measureSorting(new int[500], Sorter::SelectionSort);
measureSorting(new int[500], Sorter::insertionSort);
measureSorting(new int[500], Sorter::bubbleSort);
}
I have a simple problem - I need to order 10 numbers. I had an idea how to do this recursively: Make an array of the 10 numbers, take the maximum of the ten numbers, take it out of the array, and repeat the same function with the nine numbers left. The problem was that I did not know how to implement that. I wrote the program, and it works, only it has a part that repeats all the time but with new arrays, because you cannot change the size of the array.
/* package whatever; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone {
public static void main (String[] args) throws java.lang.Exception {
int[] sortedArray = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
Scanner input = new Scanner(System.in);
int in0 = input.nextInt();
int in1 = input.nextInt();
int in2 = input.nextInt();
int in3 = input.nextInt();
int in4 = input.nextInt();
int in5 = input.nextInt();
int in6 = input.nextInt();
int in7 = input.nextInt();
int in8 = input.nextInt();
int in9 = input.nextInt();
int[] numArray = new int[]{in0, in1, in2, in3, in4, in5, in6, in7, in8, in9};
int numArrayLength = numArray.length;
recursiveSort(numArray);
for (int i=0;i<numArrayLength;i++) {
System.out.print(numArray[i]+",");
}
sortedArray[0] = numArray[0];
System.out.println(" ");
int[] numArray2 = Arrays.copyOfRange(numArray, 1, numArrayLength);
int numArray2Length = numArray2.length;
recursiveSort(numArray2);
for (int j=0;j<numArray2Length;j++) {
System.out.print(numArray2[j]+",");
}
sortedArray[1] = numArray2[0];
System.out.println(" ");
int[] numArray3 = Arrays.copyOfRange(numArray2, 1, numArray2Length);
int numArray3Length = numArray3.length;
recursiveSort(numArray3);
for (int k=0;k<numArray3Length;k++) {
System.out.print(numArray3[k]+",");
}
sortedArray[2] = numArray3[0];
System.out.println(" ");
int[] numArray4 = Arrays.copyOfRange(numArray3, 1, numArray3Length);
int numArray4Length = numArray4.length;
recursiveSort(numArray4);
for (int k=0;k<numArray4Length;k++) {
System.out.print(numArray4[k]+",");
}
sortedArray[3] = numArray4[0];
System.out.println(" ");
int[] numArray5 = Arrays.copyOfRange(numArray4, 1, numArray4Length);
int numArray5Length = numArray5.length;
recursiveSort(numArray5);
for (int k=0;k<numArray5Length;k++) {
System.out.print(numArray5[k]+",");
}
sortedArray[4] = numArray5[0];
System.out.println(" ");
int[] numArray6 = Arrays.copyOfRange(numArray5, 1, numArray5Length);
int numArray6Length = numArray6.length;
recursiveSort(numArray6);
for (int k=0;k<numArray6Length;k++) {
System.out.print(numArray6[k]+",");
}
sortedArray[5] = numArray6[0];
System.out.println(" ");
int[] numArray7 = Arrays.copyOfRange(numArray6, 1, numArray6Length);
int numArray7Length = numArray7.length;
recursiveSort(numArray7);
for (int k=0;k<numArray7Length;k++) {
System.out.print(numArray7[k]+",");
}
sortedArray[6] = numArray7[0];
System.out.println(" ");
int[] numArray8 = Arrays.copyOfRange(numArray7, 1, numArray7Length);
int numArray8Length = numArray8.length;
recursiveSort(numArray8);
for (int k=0;k<numArray8Length;k++) {
System.out.print(numArray8[k]+",");
}
sortedArray[7] = numArray8[0];
System.out.println(" ");
int[] numArray9 = Arrays.copyOfRange(numArray8, 1, numArray8Length);
int numArray9Length = numArray9.length;
recursiveSort(numArray9);
for (int k=0;k<numArray9Length;k++) {
System.out.print(numArray9[k]+",");
}
sortedArray[8] = numArray9[0];
System.out.println(" ");
int[] numArray10 = Arrays.copyOfRange(numArray9, 1, numArray9Length);
int numArray10Length = numArray10.length;
recursiveSort(numArray10);
for (int k=0;k<numArray10Length;k++) {
System.out.print(numArray10[k]+",");
}
sortedArray[9] = numArray10[0];
System.out.println(" ");
sortedArray[2] = numArray3[0];
for (int dasdasd=0;dasdasd<sortedArray.length;dasdasd++) {
System.out.print(sortedArray[dasdasd]+",");
}
}
private static int[] recursiveSort(int numArray[]) {
int numArrayLength = numArray.length;
int maximum = 0;
for (int i=0;i<numArrayLength;i++) {
if (numArray[i] > maximum) {
maximum = numArray[i];
}
}
int indexOfMaximum = -1;
for (int j=0;j<numArrayLength;j++) {
if (numArray[j] == maximum) {
indexOfMaximum = j;
break;
}
}
int temporary = numArray[0];
numArray[0] = numArray[indexOfMaximum];
numArray[indexOfMaximum] = temporary;
return numArray;
}
}
As you can see, the
int[] numArray(n) = Arrays.copyOfRange(numArray(n-1), 1, numArray(n-1)Length);
int numArray(n)Length = numArray(n).length;
recursiveSort(numArray(n));
for (int k=0;k<numArray(n)Length;k++) {
System.out.print(numArray(n)[k]+",");
}
sortedArray[(n-1)] = numArray(n)[0];
System.out.println(" ");
constantly repeats, so there is probably a recursive solution that will work nicely. Maybe I can do something using ArrayLists because their size can change...
Any help will be appreciated!
Thank you!
I suggest a recursive routine that uses an explicit start index for the part that remains to be sorted:
private static void recursiveSort(int[] array, int start) {
if (start < array.length - 1) {
int maximum = array[start];
int maximumIndex = start;
for (int i = start + 1; i < array.length; ++i) {
if (array[i] > maximum) {
maximum = array[i];
maximumIndex = i;
}
}
if (maximumIndex != start) {
int tmp = array[start];
array[start] = array[maximumIndex];
array[maximumIndex] = tmp;
}
recursiveSort(array, start + 1);
}
}
This actually does recursion (unlike your code, which iterates calling a routine named "recursiveSort" but isn't recursive at all). The whole process would be started by calling:
recursiveSort(numArray, 0);
When it returns, the array will be sorted in descending order.
As a general heuristic, when you are struggling with how to make a method recursive, you should consider adding arguments to the method to help with the bookkeeping.
Is this homework or you just need to have the numbers ordered? Java has an easy way to do this if you use ArrayList() instead of array[]. You would just need to call Collections.sort(yourArrayList);
I suggest not trying to make your own sorting algorithm. Many smart people have already done that hard work for you.
The "recursive" sort that you were trying to implement (aka bubble sort which Ted has shown you how to truly make recursive) will work, but it is grossly inefficient. See a comparison of sorting algorithms here.
Below is a demo of the algorithm you were trying to implement compared to a shell sort, one of the fastest sorting algorithms available. The implementation I used was taken from here. Run it and you will see that shell sort is on average 7 to 8 times faster than bubble sort.
public class SortingDemo {
// Methods required for Shell sort
public static void shellSort(Comparable[] a) {
int N = a.length;
int h = 1;
while (h < N/3) h = 3*h + 1;
while (h >= 1) {
for (int i = h; i < N; i++) {
for (int j = i; j >= h && less(a[j], a[j-h]); j -= h) {
exch(a, j, j-h);
}
}
assert isHsorted(a, h);
h /= 3;
}
assert isSorted(a);
}
private static boolean less(Comparable v, Comparable w) {
return (v.compareTo(w) < 0);
}
private static void exch(Object[] a, int i, int j) {
Object swap = a[i];
a[i] = a[j];
a[j] = swap;
}
private static boolean isSorted(Comparable[] a) {
for (int i = 1; i < a.length; i++)
if (less(a[i], a[i-1])) return false;
return true;
}
private static boolean isHsorted(Comparable[] a, int h) {
for (int i = h; i < a.length; i++)
if (less(a[i], a[i-h])) return false;
return true;
}
// Method required for "recursive" sort
private static void recursiveSort(Integer[] array, int start) {
if (start < array.length - 1) {
int maximum = array[start];
int maximumIndex = start;
for (int i = start + 1; i < array.length; ++i) {
if (array[i] > maximum) {
maximum = array[i];
maximumIndex = i;
}
}
if (maximumIndex != start) {
int tmp = array[start];
array[start] = array[maximumIndex];
array[maximumIndex] = tmp;
}
recursiveSort(array, start + 1);
}
}
public static void main(String[] args) {
int desiredArraySize = 1000;
int minSizeOfNumberInArray = 0;
int maxSizeOfNumberInArray = 100;
Integer[] array = new Integer[desiredArraySize]; // Used Integer instead of int to utilize Comparable interface
for(int i = 0; i < array.length; i++) {
int randomInt = (int) Math.random() * (maxSizeOfNumberInArray - minSizeOfNumberInArray);
array[i] = randomInt;
}
long startTime = System.nanoTime();
recursiveSort(array, 0);
long endTime = System.nanoTime();
long recursiveSortTime = endTime - startTime;
System.out.println(String.format("\"Recursive\" sort completed in %d ns", recursiveSortTime));
startTime = System.nanoTime();
shellSort(array);
endTime = System.nanoTime();
long shellSortTime = endTime - startTime;
System.out.println(String.format("Shell sort completed in %d ns", shellSortTime));
System.out.println(String.format("\"Recursive\" sort took %f times longer", (float)recursiveSortTime / (float)shellSortTime));
}
}
When learning programming, both writing your own sorting algorithms and your own recursive algorithms are great exercises for solidifying your understanding of how things work. It's time well invested, even if someone's already done it better.
You noticed a pattern that repeats, and associated that with recursion. When evaluating whether recursion is a good fit, I would encourage you to tweak that thought process with the notion of "divide-and-conquer". If you're solving only one element with each recursion, then your stack will grow very deep, which should be avoided. If you can split your problem into roughly even chunks and process each chunk recursively, then recursion will be a good fit. Otherwise, a loop is already an excellent fit for repeating patterns.
This program is suppose to detect if an integer is found or not and how long it took to find. The first one is a linear search and the second is a binary search. The problems I'm having is this. The linear search works, except I keep getting the message "Linear search successful" again and again. I'm not sure why the binary search isn't outputting anything to be honest. Any help is appreciated
public class search {
/**
* #param args
*/
public static void main(String[] args) {
Scanner scanner1 = new Scanner(System.in);
System.out.println("Please enter in an integer:");
int searchValue = scanner1.nextInt();
int[] numbers = new int[1000];
try {
Scanner scanner = new Scanner(new File("numbers.txt"));
for (int i = 0; i < 1000; i++) {
numbers[i] = scanner.nextInt();
}
} catch (FileNotFoundException e) {
System.out
.println("A problem occurred reading the file numbers.txt");
System.exit(0);
}
long time = System.nanoTime();
int linear = linearSearch(numbers, searchValue);
long end = System.nanoTime();
System.out.println(end - time);
}
public static int linearSearch(int[] numbers, int searchValue) {
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] > searchValue)
return -1;
else if (numbers[i] == searchValue)
return i;
System.out.println("Linear search successful");
}
return -1;
}
public int binarySearch(int searchValue, int[] numbers) {
long time = System.nanoTime();
int low = 0;
int high = numbers.length - 1;
while (low <= high) {
int middle = low + (high - low) / 2;
if (numbers[middle] == searchValue) {
System.out.println("Binary found");
long end = System.nanoTime();
System.out.println(end - time);
}
if (searchValue < numbers[middle])
high = middle - 1;
else if (searchValue > numbers[middle])
low = middle + 1;
else
return middle;
}
return -1;
}
}
It's because you never call the binarySearch() function. You only call linearSearch().
/* Call to linearSearch is here */
int linear = linearSearch(numbers, searchValue);
/* No call to binarySearch to put here */
System.out.println("Linear search successful")
put this outside the for loop
and for binary search to take place you need to at least call the function .