Insertion Sort Function - java

This insertion sort function is supposed to take in an array of Drink objects and sort them according to one of their properties (cost). This property is fetched by getCost(). I keep getting a NullPointer error. The code is as follows:
public void sortDrinks(Drink[] drinks){
for(int i = 1; i <= drinks.length; i++){
Drink key = drinks[i];
int count = i-1;
while((count >= -1)&&(drinks[count].getCost() > key.getCost())){
drinks[count+1] = drinks[count];
count--;
}
drinks[count+1] = key;
}
}

When count is equal to -1, you are trying to access the getcost method of drinks[-1]. I believe this will be fixed if you change "while count >= -1" to "while count > -1".
This will obviously require a small amount of restructuring, for the drink to then be inserted in the correct place.

Why not implement the comparable interface in your Drink class?
public class Drink implements Comparable<Drink> {
// attributes and constructor
public int getCost() {
return cost;
}
public int compareTo(Drink other) {
return getCost().compareTo(other.getCost());
}
}
Then later on you can sort the array of Drink objects that is passed with:
Collections.sort(drinks); // returns the sorted drinks

Related

Sorting objects in an ArrayList without using Collections.sort

I would like to use my own sorting method instead of Collections.sort so that I can tinker around with my program to understand other sorts, generics, and ArrayLists better.
I have an employee class that has an employee number member. I know how to make an ArrayList of Employee objects, but could you explain how I could print and sort them? I started off by sorting a regular array and wanted to do the same with an ArrayList of Employee objects (the employee number). I'm having trouble understanding how to print ArrayLists of objects and sorting them.
package dataStructures;
import java.util.ArrayList;
import java.util.Arrays;
public class SortPractice {
public static void main(String[] args) {
int[] nums = {5,4,3,2,1};
System.out.println(Arrays.toString(nums));
BubbleSort1(nums);
ArrayList<Employee> empList = new ArrayList<Employee>();
for (int i=0; i<10; i++) {
empList.add(new Employee(10-i));
}
BubbleSort(empList); //This method doesn't work. I need help here.
}
public static void BubbleSort (int[] A) { //I included this because I know it works.
int temp = 0;
int firstLoopCount = 0;
int SecLoopCount = 0;
for (int i=0; i< A.length-1; i++) {
firstLoopCount++;
System.out.println(Arrays.toString(A) + i + " << First Loop interation");
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;
}
SecLoopCount++;
System.out.println(Arrays.toString(A) + j + " << Second Loop Interation");
}
}
System.out.println((firstLoopCount+SecLoopCount));
}
public static void BubbleSort (ArrayList<Employee> empList) { //I tried to use the same
int temp = 0; //approach just with the List
int firstLoopCount = 0;
int SecLoopCount = 0;
for (int i=0; i<empList.size()-1; i++) {
firstLoopCount++;
System.out.println(Arrays.toString(empList) + i + " << First Loop interation");
for (int j=0; j<empList.size()-1; j++) {
if (empList.get(j) > empList.get(j+1)) { //I get errors here in Eclipse and
temp = A[j]; //up above when I use toString
A[j] = A[j+1];
A[j+1] = temp;
}
SecLoopCount++;
System.out.println(Arrays.toString(A) + j + " << Second Loop Interation");
}
}
System.out.println((firstLoopCount+SecLoopCount));
}
Here is the employee class. It has other getters and setters but I didn't include them.
package dataStructures;
public class Employee {
private int empNum;
private String firstName;
private String LastName;
private String email;
public Employee(int empNum) {
this.empNum = empNum;
}
public String toString(){
return " "+ empNum + ",";
}
public Employee() {
}
public int getEmpNum() {
return empNum;
}
public void setEmpNum(int empNum) {
this.empNum = empNum;
}
Accessing an array is different from accessing an ArrayList. This is because these two objects are fundamentally different.
Let's focus on this line of code:
System.out.println(Arrays.toString(empList) + i + " << First Loop interation");
You're going to want to bookmark the Java 7 API so that you can reference what it is these methods actually take as arguments. Believe me, it will save you lots of time in the long run.
Specifically, the code is invalid because toString does not accept a parameter of type ArrayList. You can just straight-up print an ArrayList, as it has a reasonable toString method, whereas an array doesn't (which is why you use Arrays#toString):
System.out.println(empList.toString() + i + " << First Loop interation");
Let's look at this if block next:
if (empList.get(j) > empList.get(j + 1)) { //I get errors here in Eclipse and
temp = A[j]; //up above when I use toString
A[j] = A[j + 1];
A[j + 1] = temp;
}
I'll be blunt, you're going to get errors in any reasonable IDE with that code. The reason: you index into arrays with brackets, but you use get for an ArrayList.
The first fix is that you can't compare those two instances with >. What you'd wind up doing instead is retrieving the field you want to compare it with instead.
if(empList.get(j).getEmpNum() > empList.get(j+1).getEmpNum()) {
// more code
}
Here's the relevant Javadoc for ArrayList. You're going to need it.
Let's focus on the inner part of the if. The operation you're doing there is called a swap. You're taking an element from one location and overwriting it with another. Since arrays don't shift elements down, you have to capture the original value before you overwrite it.
To put it in English:
Take original value
Place new value in original value's original array location
Place original value in new value's original array location
You shouldn't have to do that with an ArrayList, as it can add the element in a specific spot.
In English, it should be as simple as:
Insert new value in original value's spot
Delete new value's occurrence in the list
In Java, it might read like this:
if(empList.get(j).getEmpNum() > empList.get(j + 1).getEmpNum()) {
empList.add(j, empList.get(j + 1));
empList.remove(j + 1);
}
One problem I noticed is in this line -
empList.get(j) > empList.get(j+1)
You are comparing 2 objects, i.e. 2 employee objects, this is usually not used other than for primitive types (e.g. Integer).
What you probably want to compare is the employee IDs which I assume is in your Employee.java file (please post this file so we can take a look). Here's an example of what you could do for this line -
empList.get(j).getEmployeeId() > empList.get(j+1).getEmployeeId()
Edit: sorry read the question wrong, not using Collections.sort()
Here is an example. In this case, your class has to provide a method that overrides the compareTo method in the Comparable interface. The specification is that it should return an integer greater than 0 if the calling object is greater, or an integer less than 0 if the caller is less, return 0 otherwise.
public class Employee implements Comparable {
//Rest of your class code here
public void getID() {
//return some value associated with the ID
}
//override this method
public int compareTo(Employee other) {
//code to compare two Employees
// Maybe something like the following
if (this.getID() > other.getID()) {
return 1;
} else if (this.getID() < other.getID()) {
return -1;
} else {
return 0;
}
}
}
This is the final answer with the help of #Makoto
public static void BubbleSort (ArrayList<Employee> empList) {
for (int i=0; i<empList.size()-1; i++) {
for (int j=0; j<4; j++) {
if (empList.get(j).getEmpNum() > empList.get(j+1).getEmpNum()) {
empList.add(j, empList.get(j + 1)); //This line inserts the smaller value
empList.remove(j+2); //into the first index and pushes the
} //indices down 1. So I need to remove
//j+2 not j+1.
/*When I use the debugger to step into toString() it says source not found.
I don't get it but it works.*/
System.out.println(empList.toString() + j + " << Second Loop Interation");
}
System.out.println(empList.toString() + i + " << First Loop interation");
}
}

How to decide the state of an object before starting to code?

I have the following code for displaying the sum of two consecutive element of ArrayList until the element left is one.for example:-
if i entered
1 2 3 4 5
output
3 7 5 //adding the two consecutive last one is as it is
10 5//doing the same thing
15
code
import java.util.*;
import java.lang.Integer;
class Substan{
ArrayList <Integer> list = new ArrayList <Integer> ();
ArrayList <Integer> newList = new ArrayList <Integer> ();// this will be the list containing the next sequence.
int index=0;
int sum=0;
Substan(){
Scanner read = new Scanner(System.in);
String choice;
System.out.println("Enter the elements of the array");
do{
int element = read.nextInt();
list.add(element);
System.out.println("More?");
choice = read.next();
}while(choice.equals("y") || choice.equals("Y"));
}
/* precondition- we have the raw list that user has enterd.
postcondition - we have displayed all the sublists,by adding two consecutives numbers and the last one is having one element.
*/
void sublist(){
while(noofElementsIsNotOneInList()){
index =0;
while(newListIsNotComplete()){
if(nextElementIsThere()){
sum = addTheConsecutive();
}
else{
sum = getLastNumber();
}
storeSumInNewList();
}
displayTheNewList();
System.out.println("");
updateTheLists();
}
displayTheNewList(); //as we have danger of Off By One Bug (OBOB)
System.out.println("");
}
private boolean noofElementsIsNotOneInList(){
boolean isnotone = true;
int size = list.size();
if ( size == 1){
isnotone = false;
}
return isnotone;
}
private boolean newListIsNotComplete(){
boolean isNotComplete = true;
int listSize = list.size();
int newListSize = newList.size();
if (listSizeIsEven()){
if ( newListSize == listSize/2){
isNotComplete = false;
}
}
else{
if( newListSize == (listSize/2) +1){
isNotComplete = false;
}
}
return isNotComplete;
}
private boolean listSizeIsEven(){
if ( list.size()%2 == 0 ){
return true;
}
else{
return false;
}
}
/*
we are at some index.
returns true if we have an element at (index+1) index.
*/
private boolean nextElementIsThere(){
if ( list.size() == index+1 ){
return false;
}
else{
return true;
}
}
/* precondition-we are at index i
postcondition - we will be at index i+2 and we return sum of elements at index i and i+1.
*/
private int addTheConsecutive(){
int sum = list.get(index)+list.get(index+1);
index += 2;
return sum;
}
/* we are at last element and we have to return that element.
*/
private int getLastNumber(){
return list.get(index);
}
private void storeSumInNewList(){
newList.add(sum);
}
private void displayTheNewList(){
int size = newList.size();
for ( int i=0;i<size;i++){
System.out.print(newList.get(i)+" ");
}
}
/*precondition - we have processed all the elements in the list and added the result in newList.
postcondition - Now my list will be the newList,as we are processing in terms of list and newList reference will have a new object.
*/
private void updateTheLists(){
list = newList;
newList = new ArrayList <Integer>();// changing the newList
}
public static void main(String[] args) {
Substan s = new Substan();
s.sublist();
}
}
So i have done a lot of refinement of my code but having a problem of sharing the local variables with the other methods.for example i have used index instance for storing the index and initially i thought that i will put this as not an instance but a local variable in method sublist() but as it cannot be viewed from other methods which needed to use the index like addTheConsecutive().So considering that i put the index at class level.So is it wright approach that put the variables that are shared at class level rather than looking at only the state of the object initially before coding and stick to that and never change it?
Consider this:
An object can communicate with other(s) only by sharing its attributes. So, if you need an object to read the state of another, the only way it can be done is by giving it "permission" to read the other object attributes.
You have two ways to do that:
Declaring the object attributes public, or
Creating getXXX() methods (makes sense for private attributes)
I personally prefer option two, because the getXXX() method returns the value ("state") of a particular attribute without the risk of being modified. Of course, if you need to modify a private attribute, you should also write a setXXX() method.
Example:
public class MyClass {
private int foo;
private String bar;
/*
* Code
*/
public int getFoo() {
return foo;
}
public String getBar() {
return bar;
}
public void setFoo(int foo) {
this.foo = foo;
}
public void setBar(String bar) {
this.bar = bar;
}
/*
* More code
*/
}
This way all the object attributes are encapsulated, and:
they cannot be read by any other object, unless you specifically call the appropriate getXXX() function, and
cannot be altered by other objects, unless you specifically call the appropriate setXXX() function.
Compare it with the non-abstracted version.
for (int index = 0; index < list.size(); index += 2) {
int sum = list.get(index);
if (index + 1 < list.size() {
sum += list.get(index + 1);
}
newList.add(sum);
}
Now, top-down refining the algorithm using names is a sound methodology, which helps in further creative programming.
As can seen, when abstracting the above again:
while (stillNumbersToProcess()) {
int sum = sumUpto2Numbers();
storeSumInNewList(sum);
}
One may keep many variables like sum as local variables, simplifying state.
One kind of helpful abstraction is the usage of conditions, in a more immediate form:
private boolean listSizeIsEven() {
return list.size() % 2 == 0;
}
private boolean nextElementIsThere() {
return index + 1 < list.size();
}
There's no point in declaring index at Class level since you dont want it to be a member or an instance of that class. Instead make it local to the method and pass it to other methods as argument where you want to access it.
I think you are asking the wrong question.
Your class variables make very little sense, as do many of the methods. This is mostly because:
Your class is doing too much
Your algorithm is a little odd
The class variables that you do have make much more sense passed as method parameters. Some methods need to see them, and some don't.
Your class is also a little odd, in that calling subList twice on the same class will not produce the same answer.
The code is littered with methods I don't quite see the point in, such as:
private boolean noofElementsIsNotOneInList(){
boolean isnotone = true;
int size = list.size();
if ( size == 1){
isnotone = false;
}
return isnotone;
}
Shouldn't this be:
private boolean noofElementsIsNotOneInList(){
return list.size() == 1;
}
And it makes no sense for it to use some arbitrary List, pass one in so that you know which List you are checking:
private boolean noofElementsIsNotOneInList(final Collection<?> toCheck){
return toCheck.size() == 1;
}
The same logic can be applied to almost all of your methods.
This will remove the instance variables and make your code much more readable.
TL;DR: Using lots of short appropriately named methods: good. Having those methods do things that one wouldn't expect: bad. Having lots of redundant code that makes things very hard to read: bad.
In fact, just to prove a point, the whole class (apart from the logic to read from stdin, which shouldn't be there anyway) can transformed into one short, recursive, method that requires no instance variables at all:
public static int sumPairs(final List<Integer> list) {
if (list.size() == 1)
return list.get(0);
final List<Integer> compacted = new LinkedList<>();
final Iterator<Integer> iter = list.iterator();
while (iter.hasNext()) {
final int first = iter.next();
if (iter.hasNext()) compacted.add(first + iter.next());
else compacted.add(first);
}
return sumPairs(compacted);
}
Now you could break this method apart into several appropriately named shorter methods, and that would make sense. It's sometimes more helpful to start from the other end. Sketch out the logic of your code and what it's trying to do, then find meaningful fragments to split it into. Possibly after adding unit tests to verify behaviour.
what about doing by Recursion:
public int calculateSum(List<Integer> nums) {
displayList(nums);
if (nums.size() == 1) {
return nums.get(0);
}
List<Integer> interim = new ArrayList<Integer>();
for (int i = 0; i < nums.size(); i = i + 2) {
if (i + 1 < nums.size()) {
interim.add(nums.get(i) + nums.get(i + 1));
} else {
interim.add(nums.get(i));
}
}
return calculateSum(interim);
}
public static void displayList(List<Integer> nums){
System.out.println(nums);
}
Steps:
Run calculate sum until list has 1 element
if list has more than 1 element:
iterate the list by step +2 and sum the element and put into a new List
again call calculate sum

Doing a Selection sort on an ArrayList

I need to sort the array list from highest to lowest based on the "value" and im really stuck :( basically in this project, they are gonna run a list of items and this method is supposed to put the one with the highest value first and so fort and im trying to use a selection sort. Thank for you help in advance :) here is what i have at the moment
public void pickMostExpensiveFirst(ArrayList<Item> totalListOfItems)
{
int max, i ,j;
Item temp;
for (i = 0; i < totalListOfItems.size() - 1; i++)
{
max = i;
for (j = i + 1; j < totalListOfItems.size(); j++)
{
if (totalListOfItems.get(max).getValue()
.compareTo(totalListOfItems.get(j).getValue()) > 0)
max = j;
}
temp = totalListOfItems.get(i);
totalListOfItems.set(i, totalListOfItems.get(max));
totalListOfItems.set(max, temp);
}
}
Your problem lies here:
if (totalListOfItems.get(max).getValue().compareTo(totalListOfItems.get(j).getValue()) > 0)
max = j;
here you compare item at position max and j, and if item(max) > item(j), you replace max with j. This is basically searching for LOWEST value, not HIGHEST. Switch it over, and your problem is solved.
Java helps Object Oriented programming, why to implement from scratch when Java collection framework (along with supporting classes) provides ready made proved solutions.
If the objective of your method is just to identify the maximum/ minimum or sort list, then java.util.Collections class provides util methods. only requirement is that your Item class should be (IsA relationship) Comparable, meaning Item should implement Comparable interface. If you do not have control over Item class code, then we can use Interface Comparator to provide comparison rule. the sample code looks as follows.
public static void pickMostExpensiveFirst(ArrayList<Item> totalListOfItems) {
System.out.println(Collections.max(totalListOfItems));
// Collections.sort(totalListOfItems); // to sort with Comparable
// Collections.sort(totalListOfItems, ValueComparator); // to sort with
// Comparator
}
class Item implements Comparable<Item> {
String name;
int value;
public Item(String name, int value) {
this.name = name;
this.value = value;
}
#Override
public int compareTo(Item other) {
return Integer.compare(this.value, other.value);
// return -1 * Integer.compare(this.value, other.value); in case you
//need descending order
}
#Override
public String toString() {
return name + " " + value;
}
}

Java Bubblesort Algorithm

I am trying to use the summer to practice more Java to get better by learning how to code algorithms. I have this problem where I add elements to my ArrayList but somehow the first number I add also sets the number of positions in my list which I want to avoid. I only want the 0th index to contain the number 5. I seem to not catch a clue on how to solve this.
public class Algorithms {
private ArrayList<Integer> numbers;
public Algorithms() {
numbers = new ArrayList<Integer>();
numbers.add(5);
numbers.add(4);
bubblesort();
}
public static void main(String args[]) {
new Algorithms();
}
public void bubblesort() {
System.out.println(numbers);
for (int a = 0; a < numbers.size();) {
for (int b = 1; b < numbers.size();) {
int currentNumber = numbers.get(a);
if (currentNumber > numbers.get(b)) {
//Collections.swap(numbers, currentNumber, numbers.get(b));
numbers.set(numbers.get(a), numbers.get(b));
numbers.set(numbers.get(b), numbers.get(a));
a++;
b++;
} else if (currentNumber < numbers.get(b)) {
a++;
b++;
}
System.out.println(numbers);
}
}
}
}
You are not swapping elements correctly. Instead of
numbers.set(numbers.get(a), numbers.get(b));
numbers.set(numbers.get(b), numbers.get(a));
it should be
int temp = numbers.get(a);
numbers.set(a, numbers.get(b));
numbers.set(b, temp);
The below two statements:
numbers.set(numbers.get(a), numbers.get(b));
numbers.set(numbers.get(b), numbers.get(a));
is not performing swapping. The first argument to the List#set(int, E) method is the index in the list, where you want to set the value passed as 2nd argument. You need to use a temp variable for swapping.
Also, the swapping didn't work for your commented line for the same reason. Collections#swap method take indices for swapping. So, just change:
Collections.swap(numbers, currentNumber, numbers.get(b));
to:
Collections.swap(numbers, a, b);
And please for the love of all that is holy, don't call method from inside a constructor. Remove the method invocation from inside the constructor, and move it to main method like this:
Algorithms algo = new Algorithms();
algo.bubbleSort()

How to use binary search in order to find the first element in an array that has certain weight (another element in a different array)?

All the methods here are correct, but my problem is that i have to find a part in the parts array that has a certain weight. So After i do the getweight method I think i have to call that. But the last part of the code is what i have a problem with. It starts with the line public Part getPartWithWeight (int weight){
class Robot {
Part[] parts;
public Robot () {// assume these are right}
}
public void addPart(Part p) { // assume these are right}
}
class Part {
// Class details not shown
public double getWeight() {//... }
}
public int getPartnum() {//...}
}
public String getMaterial() {//...}
}
public Part getPartWithWeight (int weight){
for(int i = 0; i < parts.length; i ++){
if (parts[i].weight == weight) {
return parts[i];
}
}
Well, here's the "works-out-of-the-box" version.
Step 1 Write a comparator.
class PartComparator implements java.util.Comparator<Part> {
#Override
public int compare(Part part1, Part part2) {
return part1.weight - part2.weight;
}
public final static PartComparator instance = new PartComparator();
}
The comparator class should be static if you declare it inside Part (which is what I would suggest).
Step 2 Use the comparator
public Part getPartWithWeight (int weight){
Part pivot = new Part();
pivot.weight = weight;
int idx = Arrays.binarySearch(parts, pivot, PartComparator.instance);
return parts[idx];
}
if (parts[i].weight == weight)
should say
if (parts[i].getWeight() == weight)
You should use getWeight() because that's the method defined in the Parts class.
Also if you're problem is getting the parts array from the robot class and using it in the part class then you should just pass it as a parameter.
public Part getPartWithWeight (int weight, Part[] parts){
for(int i = 0; i < parts.length; i ++){
if (parts[i].getWeight() == weight) {
return parts[i];
}
}
}
Then when you call the method getPartWithWeight() make sure you put the array in there too.
EDIT: Also per Ray Cheng's comment, the weight you're looking for is supposed to be an int but your getWeight() method returns a double.... so either your getWeight() should return an in or you should typecast it as an int before making the comparison. Be aware that if you typecast it as an int you will lose some precision. It would be better to fix your getWeight() so it returns a double like you need it to.
To implement a binary search, you first need to cut the array in half and then decide which half you want to begin the search. Then you cut the halved array in half again and repeat...
Unless you want to implement your own, but looks like there is a built-in one you can call.
http://docs.oracle.com/javase/7/docs/api/index.html?java/util/Arrays.html

Categories

Resources