Java - Sorting ArrayList - Bubble Sort - java

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);`
}

Related

when filling a 2d array it gets null values

Im trying to initialise all the elements of the 2d array into a string "EMPTY". but When ever I try to initialise the array it gets null values. I checked errors in the for loop but couldn't see any
public static void arr_2d(){
String [][] arr = new String[3][2];
for (int i = 0; i < arr.length; i++) {
for (int a = 0; a < arr[i].length; a++) {
arr[i][a] = "EMPTY";
}
for (int b = 0; b < arr.length; b++) {
for (int j = 0; j < arr[b].length; j++) {
System.out.print(arr[b][j] + " ");
}
System.out.println();
}
}
}
Your loops are nested wrongly, which will result in the filling process not being complete while you're trying to process its results. You need
public static void arr_2d() {
String[][] arr = new String[3][2];
for (int i = 0; i < arr.length; i++) {
for (int a = 0; a < arr[i].length; a++) {
arr[i][a] = "EMPTY";
}
}
for (int b = 0; b < arr.length; b++) {
for (int j = 0; j < arr[b].length; j++) {
System.out.print(arr[b][j] + " ");
}
System.out.println();
}
}
Actually for(int b) is in for(int i); that's why you observe null values. If you move for(int b) outside of for(int i), there will be no null values.
public static void arr_2d(){
String [][] arr = new String[3][2];
for (int i = 0; i < arr.length; i++) {
for (int a = 0; a < arr[i].length; a++) {
arr[i][a] = "EMPTY";
}
}
for (int b = 0; b < arr.length; b++) {
for (int j = 0; j < arr[b].length; j++) {
System.out.print(arr[b][j] + " ");
}
System.out.println();
}
}
Check the comments given below in the snippet:
public static void arr_2d(){
String [][] arr = new String[3][2];
for (int i = 0; i < arr.length; i++) {
for (int a = 0; a < arr[i].length; a++) {
arr[i][a] = "EMPTY";
// you can have the sysout statement here as well instead of having looping the entire array again.
System.out.print(arr[i][a] + " ");
}
// this loop must be executed separately inorder to check values present in the array or else you can have a sysout statement when assigning the "empty" value in the array.
for (int b = 0; b < arr.length; b++) {
for (int j = 0; j < arr[b].length; j++) {
System.out.print(arr[b][j] + " ");
}
System.out.println();
}
}
}
Although the answers you have are correct I will add that one problem is your code style is prone to errors.
Your mistake was traversing the array incorrectly. The correct way is traversing the array twice, one of filling and another for printing, but instead it seems you have attempted to do everything in one shot. That mistake can be avoided with a better code style.
This is how I would have written your code in imperative style:
String[][] arr = new String[3][2];
for (String[] a : arr)
Arrays.fill(a, "EMPTY");
for (String[] a : arr)
System.out.println(Arrays.toString(a));
Notice the code is much shorter, so there's less chances of mistakes. It's also a lot more obvious that you're traversing twice.
Instead of traversing an array explicitly:
for (int i = 0; i++; i < arr.length())
Use the implicit for loop:
for (String[] value: arr)
Instead of filling an array explicitly:
for (int a = 0; a < arr[i].length; a++) {
arr[i][a] = "EMPTY";
}
Use the already provided fill method:
Arrays.fill(value, "EMPTY");
Instead of printing an array explicitly:
for (String string : strings) {
System.out.print(string + " ");
}
System.out.println();
Use the already provided print method:
for (String[] a : arr)
System.out.println(Arrays.toString(a));
However, I would have written in functional style:
String [][] arr = new String[3][2];
Arrays.stream(arr)
.forEach(a -> Arrays.fill(a, "EMPTY"));
Arrays.stream(arr)
.map(Arrays::toString)
.forEach(System.out::println);
One particular advantage is that you are encouraged to think in a more abstract way. Instead of thinking how to explicitly set or print each element of the array, you are encouraged to use methods that implicitly traverse, transform or perform generic computations on all elements of the array.

Is this a selection sort or a bubble sort?

Is this a selection sort? I think it is Bubble Sort because I'm using (dot)compareTo. I look at different sources on the internet so I can make one. Here is the codes.
import java.util.Arrays;
public class SelectionSort {
public static void main(String args[]) {
String[] row = {"apple", "orange", "banana", "grapes", "mango", "avocado"};
int min = row.length;
for(int m = 0; m < min-1; m++) {
for (int n = m+1; n < row.length; n++) {
if(row[m].compareTo(row[n]) > 0){
String bar = row[m];
row[m] = row[n];
row[n] = bar;
}
}
}
System.out.println("Expected Outcome: " + Arrays.toString(row));
}
}
this is not selection sort
I selection sort in each iteration you find minimum value and put it to the proper location. See this picture
A simple implementation show here:
https://www.javatpoint.com/selection-sort-in-java
public class SelectionSortExample {
public static void selectionSort(int[] arr){
for (int i = 0; i < arr.length - 1; i++)
{
int index = i;
for (int j = i + 1; j < arr.length; j++){
if (arr[j] < arr[index]){
index = j;//searching for lowest index
}
}
int smallerNumber = arr[index];
arr[index] = arr[i];
arr[i] = smallerNumber;
}
}
public static void main(String a[]){
int[] arr1 = {9,14,3,2,43,11,58,22};
System.out.println("Before Selection Sort");
for(int i:arr1){
System.out.print(i+" ");
}
System.out.println();
selectionSort(arr1);//sorting array using selection sort
System.out.println("After Selection Sort");
for(int i:arr1){
System.out.print(i+" ");
}
}
}
It is not Selection Sort (Milad already answered this), but it is also not Bubble Sort.
The way you can tell that it is not bubble sort, is because bubble sort compares pairs of items that are next to each-other (ex: compares items at index 0-1, 1-2, 2-3... and swaps if necessary). In your code, when m=0, the inner loop will compare item at index 0 with all the other items in the array.
Bubble Sort in Java:
public void sort( int[] array) {
boolean isSorted;
for (var i = 0; i < array.length; i++) {
isSorted = true;
for (var j = 1; j < array.length - i ; j++)
if (array[j] < array[j - 1]) {
swap(array, j, j - 1);
isSorted = false;
}
if (isSorted)
return;
}
}
private void swap(int[] array, int index1, int index2) {
var temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}

Basic Bubble Sort with ArrayList in 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;
}
}

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: Combination of recursive loops which has different FOR loop inside; Output: FOR loops indexes

currently recursion is fresh & difficult topic for me, however I need to use it in one of my algorithms.
Here is the challenge:
I need a method where I specify number of recursions (number of nested FOR loops) and number of iterations for each FOR loop. The result should show me, something simmilar to counter, however each column of counter is limited to specific number.
ArrayList<Integer> specs= new ArrayList<Integer>();
specs.add(5); //for(int i=0 to 5; i++)
specs.add(7);
specs.add(9);
specs.add(2);
specs.add(8);
specs.add(9);
public void recursion(ArrayList<Integer> specs){
//number of nested loops will be equal to: specs.size();
//each item in specs, specifies the For loop max count e.g:
//First outside loop will be: for(int i=0; i< specs.get(0); i++)
//Second loop inside will be: for(int i=0; i< specs.get(1); i++)
//...
}
The the results will be similar to outputs of this manual, nested loop:
int[] i;
i = new int[7];
for( i[6]=0; i[6]<5; i[6]++){
for( i[5]=0; i[5]<7; i[5]++){
for(i[4] =0; i[4]<9; i[4]++){
for(i[3] =0; i[3]<2; i[3]++){
for(i[2] =0; i[2]<8; i[2]++){
for(i[1] =0; i[1]<9; i[1]++){
//...
System.out.println(i[1]+" "+i[2]+" "+i[3]+" "+i[4]+" "+i[5]+" "+i[6]);
}
}
}
}
}
}
I already, killed 3 days on this, and still no results, was searching it in internet, however the examples are too different. Therefore, posting the programming question in internet first time in my life. Thank you in advance, you are free to change the code efficiency, I just need the same results.
// ...
recursion (specs, specs.size () - 1);
// ...
public void recursion(ArrayList<Integer> specs, int startWith){
for (int i = 0; i < specs.get(startWith); i++) {
// ...
if (startWith - 1 >= 0)
recursion (specs, startWith - 1);
}
}
Your function also need to now the index of the specs array to use for iteration, and also the previous numbers that should be printed:
public void recursion(ArrayList<Integer> specs, int index, String output) {
if( index >= specs.size() ) {
System.out.println(output);
return;
}
for (int i = 0; i < specs.get(index); i++ )
recursion( specs, index+1, Integer.toString(i) + " " + output );
}
The you should call it like this:
ArrayList<Integer> specs= new ArrayList<Integer>();
specs.add(5);
specs.add(7);
specs.add(9);
specs.add(2);
specs.add(8);
specs.add(9);
recursion( specs, 0, "" );
Does this snippet give the output you want? (It is compileable and executeable)
import java.util.ArrayList;
import java.util.List;
public class SO {
static ArrayList<Integer> specs = new ArrayList<Integer>();
static int[] i;
public static void main(String[] args) throws Exception {
specs.add(5); //for(int i=0 to 5; i++)
specs.add(7);
specs.add(9);
specs.add(2);
specs.add(8);
specs.add(9);
i = new int[specs.size()];
printMe(0, specs, i);
}
static void printMe(int depth, List<Integer> _specs, int[] i) {
if (_specs.isEmpty()) {
System.out.println(printI(i));
return;
} else {
for (int j = 0; j < _specs.get(0); j++) {
i[depth] = j + 1; // + 1 since you seems to want to go from 1 and not 0
printMe(depth + 1, _specs.subList(1, _specs.size()), i);
}
}
}
static String printI(int[] i) {
StringBuilder sb = new StringBuilder();
for (int j = 0; j < i.length; j++) {
sb.append(i[j]);
if (j < i.length - 1) {
sb.append(" ");
}
}
return sb.toString();
}
}
You can try this :
public static void loops(ArrayList<Integer> specs, int idx, StringBuilder res){
if(idx==specs.size()-1){
for (int i = 0; i < specs.get(idx); i++) {
System.out.println(i+" "+res);
}
}
else{
for(int i=0;i<specs.get(idx);i++){
res.insert(0,i+" ");
loops(specs,idx+1,res);
res.delete(0, 2);
}
}
}
And call with :
ArrayList<Integer> specs= new ArrayList<Integer>();
specs.add(5); //for(int i=0 to 5; i++)
specs.add(7);
specs.add(9);
specs.add(2);
specs.add(8);
specs.add(9);
loops(specs,0, new StringBuilder());

Categories

Resources