Java Bubble Sort Acting Strange - java

I have a function here for bubble sort using Java and this code does work and sort an array. However, the issue is that I have no idea how it's sorting it because it does not seem like standard bubble sort.
public static void swap (int [ ] data, int index1, int index2)
// POST: elements at indexes are exchanged
{ int temp = data[index1]; // temporary to hold first value
data[index1] = data[index2];
data[index2] = temp;
}
public static void bubbleSort (int [ ] data)
// POST: elements in data array are sorted in ascending order
{ for (int ct1=0; ct1<data.length-1; ct1++) // outer loop moves one element into place
{ for (int ct2=0; ct2<data.length-1-ct1; ct2++)
if (data[ct2] > data[ct2+1]) // swap if element on left bigger than right
swap (data, ct2,ct2+1);
for (int i = 0; i < data.length; i++) System.out.print(data[i] + " ");
System.out.println();
}
}
The bubble sort I understand would take an array {40, 90, 10, 60, 20} and compare the 0th and 1st index. If the 0th index is greater than the 1st index then they would swap. Then, in this case, 40 and 90 would stay where they are and then the 1st and 2nd index would be compared, resulting in 90 and 10 swapping. This would continue n - 1 times where n is the length of the array.
The problem is, using this function seems to give the output:
Bubble sort:
Starting array: 40 90 10 60 20
40 10 60 20 90
10 40 20 60 90
10 20 40 60 90
10 20 40 60 90
Can anybody help explain this please?
It seems to be comparing arbitrary values and does not check the 40 and 90 like it should.

it will be swap until the end in a one loop with ct2.
inside loop ,will be going 4 times .
it is like a rock falling into water.
Engilsh is poor ,sorry~

Inside your bubbleSort method, you are starting an array from 0 upto the length of array - 1. Instead just make is simple and run it in reverse like this:
public static void bubbleSort(int [] data) {
int k;
for (int m = data.length; m >= 0; m--) {
for (int i = 0; i < data.length - 1; i++) {
k = i + 1;
if (array[i] > array[k]) {
swapNumbers(i, k, array);
}
}
// Time to test this new array here:
for (int i = 0; i < data.length; i++) {
System.out.print(data[i] + ", ");
}
System.out.println("\n");
}
}
Check if your solution is printed correctly and let me know

Your bubble sort is behaving the way you expect it too.
It is sorting lowest to highest in reverse order (i.e. last column is set first)
I think the problem you are having is that the output sample frequency
does not match what is going on in your head.
if you change the code slightly
public static void swap (int [ ] data, int index1, int index2){
int temp = data[index1];
data[index1] = data[index2];
data[index2] = temp;
}
public static void bubbleSort (int [ ] data) {
for (int ct1=0; ct1<data.length-1; ct1++) {
for (int ct2=0; ct2<data.length-1-ct1; ct2++) {
if (data[ct2] > data[ct2 + 1]) {
swap(data, ct2, ct2 + 1);
// non functional change to move sampling point
for (int i = 0; i < data.length; i++) {
System.out.print(data[i] + " ");
}
System.out.println();
}
}
}
}
public static void main(String[] args) {
bubbleSort(new int[]{40,90,10,60,20});
}
this produces the output
40 10 90 60 20
40 10 60 90 20
40 10 60 20 90
10 40 60 20 90
10 40 20 60 90
10 20 40 60 90
which is what I think you expect to see.

Related

Creating a method that merges 2 arrays into one sorted array in ascending order in Java

For part of an assignment, I have to create a method that merges 2 arrays into one sorted array in ascending order. I have most of it done, but I am getting a bug that replaces the last element in the array with 0. Has anyone ever run into this problem and know a solution? Heres my code:
public static OrderedArray merge(OrderedArray src1, OrderedArray src2) {
int numLength1 = src1.array.length;
int numLength2 = src2.array.length;
//combined array lengths
int myLength = (numLength1 + numLength2);
// System.out.println(myLength);
OrderedArray mergedArr = new OrderedArray(myLength);
//new array
long[] merged = new long[myLength];
//loop to sort array
int i = 0;
int j = 0;
int k = 0;
while (k < src1.array.length + src2.array.length - 1) {
if(src1.array[i] < src2.array[j]) {
merged[k] = src1.array[i];
i++;
}
else {
merged[k] = src2.array[j];
j++;
}
k++;
}
//loop to print result
for(int x = 0; x < myLength; x++) {
System.out.println(merged[x]);
}
return mergedArr;
}
public static void main(String[] args) {
int maxSize = 100; // array size
// OrderedArray arr; // reference to array
OrderedArray src1 = new OrderedArray(4);
OrderedArray src2 = new OrderedArray(5);
// arr = new OrderedArray(maxSize); // create the array
src1.insert(1); //insert src1
src1.insert(17);
src1.insert(42);
src1.insert(55);
src2.insert(8); //insert src2
src2.insert(13);
src2.insert(21);
src2.insert(32);
src2.insert(69);
OrderedArray myArray = merge(src1, src2);
This is my expected output:
1
8
13
17
21
32
42
55
69
and this is my current output:
1
8
13
17
21
32
42
55
0
While merging two arrays you are comparing them, sorting and merging but what if the length of two arrays is different like Array1{1,3,8} and Array2{4,5,9,10,11}. Here we will compare both arrays and move the pointer ahead, but when the pointer comes at 8 in array1 and at 9 in array2, now we cannot compare ahead, so we will add the remaining sorted array;
Solution:-
(Add this code between loop to sort array and loop to print array)
while (i < numLength1) {
merged[k] = src1.array[i];
i++;
k++;
}
while (j < numLength2) {
merged[k] = src2.array[j];
j++;
k++;
}
To answer your main question, the length of your target array is src1.array.length + src2.array.length, so your loop condition should be one of:
while (k < src1.array.length + src2.array.length) {
while (k <= src1.array.length + src2.array.length - 1) {
Otherwise, you will never set a value for the last element, where k == src1.array.length + src2.array.length - 1.
But depending on how comprehensively you test the code, you may then find you have a bigger problem: ArrayIndexOutOfBoundsException. Before trying to use any array index, such as src1.array[i], you need to be sure it is valid. This condition:
if(src1.array[i] < src2.array[j]) {
does not verify that i is a valid index of src1.array or that j is a valid index of src2.array. When one array has been fully consumed, checking this condition will cause your program to fail. You can see this with input arrays like { 1, 2 } & { 1 }.
This revision of the code does the proper bounds checks:
if (i >= src1.array.length) {
// src1 is fully consumed
merged[k] = src2.array[j];
j++;
} else if (j >= src2.array.length || src1.array[i] < src2.array[j]) {
// src2 is fully consumed OR src1's next is less than src2's next
merged[k] = src1.array[i];
i++;
} else {
merged[k] = src2.array[j];
j++;
}
Note that we do not need to check j in the first condition because i >= src1.array.length implies that j is a safe value, due to your loop's condition and the math of how you are incrementing those variables:
k == i + j due to parity between k's incrementing and i & j's mutually exclusive incrementing
k < src1.array.length + src2.array.length due to the loop condition
Therefore i + j < src1.array.length + src2.array.length
If both i >= src1.array.length and j >= src2.array.length then i + j >= src1.array.length + src2.array.length, violating the facts above.
A couple other points and things to think about:
Be consistent with how you refer to data. If you have variables, use them. Either use numLength1 & numLength2 or use src1.length & src2.length. Either use myLength or use src1.array.length + src2.array.length.
Should a merge method really output its own results, or should the code that called the method (main) handle all the input & output?
Is the OrderedArray class safe to trust as "ordered", and is it doing its job properly, if you can directly access its internal data like src1.array and make modifications to the array?
The best way to merge two arrays without repetitive items in sorted order is that insert both of them into treeSet just like the following:
public static int[] merge(int[] src1, int[] src2) {
TreeSet<Integer> mergedArray= new TreeSet<>();
for (int i = 0; i < src1.length; i++) {
mergedArray.add(src1[i]);
}
for (int i = 0; i < src2.length; i++) {
mergedArray.add(src2[i]);
}
return mergedArray.stream().mapToInt(e->(int)e).toArray();
}
public static void main(String[] argh) {
int[] src1 = {1,17,42,55};
int[] src2 = {8,13,21,32,69};
Arrays.stream(merge(src1,src2)).forEach(s-> System.out.println(s));
}
output:
1
8
13
17
21
32
42
55
69

Java Exception: Array indexes out of bounds

I was given a lab assignment where we were asked to fill an array of size 50. The first 25 elements had random distinct elements, and the remaining have to be each 26 . All we have to do is print the repeating element,which obviously is 26, using the Las Vegas Algorithm .
I wrote the program and since it's my first time at Java , I am stuck with an exception of Array indexes out of bounds.
I am also sure that there is nothing wrong with the algorithm, and please note that I first created a list and then converted it to array of Integer type.
Hoping for a helping hand.
The code is as follows :-
public class NewClass {
static Random randomGenerator = new Random();
public static void lasveg(Integer a[],int n)
{
int i,j;
boolean chk= true;
while(chk)
{
i=(randomGenerator.nextInt())%n+1;
j=(randomGenerator.nextInt())%n+1;
if((i!=j)&&(a[i].equals(a[j])))
System.out.println("The repeated element is : " + i);
}
}
public static void main(String[] args)
{
int i ;
Integer[] arr = new Integer[50] ; //used the Integer wrapper class instead of primitive int
ArrayList list = new ArrayList(50);
for (i=1; i<26; i++)
{
list.add(i) ;
}
Collections.shuffle(list);
for(i=26 ; i<51 ; i++)
{
list.add(26) ;
}
list.toArray(arr) ;
for(i=0 ; i<50 ; i++)
{
System.out.print(arr[i] + " ");
}
lasveg(arr,50);
}
}
The code has several issues:
randomGenerator.nextInt() could return negative numbers and you
can't use negative numbers as index for an array.
if you use % n+1 then you could get an index bigger than 49, which
should be the highest index in an array of length 50.
the third thing is that you have a endless loop, because you never
end the while(true)
If you change all that then your code could look like that:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
public class NewClass {
static Random randomGenerator = new Random();
public static void lasveg(Integer a[], int n) {
int i, j;
boolean chk = true;
while (chk) {
i = Math.abs(randomGenerator.nextInt()) % n ;
j = Math.abs(randomGenerator.nextInt()) % n ;
if ((i != j) && (a[i].equals(a[j]))){
System.out.println("The repeated element is : " + i);
break;
}
}
}
public static void main(String[] args) {
int i;
Integer[] arr = new Integer[50]; // used the Integer wrapper class
// instead of primitive int
ArrayList list = new ArrayList(50);
for (i = 1; i < 26; i++) {
list.add(i);
}
Collections.shuffle(list);
for (i = 26; i < 51; i++) {
list.add(26);
}
list.toArray(arr);
for (i = 0; i < 50; i++) {
System.out.print(arr[i] + " ");
}
lasveg(arr, 50);
}
}
Output:
24 20 19 14 13 16 10 7 22 18 12 15 2 6 3 25 17 8 1 21 4 5 11 23 9 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 The repeated element is : 26
If you call this function with n = 50 and your array a got 50 elements
public static void lasveg(Integer a[],int n)
{
int i,j;
boolean chk= true;
while(chk)
{
i=(randomGenerator.nextInt())%n+1;
j=(randomGenerator.nextInt())%n+1;
if((i!=j)&&(a[i].equals(a[j])))
System.out.println("The repeated element is : " + i);
}
}
Whats happen there is if the random number is (50*x)-1 % 50 + 1 you calling a[50] thats throwing an out of range exception.
You aint want to increase the term rand % n then you get a range from 0 to 49.
Your i and j variables are assigned a random number in the segment from 0 to n, including n
i=(randomGenerator.nextInt())%n+1;
j=(randomGenerator.nextInt())%n+1;
In Java the index of the last element of array of n elements is n-1, so there is a possibility, that this statement
if((i!=j)&&(a[i].equals(a[j])))
System.out.println("The repeated element is : " + i);
will cause the index out of bound exception.
The problem that you have here it's that you have to notice that arrays starts at position 0.
array[0];
So, when you use your method lasveg you are setting the number 50 and really trying to access to the position 51 where you do a[i] and a[j] here:
if((i!=j)&&(a[i].equals(a[j])))
To fix your problem you will have to do:
lasveg(arr,49);
Another solution it's to avoid the + 1 in your Random. Change this:
i=(randomGenerator.nextInt())%n+1;
j=(randomGenerator.nextInt())%n+1;
to this:
i=(randomGenerator.nextInt())%n;
j=(randomGenerator.nextInt())%n;
I expect it will be helpful for you!

How to change position of the elements in an array

I'm writing a program, that take 10 Integers from a keyboard and list them in an array indexed from 0-9, and reports the position of the lowest number in the array. If the lowest number has any other position than 0, then the program is supposed to switch the position of the lowest number input with the number in the first position in the array:
import java.util.Scanner;
public class q35 {
public static void main(String args[]) {
Scanner tastatur = new Scanner(System.in);
int[] helTall = new int[10];
int input;
int lowest = Integer.MAX_VALUE;
for(int i=0;i<helTall.length;i++) {
System.out.println("Integers? ");
input = tastatur.nextInt();
if (input < lowest) {
lowest = input;
}
helTall[i] = input;
}
for (int i = 0; i < helTall.length; i++) {
helTall[0] = lowest;
System.out.println(helTall[i]);
}
System.out.println("Lowest number is " + lowest);
}
}
The only problem is that instead of changing position with the lowest number with the number at helTall[0], it just completely replaces the first number in the sequence helTall[0] with the lowest Integer, that way if my input is 4 5 63 23 6 -4 7 33 23 99, then the output becomes -4 5 63 23 6 -4 7 33 23 99 (as you can see the first input number is completely erased), but it should have been -4 5 63 23 6 4 7 33 23 99 any tips/advice/solutions? Thanks in advance.
You should keep track of the index of the lowest number (each time you write lowest = input; you should add lowestIndex=i;.
Then helTall[lowestIndex] will be the lowest number.
So you swap helTall[lowestIndex] with helTall[0] instead of just overwriting the value of helTall[0].
I thought it was enough to describe the solution in words, but I guess it wasn't...
int lowest = Integer.MAX_VALUE;
int lowestIndex = 0;
for(int i=0;i<helTall.length;i++){
System.out.println("Integers? ");
input = tastatur.nextInt();
if (input < lowest){
lowest = input;
lowestIndex = i;
}
helTall[i]=input;
}
// swap the numbers
if (lowestIndex > 0) {
int temp = lowest;
helTall[lowestIndex] = helTall[0];
helTall[0] = temp;
}
// display output
for (int i = 0; i < helTall.length; i ++) {
System.out.println(helTall[i]);
}
This part is wrong:
for (int i = 0; i < helTall.length; i ++) {
helTall[0]=lowest;
System.out.println(helTall[i]);
}
First, you do not need to repeatedly (10 times) put lowest into helTall[0]. Let's move that outside first so it's only done once:
helTall[0]=lowest;
for (int i = 0; i < helTall.length; i ++) {
System.out.println(helTall[i]);
}
Next, the line we put outside the loop overwrites the helTall[0] without regard for what is already in there. We need to temporarily save that number in there elsewhere, then overwrite the spot, so that we can use it to overwrite the spot where the lowest number was:
int numberAtLocationZero = helTall[0];
helTall[0]=lowest;
// Now, on this line we need to write helTall[lowestNumberIndex] = numberAtLocationZero;
for (int i = 0; i < helTall.length; i ++) {
System.out.println(helTall[i]);
}
In the above code I wrote a comment. It relies on you either knowing where in the array the lowest number was, or to find it again. If you add a new variable to your code that takes in values called lowestNumberIndex and update that each time you detect a new lowest number, then you're pretty much done if you uncomment my comment.
You need a separate variable to store what is in the bottom of the array before you overwrite it with your new lowest input number.
helTall[0]=lowest;
should be proceeded by
int placeholder = helTall[0]
and followed by
hellTall[i] = placeholder;
This way, you'll end up swapping the two array elements, the first swapped with the lowest. Is this what you're trying to accomplish? This leaves most of the array unsorted.

Need help writing numbers in the Reverse ORDER

I need some help with this assignment I've been given. Not asking anyone to do my work but I'm really honestly stuck on how to even do this.
I'm supposed to write a program that prompts the user to enter 10 numbers and then have it write all the numbers in reverse order.
Example:
Enter 10 Numbers: 23 89 21 55 67 89 99 13 98 78
Reverse Order: 78 98 13 99 89 67 55 21 89 23
So far all I have is how to get the user inputs. If anyone can push me in the right direction, i'd be very grateful!
import java.util.*;
public class ReverseNumbers
{
public static void main(String[] args)
{
Scanner keyboard = new Scanner(System.in);
int[] values;
values = new int[10];
//Ask the user to enter 10 integers
System.out.println("Please enter 10 numbers:");
for (int i = 0; i< values.length; i++)
{
values[i] = keyboard.nextInt();
}
int[] reverseNums;
reverseNums = new int[10];
for (int i = (values.length -1); i>= 0; i--)
{
reverseNums[ reverseNums.length -1 -i ] = values[ i ];
System.out.println( reverseNums[ i ] );
}
}
}
If you dont want to store the reversed values
for (int i = (values.length -1); i>= 0; i--)
{
System.out.println( values[ i ] );
}
Your code looks good for reading inputs into values. Now you can loop over that array in reverse and print the values:
for (int i = 0; i < values.length; i++)
System.out.println(values[values.length - i - 1]);
Think about it, when i == 0 it will print values[9] since 10 - 0 - 1 = 9. At the end, when i == 9 it will print values[0] since 10 - 9 - 1 = 0.
As you can see, there is no need for the extra reverseNums array.
PS: If you want, you can combine int[] values; and values = new int[10]; into a single line: int[] values = new int[10];
Read in the whole line as a string using Scanner.nextLine(), and then split it into an array using String.split(" ");. After this, you can simply iterate from the end of the array going backwards and print the numbers.
If it's not an assignment then why not try using http://commons.apache.org/proper/commons-lang/ library
ArrayUtils.reverse(int[] array)
I think your code is creating the array correctly. You are just printing out the numbers in the original order because your second for-loop is iterating over them backwards. You can see the correct result by adding the statement below after the last loop:
System.out.println(java.util.Arrays.toString(reverseNums));
You can also perform the complete task with only one iteration:
Scanner keyboard = new Scanner(System.in);
int[] reverseNums= new int[10];
System.out.println("Please enter 10 numbers:");
for (int i = 0; i< values.length; i++) {
reverseNums[values.length -1 - i] = keyboard.nextInt();
}
System.out.println(java.util.Arrays.toString(reverseNums));
To reverse it:
for (int i = 0; i < values.length; i++)
reverseNums[values.length - i - 1] = values[i];

How to add values beside elements in an array in bubble sort algorithm in java

Hi I have the following bubble sort algorithm (generic code taken from another site) and I would like to have numbers next to each element of the array as it gets sorted. For example when I run it and it sorts out the array, next to each element it should have the number 1 as this is the first of many sorting algorithms I am using. So to demonstrate:
My results after sorting will look like:
4 1
27 1
54 1
321 1
542 1
654 1
887 1
1023 1
As you can see, the number 1 is inserted into the each element of the array as it is being sorted in the algorithm. Can someone help me with this?
Sorting algorithm:
public static <E extends Comparable<? super E>> void bubbleSort(E[] comparable) {
boolean changed = false;
do {
changed = false;
for (int a = 0; a < comparable.length - 1; a++) {
if (comparable[a].compareTo(comparable[a + 1]) > 0) {
E tmp = comparable[a];
comparable[a] = comparable[a + 1];
comparable[a + 1] = tmp;
changed = true;
}
}
} while (changed);
}
After you have sorted do the following to print:
for (int i = 0 ; i < comparable.length ; i++){
System.out.println(comparable[i] + " 1" );
}

Categories