Basic Bubble Sort with ArrayList in Java - java

I was implementing a comparator, and it wasn't working, so I thought I'd write a basic bubble sort.
int[] numbers = { 5, 8, 14, 1, 5678 };
int tempVar;
for (int i = 0; i < numbers.length; i++)
{
for(int j = 0; j < numbers.length; j++)
{
if(numbers[i] > numbers[j + 1])
{
tempVar = numbers [j + 1];
numbers [j + 1]= numbers [i];
numbers [i] = tempVar;
}
}
}
for (int i = 0; i < numbers.length; i++)
{
System.out.println(numbers[i].toString());
}
Is this tutorial correct at all?
https://blog.udemy.com/bubble-sort-java/
I followed the example and applied it to Last Names in an arraylist, but the results are a bit wack.
String a;
String b;
Person c;
Person d;
for (int i=0; i< list.size(); i++){
for(int j=0; j< list.size()-1; j++){
a = list.get(i).getLastName();
b = list.get(j+1).getLastName();
c = list.get(i);
d = list.get(j+1);
if ( a.compareTo(b) < 0 ) {
Person temp = d;
list.set(j+1, c);
list.set(i, temp);
}
}
}
I'd really like to get a grip on a few methods (like figuring out why my comparator didn't work), but right now I'd just like to get a Bubble Sort to work correctly. Thanks.

In Bubble sort you need to compare only the adjacent elements and swap them(depending up on the condition).
If you are doing ascending order than comparing the adjacent elements and swap if(arr[j]>arr[j+1]).
This moves the largest elements to the end in the first iteration.Thus there are n-1 iterations in outer loop to sort the array where n is the length of the array.
Read this first Bubble sort as the tutorial you mentioned is completely wrong
Corrected code
for (int i = 0; i < numbers.length-1; i++)
{
for(int j = 0; j < numbers.length-i-1; j++)
{
if(numbers[j] > numbers[j + 1])
{
tempVar = numbers [j + 1];
numbers [j + 1]= numbers [j];
numbers [j] = tempVar;
}
}
}
Here is the working link

This is a strange and inefficient implementation, you compare each number which each other. Something like this is much more intuitive (could be improved a little performance-wise, but that is not the point, you will just save a lot of time not accidently making mistakes with the indices and if you really care about performance and not readability use mergesort or quicksort as Java does [Java is using quicksort for primitive types and mergesort for Objects, probably because for primitive types it doesn't matter if the algorithm is stable or not]):
public void bubbleSort(int[] arr) {
boolean change;
do {
change = false;
for (int i = 0; i < arr.length - 1; i++) {
if (arr[i] > arr[i + 1]) {
int temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
change = true;
}
}
} while (change);
}
Applied to your code (sorts ascending):
boolean change;
do {
change = false;
for (int i = 0; i < list.size() - 1; i++) {
c = list.get(i);
d = list.get(i + 1);
a = c.getLastName();
b = d.getLastName();
// add special comparison for null values if a or b can be null ("" is ok)
// toLowerCase() is to compare case-insensitive ('a' != 'A')
if (a.toLowerCase().compareTo(b.toLowerCase()) > 0) {
list.set(i, d);
list.set(i + 1, c);
change = true;
}
}
} while (change);
Sidenote: s.toUpperCase().compareTo(s.toLowerCase()) == 0 would be true if s only contains symbols.

Thanks to everyone for pointing me in the right direction.
One problem was I forgot to .trim() so compareTo wasn't working and neither was comparing with charAt(0).
Also, I found a better implementation of loops for Bubble-Sort.
This is what now works:
String a;
String b;
Person c;
Person d;
for (int i= 0; i< list.size() ; i++){
for(int j=0; j< list.size() - i-1; j++){
a = list.get(j).getLastName().toUpperCase().trim();
b = list.get(j+1).getLastName().toUpperCase().trim();
c = list.get(j);
d = list.get(j+1);
if ( a.compareTo(b) > 0) {
Person temp = d;
list.set(j+1, c);
list.set(j, temp);
}
}

If you write,
for(int j = 0; j < numbers.length; j++)
Then, you will get ArrayIndexOutOfBoundsException for the following line,
tempVar = numbers [j + 1];
Because, the array numbers has length 5 with last index 4 (as index starts from 0). So, when j = 4, the loop breaking condition j < numbers.length or 4 < 5 is true, but you will get exception accessing numbers [4 + 1] index.
So try
for(int j = 0; j < numbers.length -1; j++)
or
for(int j = i; j < numbers.length -1; j++) // more efficient
Now for the second snippet of your code, can you tell me what exactly the problem you get?
From a wild guess, your a.compareTo(b) < 0 is not working like what you want.
Note that compareTo returns a value less than 0 if string a is lexicographically less than the string b.
I'm confused what exactly you want, hence produces the following code which may help you to overcome your problem:
import java.util.ArrayList;
public class Sort{
private static ArrayList<String> list = new ArrayList<String>();
public static ArrayList<String> sortByName(String [] input) {
String temp;
for (int i=0; i< input.length; i++){
for(int j= i; j< input.length-1; j++){
char first = input[i].charAt(0);
char sec = input[j +1].charAt(0);
if (first < sec) {
temp = input[j +1];
input[j +1] = input[i];
input[i] = temp;
}
}
list.add(input[i]);
}
return list;
}
public static void main(String[] args) {
String string[] = {"Ezen", "Allen" , "Wilker", "Kruden", "Crocket"};
bubbleSortByName(string);
}
}
Output is a list containing:
list = [Wilker, Kruden, Ezen, Crocket, Allen]

Bubble Sort Swap Printer in JAVA:
static void countSwaps(int[] a) {
int swaps = 0;
for(int i=0; i<a.length-1; i++){
for(int j=0; j<a.length-i-1; j++){
if (a[j] > a[j+1]){
int temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
swaps++;
}
}
}
System.out.println("Array is sorted in " + swaps +" swaps.");
}

There is a small problem with the sort program you used originally.
int j=0
should be
int j=i
Also you didn't exactly replace it for string sorting.
a.compareTo(b) < 0
should be
a.compareTo(b) > 0
Check this:
import java.util.*;
public class HelloWorld{
public static void main(String[] args){
ArrayList<Person> list = new ArrayList<Person>();
list.add(new Person("xyz"));
list.add(new Person("abc"));
list.add(new Person("pqr"));
list.add(new Person("lmn"));
String a;
String b;
Person c;
Person d;
for (int i=0; i< list.size(); i++){
for(int j=i; j< list.size()-1; j++){
a = list.get(i).getLastName();
b = list.get(j+1).getLastName();
c = list.get(i);
d = list.get(j+1);
if ( a.compareTo(b) > 0 ) {
Person temp = d;
list.set(j+1, c);
list.set(i, temp);
}
}
}
for(Person person: list){
System.out.println(person.lastName);
}
}
}
class Person{
String lastName;
Person(String str){
lastName = str;
}
public String getLastName(){
return lastName;
}
}

Related

Writing a program that, if given an array of characters, will output array that has the indices in order from largest to smallest (java)

So I'm working through a problem that if I have an array of characters it wants me to arrange them in order from largest to smallest but by the index not the actual letter. so ex, a[] = { 'a', 'z', 'p'} the output array would be like `b[] = {1 , 2, 0}
I understand how to sort the array of characters into descending order but now I'm confused on how to relate the two arrays together. I'm thinking I need to copy the original array into another array and then compare them someway. But im confused on the steps i need to take to get there. My sorting code is below just for reference. if anyone can help me out that would be great. Thanks
public static void main(String[]args){
char[] a ={'f','a','z','v','t','u','i','j','o','c'};
int[] b ;
// Sort a
for(int i= 0; i <= a.length-2;i++){
int maxindex = i;
for(int j = maxindex+1; j<a.length; j++){
if(a[j]>a[maxindex]){
maxindex = j;
}
}
// swap
char temp = a[i];
a[i] = a[maxindex];
a[maxindex] = temp;
}
for(int i = 0; i < a.length; i++){
System.out.print(a[i] + " ");
}
}
Hi! It was a bit more challenging than I thought. Here is what I did:
Make a copy from the original array.
Sort the original array.
Compare the two arrays so you can get the array with indexes
It's just like you thought. I think you could simplify the code using other types of structures, but it's fine if it is to practice java
char[] sorted = {'z','f','z','v','t','u','i','j','o','k','b'};
// Let's copy it
char[] copy = sorted.clone();
// initialize b as an array of integer with the same size as 'sorted' array
int[] b= new int[sorted.length];
// Sort your original array (this is your code)
for(int i= 0; i <= sorted.length-2;i++){
int maxindex = i;
for(int j = maxindex+1; j<sorted.length; j++){
if(sorted[j]>sorted[maxindex]){
maxindex = j;
}
}
// swap
char temp = sorted[i];
sorted[i] = sorted[maxindex];
sorted[maxindex] = temp;
}
// let's see what we got
for(int i = 0; i < sorted.length; i++){
System.out.print(sorted[i] + " ");
}
// now let's compare the original vs the sorted and get the indexes array
for(int i = 0; i < sorted.length; i++){
for(int k = 0; k < copy.length; k++){
if ((copy[k] == sorted[i] && i == 0) || (copy[k] == sorted[i] && k != b[i - 1]) ) {
b[i] = k;
break;
}
}
}
System.out.print("\n");
// let's see the indexes array
for(int i = 0; i < b.length; i++){
System.out.print(b[i] + " ");
}

Java : Selection Sort Logic

I am printing Sorted Array elements using Selection Sort. But I am getting my input array elements as output in same sequence without sorting.
public class SelectionSort {
public static void main(String[] args) {
int[] arr= {1,9,3,0,7};
int n=arr.length;
for(int i=0; i<n-1; i++)
{
int minimumIndex = i;
for(int j=i; j<n; j++)
{
if(arr[j]<arr[minimumIndex])
{
minimumIndex=j;
}
}
int temp=arr[i];
arr[i]=arr[minimumIndex];
arr[i]=temp;
}
for(int e: arr)
{
System.out.print(e+" ");
}
}
}
Expected o/p : 0 1 3 7 9
Actual o/p: 1 9 3 0 7
In Your method code, the actual problem is swapping elements,
the Sequence needs to be like this as below,
int temp=arr[minimumIndex];
arr[minimumIndex]=arr[i];
arr[i] =temp;
instead of
int temp=arr[i];
arr[i]=arr[minimumIndex];
arr[i]=temp;
There are two issues I see. One is the way you are swapping the items. You need to replace the item where you found the minimum index. Also, your J index should start one after your I index. You can assume that the one before it is the smallest as you are looping through. I have changed a few pieces of the code and tested it and it works fine for me.
for (int i = 0; i < arr.length - 1; i++)
{
int minimumIndex = i;
for (int j = i + 1; j < arr.length; j++)
{
if (arr[j] < arr[minimumIndex])
{
minimumIndex = j;
}
}
int temp = arr[i];
arr[i] = arr[minimumIndex];
arr[minimumIndex] = temp;
}

How do I remove duplicates from two arrays?

I need to have an algorithm that changes values in one array if it is in the second array. The result is that the first array should not have any values that are in the second array.
The arrays are of random length (on average ranging from 0 to 15 integers each), and the content of each array is a list of sorted numbers, ranging from 0 to 90.
public void clearDuplicates(int[] A, int[] B){
for(int i = 0; i < A.length; i++){
for(int j = 0; j < B.length; j++)
if(A[i] == B[j])
A[i]++;
}
}
My current code does not clear all of the duplicates. On top of that it might be possible it will creat an index out of bounds, or the content can get above 90.
Although your question is not very clear, this might do the job. Assumptions:
The number of integers in A and B is smaller than 90.
The array A is not sorted afterwards (use Arrays.sort() if you wish to
fix that).
The array A might contain duplicates within itself afterwards.
public void clearDuplicates(int[] A, int[] B) {
// Initialize a set of numbers which are not in B to all numbers 0--90
final Set<Integer> notInB = new HashSet<>();
for (int i = 0; i <= 90; i++) {
notInB.add(i);
}
// Create a set of numbers which are in B. Since lookups in hash set are
// O(1), this will be much more efficient than manually searching over B
// each time. At the same time, remove elements which are in B from the
// set of elements not in B.
final Set<Integer> bSet = new HashSet<>();
for (final int b : B) {
bSet.add(b);
notInB.remove(b);
}
// Search and remove duplicates
for (int i = 0; i < A.length; i++) {
if (bSet.contains(A[i])) {
// Try to replace the duplicate by a number not in B
if (!notInB.isEmpty()) {
A[i] = notInB.iterator().next();
// Remove the added value from notInB
notInB.remove(A[i]);
}
// If not possible, return - there is no way to remove the
// duplicates with the given constraints
else {
return;
}
}
}
}
You can do it just by using int[ ] although it's a bit cumbersome. The only constraint is that there may not be duplicates within B itself.
public void clearDuplicates(int[] A, int[] B) {
//Number of duplicates
int duplicate = 0;
//First you need to find the number of duplicates
for (int i = 0; i < A.length; i++) {
for (int j = 0; j < B.length; j++)
if (A[i] == B[j])
duplicate++;
}
//New A without duplicates
int[] newA = new int[A.length-duplicate];
//For indexing elements in the new A
int notDuplicate = 0;
//For knowing if it is or isn't a duplicate
boolean check;
//Filling the new A (without duplicates)
for (int i = 0; i < A.length; i++) {
check = true;
for (int j = 0; j < B.length; j++) {
if (A[i] == B[j]) {
check = false;
notDuplicate--;//Adjusting the index
}
}
//Put this element in the new array
if(check)
newA[notDuplicate] = A[i];
notDuplicate++;//Adjusting the index
}
}
public class DuplicateRemove {
public static void main(String[] args) {
int[] A = { 1, 8, 3, 4, 5, 6 };
int[] B = { 1, 4 };
print(clear(A, B));
}
public static int[] clear(int[] A, int[] B) {
int a = 0;
for (int i = 0; i < A.length; i++) {
for (int j = 0; j < B.length; j++) {
if (A[i] == B[j]) {
a++;
for (int k = i; k < A.length - a; k++) {
A[k] = A[k + 1];
}
}
}
}
int[] C = new int[A.length - a];
for (int p = 0; p < C.length; p++)
C[p] = A[p];
return C;
}
public static void print(int[] A) {
for (int i = 0; i < A.length; i++)
System.out.println("Element: " + A[i]);
}
}
Here is an example.. I compiled and its working. For any question just let me know :)
maybe you should try the following code:
public void clear (int[] A, int[] B)
{
for (int i=0; i<A.length;i++)
{
for (int j=0; j<B.length; j++)
if(A[i]==B[j])
{
for (int k=i; k<A.length;k++)
A[k]=A[k+1];
j=B.length-1; //so that the cycle for will not be executed
}
}
}

Java - Sorting ArrayList - Bubble Sort

I have to sort an arrayList containing the frequency of the purchases of customers. So I can display the output whether in an ascending or descending order. However, I am not quite sure what I am missing but it is not sorting the elements at all. I'd really appreciate any comments or feedback!
This is what I have so far:
for(int i=0; i<customers.size(); i++)
{
for(int k= i+1; k <customers.size(); k++)
{
if((customers.get(k)).compareTo(customers.get(i)) < 0)
{
Customer temp = customers.get(i);
customers.set(i, customers.get(k));
customers.set(k,temp);
}
}
System.out.println(customers.get(i));
}
keeping K = i, try this for your inner loop:
for(int k= i; k <customers.size() - i -1; k++)
{
this should work.
If you want to print the sorted list System.out.println(customers.get(i)); has to be outside of the sorting loop. Add another loop after that one to print the results
You had a few mistakes,
// I tested with List<String>, String temp.
public static void sort(List<Customer> customers) {
for (int i = 0; i < customers.size() - 1; i++) {
for (int k = i + 1; k < customers.size(); k++) {
// Compare left to right, not right to left.
if (customers.get(i).compareToIgnoreCase(customers.get(k)) > 0) {
Customer temp = customers.get(i);
customers.set(i, customers.get(k));
customers.set(k, temp);
}
}
}
}
When I tested with
public static void main(String[] args) {
String[] names = { "Bob", "bob", "Alice", "Bob",
"Carol" };
List<String> al = new ArrayList<String>(
Arrays.asList(names));
sort(al);
for (String str : al) {
System.out.println(str);
}
}
I got
Alice
bob
Bob
Bob
Carol
Try this
int n = yourArray.size();
for (int i = 0; i < n - 1; i++)
for (int j = 0; j < n - i - 1; j++)
if (yourArray.get(j) < yourArray.get(j + 1)) {
int temp = yourArray.get(j);
yourArray.set(j, yourArray.get(j + 1));
yourArray.set(j + 1, temp);`
}

Bubble sort is not sorting

I've written a code to input the name, day and time of a few shows, with the option to have it sorted (bubble sort) by day and name. I'm using 1.4.2 (because I have to) and an ArrayList along with a simple class.
I've been staring at this for hours, left and came back to it a bunch of times, but unfortunately, it isn't working! Any idea why?! Here's my code:
//method to sort and display info
public static void sortDay(){
for(int i = 0; i < show.size() - 1; i++) {
for(int j = 0; j < show.size() - 1; j++){
showInfo current = (showInfo)show.get(j);
showInfo next = (showInfo)show.get(j+1);
if (current.day.compareTo(next.day) < 0) {
showInfo temp = new showInfo();
temp.name = ((showInfo)show.get(j)).name;
temp.day = ((showInfo)show.get(j)).day;
temp.time = ((showInfo)show.get(j)).time;
((showInfo)show.get(j)).time = ((showInfo)show.get(i)).time;
((showInfo)show.get(j)).day = ((showInfo)show.get(i)).day;
((showInfo)show.get(j)).name = ((showInfo)show.get(i)).name;
((showInfo)show.get(i)).time = temp.time;
((showInfo)show.get(i)).day = temp.day;
((showInfo)show.get(i)).name = temp.name;
}
}
}
System.out.println("Show Information");
for (int i = 0; i < show.size(); i++){
System.out.println("Name: " + ((showInfo)show.get(i)).name);
System.out.println("Day: " + ((showInfo)show.get(i)).day);
System.out.println("Time: " + ((showInfo)show.get(i)).time);
}
}
Any help would be great! Thanks in advance!
First, I'll assume you're using some kind of List - likely an ArrayList.
That said, the main operations for Bubble Sort are described as follows:
Compare for ordering
Create temporary variable
Place left value into temporary variable
Place right value into left value
Place old left value into right value from temporary value
You're shuffling about the fields, which will lead to confusion and bugs. Use the above approach instead.
Here it is illustrated with generics (so you don't have to cast anymore), and a capital class name, as is the convention. I don't have a temporary variable in this example, as I already have a reference to current.
List<ShowInfo> show = new ArrayList<>(); // assume populated
public static void sortDay(){
for(int i = 0; i < show.size(); i++) {
for(int j = 0; j < show.size() && j != i; j++) {
ShowInfo current = show.get(i);
ShowInfo next = show.get(j);
// If the current day is greater than the next day, we need to swap.
// Adjust to suit your business logic (if current is less than next).
if (current.day.compareTo(next.day) > 0) {
show.set(i, next);
show.set(j, current);
}
}
}
}
For a generic way of doing this, perhaps you could try something like:
public static <T extends Comparable> void sort(final List<T> list){
boolean remaining;
do{
remaining = false;
for(int i = 0; i < list.size()-1; i++){
final T current = list.get(i);
final T next = list.get(i+1);
if(current.compareTo(next) < 0){
list.set(i, next);
list.set(i+1, current);
remaining = true;
}
}
}while(remaining);
}
How do you fix it?
I'm just answering your question: how to fix the code you posted. For "how to improve it?" all other answers are way better than whatever I can come up with.
There are two points:
swap on the same index, in the inner for (index j)
correct swapping: where you have j write j+1 and where you have i write j
the other for is just so it will iterate enough times to get it sorted in the worst case (suggestions in other answers go for a while, much better)
That being said, the swapping pseudocode is:
if (show[j] < show[j+1]) {
temp = j+1
j+1 = j
j = temp
}
And here is the swapping code with the fixes:
if (current.day.compareTo(next.day) < 0) {
showInfo temp = new showInfo();
temp.name = ((showInfo)show.get(j+1)).name;
temp.day = ((showInfo)show.get(j+1)).day;
temp.time = ((showInfo)show.get(j+1)).time;
((showInfo)show.get(j+1)).time = ((showInfo)show.get(j)).time;
((showInfo)show.get(j+1)).day = ((showInfo)show.get(j)).day;
((showInfo)show.get(j+1)).name = ((showInfo)show.get(j)).name;
((showInfo)show.get(j)).time = temp.time;
((showInfo)show.get(j)).day = temp.day;
((showInfo)show.get(j)).name = temp.name;
}
And here is the printed result (assuming day - time - name for each show, so we are sorting on the first int):
Show Information before sort
610 - -72 - 1402
838 - -184 - 1096
-478 - 248 - 934
709 - 832 - -590
2007 - 954 - -315
Show Information after sort
2007 - 954 - -315
838 - -184 - 1096
709 - 832 - -590
610 - -72 - 1402
-478 - 248 - 934
public class myBubbleSort
{
private static int[] a;
public static void main(String[] args)
{
getArray(10);
System.out.println("Array before sorting");
printArray();
ascendingBubble();
System.out.println("Array after ascending sort");
printArray();
descendingBubble();
System.out.println("Array after descending sort");
printArray();
System.out.println();
System.out.println("Random sort");
getArray(10);
bubbleSort(true);
System.out.println("Array after Random sort");
printArray();
}
// print the number in random array
public static void printArray()
{
for (int i : a)
{
System.out.print(i + " ");
}
System.out.println();
}
// generate a random array to be sorted in ascending and descending order
public static void getArray(int size)
{
a = new int[size];
int item = 0;
for (int i = 0; i < size; i++)
{
item = (int) (Math.random() * 100);
a[i] = item;
}
}
// sort getArray in ascending order and bubblesort it
public static void ascendingBubble()
{
int temp;
System.out.println();
System.out.println("Ascending sort");
for (int i = 0; i < a.length - 1; i++)
{
for (int j = 0; j < a.length - 1; j++)
{
if (a[j] > a[j + 1])
{
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
bubbleSort(true);
}
// sort getArray in descending order and bubblesort it
public static void descendingBubble()
{
int temp;
System.out.println();
System.out.println("Descending sort");
for (int i = 0; i < a.length - 1; i++)
{
for (int j = 0; j < a.length - 1; j++)
{
if (a[j] < a[j + 1])
{
temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
bubbleSort(true);
}
// bubble sort algorithm
public static void bubbleSort(boolean printTime)
{
boolean sorted = false;
int pass = 1;
int temp;
long startTime;
long endTime;
long duration;
startTime = System.nanoTime();
while (pass < a.length - 1 && (!sorted))
{
sorted = true;
for (int i = 0; i < a.length - 1; i++)
{
if (a[i] > a[i + 1])
{
temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
sorted = false;
}
}
pass = pass + 1;
}
endTime = System.nanoTime();
duration = (endTime - startTime);
if(printTime)
{
System.out.println(duration + " "+ " nano seconds");
}
}
}

Categories

Resources