Descending Selection Sort of Object Array in Java - java

I'm currently working on a Bank Account program that takes user input and enters it into an array. It performs actions like deposit, withdraw, search, etc. I'm currently stuck utilizing a selection sort based on the balance amounts in each account. The program should sort the accounts based on balance from highest to lowest and print the results to the screen.
This is my first time using selection sort and one of my first few times using arrays. I understand the concept of selection sort and how to do it with primitive values, but translating that to object values is stumping me. Below is the code I have for the selection sort.
if (out.equals("Sort")) {
int i, j, maxIndex;
double maxValue;
//getNumberOfAccounts is a static counter incremented each time
//a new bank account is created
for (i = 0; i < BankAccount.getNumberOfAccounts(); i++) {
//Sets first value as largest
maxValue = BankAccounts[i].getBalance();
maxIndex = i; //Index of first value
for (j = i; j == BankAccount.getNumberOfAccounts(); j++) {
//Compares subsequent values to initial max value
if (BankAccounts[j].getBalance() > maxValue) {
maxValue = BankAccounts[j].getBalance();
maxIndex = j;
}
}
//Attempts to swap values
BankAccount temp = BankAccounts[i];
BankAccounts[i] = BankAccounts[maxIndex];
BankAccounts[maxIndex] = temp;
//Outputs Bank Account data in descending order based on balance
BankAccounts[maxIndex].printReport();
}
}
Notes:
-This is a portion of the full program so if I'm missing a bracket it's just because I didn't copy the whole thing.
-It seems that when I run the program it does not store the maxValue; the output of maxValue instead outputs whichever value of the loop iteration is next.
-When I run the program it simply prints the bank accounts in the exact order I enter them.
Thank you in advance and if there's any more information I can provide I gladly will.

When you're doing BankAccounts[maxIndex].printReport();, you've already swap the values. So you're printing the value in position maxIndex, and there is already item that was at position i at the beginning of current step.
So, you need to do BankAccounts[maxIndex].printReport(); before swap, or print the value from the right position — BankAccounts[i].printReport();
About maxValue — it's updates each step, so if you need this after cycle ends, you can just get it as BankAccounts[0].getBalance() after sort routine ends.
Moreover, if you need only to sort items, but you're not tied to use selection sort, I'd like to recommend Java built-in methods for sort, so your code should look like this:
Arrays.sort(BankAccounts, 0, BankAccount.getNumberOfAccounts(), new Comparator<BankAccount>() {
#Override
public int compare(BankAccount o1, BankAccount o2) {
if (o1.getBalance() > o2.getBalance()) return -1;
if (o1.getBalance() < o2.getBalance()) return 1;
return 0;
}
}
);
After this sort operation, array BankAccounts is sorted in descending order of balances, and you can print reports just in a simple loop:
for (i = 0; i < BankAccount.getNumberOfAccounts(); i++) {
BankAccounts[i].printReport;
}

First you need to change this line
for (j = i; j == BankAccount.getNumberOfAccounts(); j++) {
to
for (j = i; j < BankAccount.getNumberOfAccounts(); j++) {
The way you have it now you're saying "loop until j is equal to BankAccount.getNumberOfAccounts()" and that’s never gonna happen in this code.
Another performance issue that you have.
BankAccount temp = BankAccounts[i];
BankAccounts[i] = BankAccounts[maxIndex];
BankAccounts[maxIndex] = temp;
Imagen that the current index is already in the right spot. You will make an unnecessary "switch".
For example: current intex ( i == 5 ) biggest balance position ( maxIndex == 5 ).
You will have:
BankAccount temp = BankAccounts[5];
BankAccounts[5] = BankAccounts[5];
BankAccounts[5] = temp;
So you can change this part to this:
if(i != maxIndex) {
//Attempts to swap values
BankAccount temp = BankAccounts[i];
BankAccounts[i] = BankAccounts[maxIndex];
BankAccounts[maxIndex] = temp;
}

After following a couple of old related threads I stumbled upon a thread that perfectly answered my question. While the Array.sort method mentioned above worked perfectly, I was uncomfortable using it simply because I have not yet learned about it.
if (out.equals("Sort")){
for (int i = 0; i < BankAccount.getNumberOfAccounts(); i++){
for(int j = i+1; j < BankAccount.getNumberOfAccounts(); j++){
if(BankAccounts[j].getBalance() > BankAccounts[i].getBalance()){
BankAccount [] temp = new BankAccount [BankAccounts.length];
temp [j] = BankAccounts [j];
BankAccounts [j] = BankAccounts [i];
BankAccounts [i] = temp [j];
}
}
}
for (int i = 0; i < BankAccount.getNumberOfAccounts(); i++){
BankAccounts[i].printReport();
System.out.println();
}
Here's the code that printed the results I've been looking for. I realized my comparison in the inner loop was off and I wasn't creating a new array for the swap, only new objects. Thanks for all the help!

Related

Selection sort: storing value instead of index

I'm studying sorting algorithms, including selection sort, so i decided to write a method and it works fine, but when i checked the book it had 2 variables so i checked it and found that it's using a variable to store the current index and the other as temporary to swap
while mine had only the temporary variable that also stored the initial value in the index as the lowest, then compared it to the other values in the array and swapped if a larger value was found.
Here's my code:
public static void selectionSort(int[] arr){
int lowest;
for(int i = 0; i < arr.length - 1; i++){
lowest = arr[i];
for(int j = i+1; j<arr.length; j++){
if(arr[j]<lowest){
lowest = arr[j];
arr[j] = arr[i];
arr[i] = lowest;
}
}
}
}
and Here's the book's
public static void selectionSort(int[] list){
int min;
int temp;
for(int i = 0; i < list.length - 1; i++) {
min = i;
for(int j = i + 1; j < list.length; j++)
if( list[j] < list[min] )
min = j;
temp = list[i];
list[i] = list[min];
list[min] = temp;
}
}
so I looked on the web and all of them follow the same way as the book, so is my code bad or slower, or it is not considered Selection sort ?
sorry for any english mistakes :P
So, the original code works like this:
Start with the first element of the array
Find the smallest number in the array
Swap the two numbers
Repeat the process Until You reach the end of the list
While Yours does this:
Start with the first element of the array
For each element smaller than the current Swap the two numbers
Replace the lowest number with the swapped
Repeat the process
The result should be the same, but probably You are swapping more numbers than the first one. This probably will make it a little bit slower than the original.
Actually it kinda looks like the insertion sort now, so basically You are swapping the elements with all that are bigger than the one You have.
It looks like you're doing a lot more swaps in the nested for loop.
What happens if you do a sort of [4,3,2,1]? I think you'll have more swap operations than the actual selectionSort.
I'm not sure if your code is bad or slower.
SelectionSort is known to be correct, but it isn't fast either.

Ordering a list of 10 numbers

I have an atomic integer array of size 10. I am using this array to organize numbers 1-10 sent in by threads. This 1-10 will eventually be able to change to be a range of numbers larger than 10 and the list is to contain the 10 greatest numbers in that range. I can see the numbers going into the loops and recognizing that they are greater than a number currently there. However, there is never more than 2 numbers in the array when it is printed out. I have tried to trace my code in debug mode, however, it looks as if it is working as intended to me. I feel like there may be a simple error to my logic? I am completely sure all values are entering in the function as I have triple checked this. I start at the end of the array which should contain the highest value and then swap downwards once the slot has been determined. I would appreciate the assistance. This is just a simple experiment I am doing in order to grasp the basics before I try to tackle a homework assignment.
Here an example of my code:
public class testing{
static AtomicIntegerArray maxList = new AtomicIntegerArray(10);
final static int n = 10;
static void setMax(int value)
{
for(int i = 9; i >= 0; i--)
{
if(value > maxList.get(i))
{
int temp = maxList.get(i);
maxList.set(i,value);
if(i == 0)
{
maxList.set(i, value);
}
else
{ for(int j = i-1; j > 0; j--)
{
maxList.set(j, temp);
temp = maxList.get(j-1);
}
}
break;
}
}
public static void main(String[] args)
{
for (int i = 0; i < n; i++)
{
setMax(i);
}
}
}
Here is an example of how it is being called:
Brooke, there is a small bug in your 'j' loop. You had saved the state of a variable (temp), however your logic in the j loop lost the state. This new logic preserves the state of the previous element in the list.
Try this:
for (int j = i - 1; j >= 0; j--) {
int t2 = maxList.get(j);
maxList.set(j, temp);
temp = t2;
}

How can you show how positions have changed after selection sort?

I coded a selection sort program and I was wondering if I wanted to add-on to it by showing how the positions of the values have changed, if it would be possible?
this is my selection sort code
import java.util.Scanner;
public class SelectionSort {
public static void main(String args[]) {
// int[] arr = {5,4,3,2,1}; // This is my array
int min = 0;
Scanner sc = new Scanner(System.in);
System.out.println("No of elements : ");
int noOfElements = sc.nextInt();
int[] arr = new int[noOfElements];
System.out.println("Give elements : ");
for (int i = 0; i < noOfElements; i++) {
arr[i] = sc.nextInt();
}
for (int i = 0; i < arr.length; i++) {
// Assume first element is min
min = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[min]) {
min = j;
}
}
int temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
System.out.println("Sorted Elemenst : " + arr[i]);
}
}
}
If you are trying to get array after each iteration, then you should print at the end of each iteration using Arrays#toString() to print complete array
for (int i = 0; i < arr.length; i++) {
...
.....
int temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
System.out.println("Sorted Elements : " + Arrays.toString(arr));
}
I don't know if your 'task' is to write your own sort method, but if you are looking for sorting an array you should use this:
public static void main(String[] args) {
int[] arr = {5,4,3,2,1};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
Never assume what a User might enter and therefore never assume that the first entry will be the minimum value.
This question has been showing up a lot in StackOverflow and therefore I can only assume this is homework. With this in mind I'm sure the assignment intent is to accept a specific number of random integer values from the User, place those values into a Integer Array, then sort that array in ascending order. While the sorting process is taking place show (display in console) what steps are taking place (which values are swapped within the array).
Here's a tip, research the Bubble Sort and the little bit of code it takes to accomplish the sorting task of Integer numbers within a Integer Array. In general a Bubble Sort utilizes two for loops to carry out a sort. It is within the second for loop where you can detail the process (steps) taken to carry out the sort as towards which Array element values are swapped with other element values as the sort is carried out. It would be within the if statement code block which checks whether or not the previous Array element is greater than the current Array Element.
Good luck.

Making 2 Modifications to a Bubblesort Program

I have to make the following 2 modifications to a simple bubblesort program:
After the first pass, the largest number is guaranteed to be in the highest-numbered element of the array; after the second pass, the two highest numbers are “in place”; and so on. Instead of making nine comparisons on every pass, modify the bubble sort to make eight comparisons on the second pass, seven on the third, and so on.
The data in the array may already be in the proper order or near proper order, so why make nine passes if fewer will suffice? Modify the sort to check at the end of each pass if any swaps have been made. If none have been made, the data must already be in the proper order, so the program should terminate. If swaps have been made, at least one more pass is needed."
Any help as to how I should approach these would be greatly appreciated!
//sort elements of array with bubble sort
public static void bubbleSort (int array2[])
{
//loop to control number of passes
for (int pass = 1; pass < array2.length; pass++)
{
//loop to control number of comparisons
for (int element = 0; element < array2.length - 1; element++)
{
//compare side-by-side elements and swap them if
//first element is greater than second element
if (array2[element] > array2[element + 1]){
swap (array2, element, element + 1);
}
}
}
}
//swap two elements of an array
public static void swap (int array3[], int first, int second)
{
//temporary holding area for swap
int hold;
hold = array3[first];
array3[first] = array3[second];
array3[second] = hold;
}
I think this will do for you. A boolean is added to check and the run (j) is subtracted from the input.length for each run.
public static int[] bubbleSort(int input[])
{
int i, j, tmp;
bool changed;
for (j = 0; j < input.length; j++)
{
changed = false;
for (i = 1; i < input.length - j; i++)
{
if (tmp[i-1] > input[i])
{
tmp= input[i];
input[i] = input[i-1];
input[i-1] = tmp;
changed = true;
}
}
if (!changed) return input;
}
return input;
}

A Sorted Integer List

So the original code is
// An (unsorted) integer list class with a method to add an
// integer to the list and a toString method that returns the contents
// of the list with indices.
//
// ****************************************************************
public class IntList {
private int[] list;
private int numElements = 0;
//-------------------------------------------------------------
// Constructor -- creates an integer list of a given size.
//-------------------------------------------------------------
public IntList(int size) {
list = new int[size];
}
//------------------------------------------------------------
// Adds an integer to the list. If the list is full,
// prints a message and does nothing.
//------------------------------------------------------------
public void add(int value) {
if (numElements == list.length) {
System.out.println("Can't add, list is full");
} else {
list[numElements] = value;
numElements++;
}
}
//-------------------------------------------------------------
// Returns a string containing the elements of the list with their
// indices.
//-------------------------------------------------------------
public String toString() {
String returnString = "";
for (int i = 0; i < numElements; i++) {
returnString += i + ": " + list[i] + "\n";
}
return returnString;
}
}
and
// ***************************************************************
// ListTest.java
//
// A simple test program that creates an IntList, puts some
// ints in it, and prints the list.
//
// ***************************************************************
import java.util.Scanner ;
public class ListTest {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
IntList myList = new IntList(10);
int count = 0;
int num;
while (count < 10) {
System.out.println("Please enter a number, enter 0 to quit:");
num = scan.nextInt();
if (num != 0) {
myList.add(num);
count++;
} else {
break;
}
}
System.out.println(myList);
}
}
I need to change the add method to sort from lowest to highest. This is what I tried doing.
// An (unsorted) integer list class with a method to add an
// integer to the list and a toString method that returns the contents
// of the list with indices.
//
// ****************************************************************
public class IntList {
private int[] list;
private int numElements = 0;
//-------------------------------------------------------------
// Constructor -- creates an integer list of a given size.
//-------------------------------------------------------------
public IntList(int size) {
list = new int[size];
}
//------------------------------------------------------------
// Adds an integer to the list. If the list is full,
// prints a message and does nothing.
//------------------------------------------------------------
public void add(int value) {
if (numElements == list.length) {
System.out.println("Can't add, list is full");
} else {
list[numElements] = value;
numElements++;
for (int i = 0; i < list.length; i++) {
if (list[i] > value) {
for (int j = list.length - 1; j > i; j--) {
list[j] = list[j - 1];
list[i] = value;
break;
}
}
}
for (in i = 0; i < list.length; i++) {
}
}
}
//-------------------------------------------------------------
// Returns a string containing the elements of the list with their
// indices.
//-------------------------------------------------------------
public String toString() {
String returnString = "";
for (int i = 0; i < numElements; i++) {
returnString += i + ": " + list[i] + "\n";
}
return returnString;
}
}
The outcome is very wrong. Any one able to steer me in the right direction? I can sort of see why what I have doesn't work, but I can't see enough to fix it.
So I realize I was not very descriptive here the first time. With the exception of the add method modifications the code was not my doing. My assignment is to only touch the add method to sort the array to print out smallest to largest. This is a beginners class and we do little to no practice my only tools for this are some basic understandings of loops and arrays.
I tried redoing it again and came up with this:
if(list[numElements-1] > value){
for(int i=0; i<numElements; i++){
if(list[i]>value){
for(int j = numElements; j>i; j-- ){
list[j] = list[j-1];
}
list[i] = value;
break;
}
}
numElements++;
}
else
{
list[numElements] = value;
numElements++;
}
my input was:8,6,5,4,3,7,1,2,9,10
the output was: 1,10,1,9,10,1,1,2,9,10
this thing is kicking my butt. I understand I want to check the input number to the array and move all numbers higher than it up one space and enter it behind those so it is sorted on entry, but doing so is proving difficult for me. I apologize if my code on here is hard to follow formatting is a little odd on here for me and time only allows for me to do my best. I think break is not breaking the for loop with i like i thought it would. Maybe that is the problem.
The biggest bug I see is using list.length in your for loop,
for(int i = 0; i <list.length; i++)
you have numElements. Also, I think it's i that needs to stop one before like,
for(int i = 0; i < numElements - 1; i++)
and then
for (int j = numElements; j > i; j--)
There are two lines that have to be moved out of the inner loop:
for (int i = 0; i < list.length; i++) {
if (list[i] > value) {
for (int j = list.length - 1; j > i; j--) {
list[j] = list[j - 1];
// list[i] = value;
// break;
}
list[i] = value;
break:
}
}
In particular, the inner break means that the loop that is supposed to move all larger elements away to make room for the new value only runs once.
You might want to include Java.util.Arrays which has its own sort function:
http://www.tutorialspoint.com/java/util/arrays_sort_int.htm
Then you can do:
public void add(int value) {
if (numElements == list.length) {
System.out.println("Can't add, list is full");
}
else {
list[numElements] = value;
numElements++;
Arrays.sort(list);
//Or: Java.util.Arrays.sort(list);
}
}
As Eliott remarked, you are getting confused between list.length (the capacity of your list) and numElements (the current size of your list). Also, though, you do not need to completely sort the list on each addition if you simply make sure to insert each new element into the correct position in the first place. You can rely on the rest of the list already to be sorted. Here's a simple and fast way to do that:
public void add(int value) {
if (numElements == list.length) {
System.out.println("Can't add, list is full");
} else {
int insertionPoint = Arrays.binarySearch(list, 0, numElements);
if (insertionPoint < 0) {
insertionPoint = -(insertionPoint + 1);
}
System.arrayCopy(list, insertionPoint, list, insertionPoint + 1,
numElements - insertionPoint);
list[insertionPoint] = value;
numElements += 1;
}
}
That will perform better (though you may not care for this assignment), and it is much easier to see what's going on, at least for me.
Here are some hints.
First, numElements indicates how many elements are currently in the list. It's best if you change it only after you have finished adding your item, like the original method did. Otherwise it may confuse you into thinking you have more elements than you really do at the moment.
There is really no need for a nested loop to do proper adding. The logic you should be following is this:
I know everything already in the list is sorted.
If my number is bigger then the biggest number (which is the one indexed by numElements-1, because the list is sorted) then I can just add my number to the next available cell in the array (indexed by numElements) and then update numElements and I'm done.
If not, I need to start from the last element in the array (careful, don't look at the length of the array. The last element is indexed by numElements-1!), going down, and move each number one cell to the right. When I hit a cell that's lower than my number, I stop.
Moving all the high numbers one cell to the right caused one cell to become "empty". This is where I'm going to put my number. Update numElements, and done.
Suppose you want to add the number 7 to this array:
┌─┬──┬──┬─┬─┐
│3│14│92│-│-│
└─┴──┴──┴─┴─┘
⬆︎ Last element
You move everything starting from the last element (92) to the right. You stop at the 3 because it's not bigger than 7.
┌─┬─┬──┬──┬─┐
│3│-│14│92│-│
└─┴─┴──┴──┴─┘
(The second element will probably still contain 14, but you're going to change that in the next step so it doesn't matter. I just put a - there to indicate it's now free for you to enter your number)
┌─┬─┬──┬──┬─┐
│3│7│14│92│-│
└─┴─┴──┴──┴─┘
⬆︎ Updated last element
This requires just one loop, without nesting. Be careful and remember that the array starts from 0, so you have to make sure not to get an ArrayIndexOutOfBoundsException if your number happens to be lower than the lowest one.
One problem I spotted is that: you are trying to insert the newly added number into the array. However your loop:
for (int i = 0; i < list.length; i++) {
if (list[i] > value) {
for (int j = list.length - 1; j > i; j--) {
list[j] = list[j - 1];
list[i] = value;
break;
}
}
}
is always looped through the total length of the array, which is always 10 in your test, rather than the actual length of the array, i.e. how many numbers are actually in the array.
For example, when you add the first element, it still loops through all 10 elements of the array, although the last 9 slots does not have value and are automatically assigned zero.
This caused your if statement always returns true:
if (list[i] > value)
if you have to write the sort algorithm yourself, use one of the commonly used sorting algorithm, which can be found in Wikipedia.
If any one was curious I finally worked it out. Thank you to everyone who replied. This is what i ended up with.
public void add(int value)
{
if(numElements == 0){
list[numElements] = value;
numElements++;
}
else{
list[numElements] = value;
for(int check = 0; check < numElements; check++){
if(list[check] > value){
for(int swap = numElements; swap> check; swap--){
list[swap] = list[swap-1];
}
list[check] = value;
break;
}
}
numElements++;
}
}
so my original is the same but we have to make another class
A Sorted Integer List
File IntList.java contains code for an integer list class. Save it to your project and study it; notice that the only things you can do are create a list of a fixed size and add an element to a list. If the list is already full, a message will be printed. File ListTest.java contains code for a class that creates an IntList, puts some values in it, and prints it. Save this to your folder and compile and run it to see how it works.
Now write a class SortedIntList that extends IntList. SortedIntList should be just like IntList except that its elements should always be in sorted order from smallest to largest. This means that when an element is inserted into a SortedIntList it should be put into its sorted place, not just at the end of the array. To do this you’ll need to do two things when you add a new element:
Walk down the array until you find the place where the new element should go. Since the list is already sorted you can just keep looking at elements until you find one that is at least as big as the one to be inserted.
Move down every element that will go after the new element, that is, everything from the one you stop on to the end. This creates a slot in which you can put the new element. Be careful about the order in which you move them or you’ll overwrite your data!
Now you can insert the new element in the location you originally stopped on.
All of this will go into your add method, which will override the add method for the IntList class. (Be sure to also check to see if you need to expand the array, just as in the IntList add() method.) What other methods, if any, do you need to override?
To test your class, modify ListTest.java so that after it creates and prints the IntList, it creates and prints a SortedIntList containing the same elements (inserted in the same order). When the list is printed, they should come out in sorted order.

Categories

Resources