Java Bubble Sort Trouble - java

I've written a bubble sort program that sorts 10000 unique values into order.
I've run the program and it gives me an output of time (using nanoTime) for the time it takes the program to complete, but I wish to add another output to the program's code; How many moves the program takes to sort from start to finish.
Here is the code:
public class BubbleSort {
public static void main(String[] args) {
int BubArray[] = new int[]{#here are 10000 integers#};
System.out.println("Array Before Bubble Sort");
for(int a = 0; a < BubArray.length; a++){
System.out.print(BubArray[a] + " ");
}
double timeTaken = bubbleSortTimeTaken(BubArray);
bubbleSort(BubArray);
System.out.println("");
System.out.println("Array After Bubble Sort");
System.out.println(" Time taken for Sort : " + timeTaken + " milliseconds.");
for(int a = 0; a < BubArray.length; a++){
System.out.print(BubArray[a] + " ");
}
}
private static void bubbleSort(int[] BubArray) {
int z = BubArray.length;
int temp = 0;
for(int a = 0; a < z; a++){
for(int x=1; x < (z-a); x++){
if(BubArray[x-1] > BubArray[x]){
temp = BubArray[x-1];
BubArray[x-1] = BubArray[x];
BubArray[x] = temp;
}
}
}
}
public static double bubbleSortTimeTaken(int[] BubArray) {
long startTime = System.nanoTime();
bubbleSort(BubArray);
long timeTaken = System.nanoTime() - startTime;
return timeTaken;
}
}
The code executes and outputs how I want it to:
Array Before Bubble Sort
13981 6793 2662 10986 733 10107 2850 ...
Array After Bubble Sort
10 11 17 24 35 53 57 60 61 78 83 89 128 131 138 141 ....
Time taken for Sort : 1.6788472E7 milliseconds.
But I wish to add another output to the code where it tells me in how many moves (basically a move counter) it takes to complete, i.e:
Time taken for Sort : 1.6788472E7 milliseconds.
Total number of moves: 3000
Does this make sense?
Any help would be appreciated, thanks.

I would change bubbleSort to return an int and assign your time complexity to it.
private static int bubbleSort(int[] BubArray) {
int z = BubArray.length;
int temp = 0;
int itrs = 0;
for(int a = 0; a < z; a++){
for(int x=1; x < (z-a); x++){
if(BubArray[x-1] > BubArray[x]){
temp = BubArray[x-1];
BubArray[x-1] = BubArray[x];
BubArray[x] = temp;
}
itrs++;
}
}
return itrs;
}
Then in main:
int itrs = bubbleSort(BubArray);
System.out.println("");
System.out.println("Array After Bubble Sort");
System.out.println(" Time taken for Sort : " + timeTaken + " milliseconds.");
System.out.println("Time complexity: " + itrs);

Try this:
// returns the number of switches
private int bubbleSort(int[] BubArray) {
int z = BubArray.length;
int temp = 0;
int timesSwitched = 0;
for(int a = 0; a < z; a++){
for(int x=1; x < (z-a); x++){
if(BubArray[x-1] > BubArray[x]){
temp = BubArray[x-1];
BubArray[x-1] = BubArray[x];
BubArray[x] = temp;
timesSwitched++
}
}
}
return timesSwitched;
}

Related

TestClass for simple sorting algorithms gives unlogical results

I have the following Class with some sorting algorithms like MaxSort, BubbleSort, etc.:
class ArrayUtility {
public static int returnPosMax(int[] A, int i, int j) {
int max = i;
int position = 0;
for(int c = 0; c <= j; c++){
if(c >= i){
if(A[c] > max){
max = A[c];
position = c;
}
}
}
return position;
}
public static int returnMax(int[] A, int i, int j) {
return A[returnPosMax(A, i, j)];
}
public static void swap(int[] A, int i, int j) {
int b = A[i];
A[i] = A[j];
A[j] = b;
}
public static void MaxSort(int[] A) {
int posMax;
for(int i = A.length - 1; i >= 0; i--){
posMax = returnPosMax(A, 0, i);
swap(A, posMax, i);
}
}
public static void BubbleSort(int[] A) {
boolean flag = true;
while (flag != false){
flag = false;
for(int i = 1; i <= A.length - 1; i++){
if(A[i-1]>A[i]){
swap(A, i-1, i);
flag = true;
}
}
if(flag = false) {
break;
}
for(int i = A.length - 1; i >= 1; i--){
if(A[i-1]>A[i]){
swap(A, i - 1, i);
flag = true;
}
}
}
}
public static void BubbleSortX(int[] A) {
boolean flag = true;
while (flag != false){
flag = false;
for(int i = 1; i <= A.length - 1; i++){
if(A[i-1]>A[i]){
swap(A, i-1, i);
flag = true;
}
}
}
}
}
Now i have to create a Test Class to evaluate the different sorting algorithms for different lengths of randomly created Arrays:
import java.util.Random;
import java.util.Arrays;
public class TestSorting{
public static void main(String[] args){
int[] lengthArray = {100, 1000, 10000, 100000};
for(int i = 0; i <= lengthArray.length - 1; i++){
int[] arr = new int[i];
for(int j = 0; j < i; j++){
Random rd = new Random();
int randInt = rd.nextInt();
arr[j] = randInt;
}
/* long startTime = System.nanoTime();
ArrayUtility.MaxSort(arr);
long cpuTime = System.nanoTime() - startTime;
System.out.println("Time: " + cpuTime + " - Array with Length: " + lengthArray[i] + " Using MaxSort"); */
/* long startTime = System.nanoTime();
ArrayUtility.BubbleSortX(arr);
long cpuTime = System.nanoTime() - startTime;
System.out.println("Time: " + cpuTime + " - Array with Length: " + lengthArray[i] + " Using BubbleSortX"); */
long startTime = System.nanoTime();
ArrayUtility.BubbleSort(arr);
long cpuTime = System.nanoTime() - startTime;
System.out.println("Time: " + cpuTime + " - Array with Length: " + lengthArray[i] + " Using BubbleSort");
/*long startTime = System.nanoTime();
Arrays.sort(arr)
long cpuTime = System.nanoTime() - startTime;
System.out.println("Time: " + cpuTime + " - Array with Length: " + lengthArray[i] + " Using BubbleSort"); */
}
}
}
Now when i run a certain sorting algorithm (i set the others as comment for the meantime), i get weird results, for example
Time: 1049500 - Array with Length: 100 Using BubbleSort
Time: 2200 - Array with Length: 1000 Using BubbleSort
Time: 13300 - Array with Length: 10000 Using BubbleSort
Time: 3900 - Array with Length: 100000 Using BubbleSort
And any time i run the test i get different results, such that Arrays with 10 times the length take less time to sort, also i dont understand why the array with 100 integers takes so long.
TL;DR: your benchmark is wrong.
Explanation
To make a good benchmark, you need to do a lot of research. A good starting point is this article and this talk by Alexey Shipilev, the author of micro-benchmark toolkit JMH.
Main rules for benchmarking:
warm up! Do a bunch (like, thousands) of warmup rounds before you actually measure stuff - this will allow JIT compiler to do its job, all optimizations to apply, etc.
Monitor your GC closely - GC event can skid the results drastically
To avoid that - repeat the benchmark many (hundreds thousands) times and get the average.
All this can be done in JMH.
I took a snippet out of your code to show you where your code is buggy.
public static void main(String[] args){
int[] lengthArray = {100, 1000, 10000, 100000};
for(int i = 0; i <= lengthArray.length - 1; i++) { // this loop goes from 0 - 3
int[] arr = new int[i]; // thats why this array will be of size 0 - 3
// correct line would be:
// int[] arr = new int[lengthArray[i]];
for(int j = 0; j < i; j++) {
// correct line would be:
// for (int j = 0; j < arr.length; j++) {
...
Additionally, the hint for benchmarking from Dmitry is also important to note.

I don't get why my run time is slower on the second sorting than the first?

Essentially, I know that the run time on the second time should be way slower than the first, however, sometimes when I run it the second time is way slower. I know it is not supposed to be that way, and I know the size of the array shouldn't affect it. I have no reason why and stop and end time shouldn't really matter since they are subtracted anyways. It may be just a dumb mistake, but I am new to programming so any help will be appreciated. Thank you!
import java.util.*;
import java.io.*;
class Main {
// Sort the Array
public static void selectionSort( int[] array ) {
// Find the integer that should go in each cell of
// the array, from cell 0 to the end
for ( int j=0; j<array.length-1; j++ ) {
// Find min: the index of the integer that should go into cell j.
// Look through the unsorted integers (those at j or higher)
int min = j;
for ( int k=j+1; k<array.length; k++) {
if ( array[k] < array[min] ) {
min = k;
}
}
// Swap the int at j with the int at min
int temp = array[min];
array[min] = array[j];
array[j] = temp;
}
}
public static void main ( String[] args ) {
Scanner kbReader = new Scanner(System.in);
System.out.print("What size is your array?: ");
int size = kbReader.nextInt();
Random rand = new Random();
int[] values = new int[size];
for (int i = 0; i < values.length; i++) {
values[i] = rand.nextInt(size);
}
System.out.println("Before: Not Sorted");
long startTime = System.currentTimeMillis();
selectionSort( values );
long endTime = System.currentTimeMillis();
System.out.println("Total execution time: " + (endTime - startTime) + " ms");
System.out.println("After: Sorted");
//second time sorting it
System.out.println("\nThis is the second time sorting: ");
System.out.println("Before: Not Sorted");
startTime = System.currentTimeMillis();
selectionSort( values );
endTime = System.currentTimeMillis();
System.out.println("Total execution time: " + (endTime - startTime) + " ms");
System.out.println("After: Sorted");
}
}

Printing an array from lowest to highest without sorting

I want to start off by saying I am not very experienced and I am sorry if this has been answered. I have been trying to find an answer for a while and have not been able to.
I am working on a project where the user inputs numbers into an array. These numbers represent temperatures for different days. The days are obviously the position in the array. I need to find a way to print the temperatures from least to greatest without sorting the array.
So if the user entered [56, 45, 67, 41, 59, 70] that means that it was 56 degrees at position 0 (day 1), 67 degrees at position 2 (day 3). I need to keep the position of the array the same so the days remain with the temps when it prints out.
Edit: I have attached the code I have on my project so far. The HighestOrdered method is the method I dont know what to do or where to start. For the HighestOrdered method as I said above I need to have it print out the temps with the day (the position in the array) and I am not sure how to do that.
This is the code I have so far:
public class Weather {
public static void main(String[] args) {
// TODO Auto-generated method stub
int [] high = new int[30];
int [] low = new int[30];
Init (high);
Init(low);
LoadData(high,low);
Report(high, low);
FindAvg(high,low);
Lowest(high, low);
Highest(high,low);
}
public static void Init(int A[])
{
for(int i = 0; i < A.length; i++)
{
A[i] = 510;
}
}
public static void Report(int[] H, int[] L)
{
System.out.println("Day High Low");
for(int i = 0; i < H.length; i++)
{
System.out.println(i + " " + H[i] + " " + L[i]);
}
}
public static void LoadData(int[] H, int[] L)
{
int day = 0;
while(day < 30)
{
try {
int high = Integer.parseInt(JOptionPane.showInputDialog("please enter the high"));
H[day] = high;
} catch (NumberFormatException e) {
}
try {
int low = Integer.parseInt(JOptionPane.showInputDialog(" Please enter the low"));
L[day] = low;
} catch (NumberFormatException e) {
}
day++;
}
}
public static void FindAvg(int[] H, int[] L){
int sumHigh = 0;
int avgHigh;
int sumLow = 0;
int avgLow;
for(int i : H)
sumHigh += i;
avgHigh = sumHigh/H.length;
for(int i : L)
sumLow += i;
avgLow = sumLow/L.length;
System.out.println("The average for the high is: " + avgHigh);
System.out.println("The average for the low is: " + avgLow);
}
public static void Highest(int[] H, int[] L)
{
int highestHigh = -1000;
int dayHigh = 0;
int highestLow = -1000;
int dayLow = 0;
for(int i = 0; i < H.length; i++)
{
if(H[i] > highestHigh && H[i] != 510)
{
highestHigh = H[i];
dayHigh = i;
}
}
System.out.println("\n" + "The highest high is: " + highestHigh + " degrees." + "\n" +
"This temperature was recorded on day: " + dayHigh);
for(int i = 0; i < L.length; i++)
{
if(L[i] > highestLow && L[i] != 510)
{
highestLow = L[i];
dayLow = i;
}
}
System.out.println("\n" + "The highest low is: " + highestLow + " degrees." + "\n" +
"This temperature was recorded on day: " + dayLow);
}
public static void Lowest(int[] H, int[] L)
{
int lowestHigh = 1000;
int dayHigh = 0;
int lowestLow = 1000;
int dayLow = 0;
for(int i = 0; i < H.length; i++)
{
if(H[i] < lowestHigh)
{
lowestHigh = H[i];
dayHigh = i;
}
}
System.out.println("\n" + "The lowest high is: " + lowestHigh + " degrees." + "\n" +
"This temperature was recorded on day: " + dayHigh);
for(int i = 0; i < L.length; i++)
{
if(L[i] < lowestLow)
{
lowestLow = L[i];
dayLow = i;
}
}
System.out.println("\n" + "The lowest low is: " + lowestLow + " degrees." + "\n" +
"This temperature was recorded on day: " + dayLow);
}
public void HighestOrdered(int[] H)
{
}
}
Here's a start.
From your array, create a sorted Map, say
Map<Integer,Integer> mymap = new TreeMap<Integer,Integer>.
You will use temp for the key and the day for the value. e.g., from your example data,
myMap.put(56,1);
myMap.put(45,2);
(Note - in the real code you'd iterate over the array to put the values.)
Then you can iterate over the keys and values (or the entries) in myMap.
Here is a small example to show how this can be done. Only the auxiliary index array is sorted, the original temp array is not changed.
public static void main(String[] args) {
final int [] temp = {56, 45, 67, 41, 59, 70};
Integer [] index = new Integer[temp.length];
for (int i = 0; i < index.length; i++) {
index[i] = i;
}
Arrays.sort(index, new Comparator<Integer>() {
#Override
public int compare(Integer a, Integer b) {
return temp[a] - temp[b];
}
});
for (Integer i : index) {
System.out.printf("temp %d on day %d%n", temp[i], i);
}
}
This gives the output:
temp 41 on day 3
temp 45 on day 1
temp 56 on day 0
temp 59 on day 4
temp 67 on day 2
temp 70 on day 5
Instead of your current array, you can create an object array with each object having two elements: the day and the corresponding temperature.
Sort this array by the temperature value and then print it.

Looping through a method and using the results

I am trying to loop through this method 10 times that searches an array of numbers captures the run time in nano seconds and prints the results. I then want t take the 10 run times and find the average and standard deviation.
Is there a way to capture the time after 10 run and use the result to find my average and standard deviation?
This is what I have so far:
public class Search {
public static int Array[] = new int[100];
//Building my array with 100 numbers in sequential order
public static void createArray(){
int i = 0;
for(i = 0; i<Array.length; i++)
Array[i] = i + 1;
int check[] = {5, 15, 12};
int target = check[2];
boolean found = false;
int j = 0;
long startTime = System.nanoTime();
for(j=0; j<Array.length;j++){
if(Array[j] == target){
long endTime = System.nanoTime();
System.out.print(endTime - startTime + "ms" + "\t\t");
found = true;
break;
}
}
if(found){
//System.out.println("got you! "+ target + " is at index "+ j +"\t");..... just to test if it was working
}
else{
System.out.println("not available");
}
}
// Printing header
public static void main(String[]args){
System.out.print("First run\tSecond run\tThird run\tFourth run\tFifth run\tSixth run\tSeventh run\tEight run\tNinth run\tTenth run\tAverage \tStandard deviation\n");
// looping through the method 10 times
int i=0;
while(i<10){
createArray();
i++;
}
}
}
Try:
long sum = 0;
long sumSquare = 0;
for(int c = 0 ; c < 10 ; c++) {
long start = System.nanoTime();
// do work
long end = System.nanoTime();
sum += end - start;
sumSquare += Math.pow(end - start, 2);
}
double average = (sum * 1D) / 10;
double variance = (sumSquare * 1D) / 10 - Math.pow(average, 2);
double std = Math.sqrt(variance);
Try creating an array list of size 10 like:
private static List<Long> times = new ArrayList<>(10);
And then, when you find the element just add endTime - startTime to list like:
times.add(..);
And once that's done, in your main method you could do sum, average like:
long totalTime = 0;
for (Long time : times) {
totalTime += time;
}
//print average by dividing totalTime by 10.

JAVA Programming Execute Multiple Times

I have written a BubbleSort program and it works great, gives me a good output and does its job sufficiently. But I am unable to make the program re-execute after sorting through once. I.e. the program completes a sort of 10000 unique numbers and outputs the time it takes and the amount of steps it took, but doesn't execute again, say for another 999 times after that?
In short, can anyone help me get my program to run through itself 1000 times so I am able to get an average of execution time?
Here is the code:
public class BubbleSort {
public static void main(String[] args) {
int BubArray[] = new int[] { #10000 unique values unsorted# };
System.out.println("Array Before Bubble Sort");
for (int a = 0; a < BubArray.length; a++) {
System.out.print(BubArray[a] + " ");
}
double timeTaken = bubbleSortTimeTaken(BubArray);
int itrs = bubbleSort(BubArray);
System.out.println("");
System.out.println("Array After Bubble Sort");
System.out.println("Moves Taken for Sort : " + itrs + " moves.");
System.out.println("Time Taken for Sort : " + timeTaken
+ " milliseconds.");
for (int a = 0; a < BubArray.length; a++) {
System.out.print(BubArray[a] + " ");
}
}
private static int bubbleSort(int[] BubArray) {
int z = BubArray.length;
int temp = 0;
int itrs = 0;
for (int a = 0; a < z; a++) {
for (int x = 1; x < (z - a); x++) {
if (BubArray[x - 1] > BubArray[x]) {
temp = BubArray[x - 1];
BubArray[x - 1] = BubArray[x];
BubArray[x] = temp;
}
itrs++;
}
}
return itrs;
}
public static double bubbleSortTimeTaken(int[] BubArray) {
long startTime = System.nanoTime();
bubbleSort(BubArray);
long timeTaken = System.nanoTime() - startTime;
return timeTaken;
}
}
and here are the results output (note it is limited to just one run):
Unsorted List :
[13981, 6793, 2662, 733, 2850, 9581, 7744 .... ]
Sorted List with BubbleSort
Moves Taken to Sort : 1447551 Moves.
Time Taken to Sort : 1.2483121E7 Milliseconds.
[10, 11, 17, 24, 35, 53, 57, 60, 78, 89, 92 ... ]
Edited code...
public class BubbleSort {
static double bestTime = 10000000, worstTime = 0; //global variables
public static void main(String[] args) {
int BubArray[] = new int[]{3,5,3,2,5,7,2,5,8};
System.out.println("Array Before Bubble Sort");
for(int a = 0; a < BubArray.length; a++){
System.out.print(BubArray[a] + " ");
}
System.out.println("\n Entering Loop...");
for(int i=0; i<1000;i++)
{
bubbleSortTimeTaken(BubArray, i);
}
int itrs = bubbleSort(BubArray);
System.out.println("");
System.out.println("Array After Bubble Sort");
System.out.println("Moves Taken for Sort : " + itrs + " moves.");
System.out.println("BestTime: " + bestTime + " WorstTime: " + worstTime);
System.out.print("Sorted Array: \n");
for(int a = 0; a < BubArray.length; a++){
System.out.print(BubArray[a] + " ");
}
}
private static int bubbleSort(int[] BubArray) {
int z = BubArray.length;
int temp = 0;
int itrs = 0;
for(int a = 0; a < z; a++){
for(int x=1; x < (z-a); x++){
if(BubArray[x-1] > BubArray[x]){
temp = BubArray[x-1];
BubArray[x-1] = BubArray[x];
BubArray[x] = temp;
}
itrs++;
}
}
return itrs;
}
public static void bubbleSortTimeTaken(int[] BubArray, int n)
{
long startTime = System.nanoTime();
bubbleSort(BubArray);
double timeTaken = (System.nanoTime() - startTime)/1000000d;
if(timeTaken > 0)
{
if(timeTaken > worstTime)
{
worstTime = timeTaken;
}
else if(timeTaken < bestTime)
{
bestTime = timeTaken;
}
}
System.out.println("Loop number: "+n + " Time Taken: " + timeTaken);
}
}
Move the method below
private static int bubbleSort(int[] BubArray)
in to some other class extending Thread. May be you can create new threads each time execution finishes. A static instance variable in root class can be used to hold the times.

Categories

Resources