0

Alright I am stuck on how do I implement this binary search that will receive data from other classes.

I am trying to implement it in my own ADT.

I have implemented a List ADT manually but now I want to add in a search operation which utilizes binary search algorithm manually and doesn't uses any built in Java API.

Example this is my sorted list interface that I implemented manually.

public class SortedArrayList<T extends Comparable<T>> implements SortedListInterface<T>{



   private boolean binarySearch(// What parameters should I receive from Student Object?) {
       // This will be my binary search implementation
   }         



}

The problem is I will be creating a Student class where I will add the instances of the student class into the sortedArrayList above.

Like how am I going to receive the data to be put into the binary search algorithm in a generics typed sortedArrayList?

Do note I am not allowed to use any JAVA Built-IN API , everything must be implemented manually else I can finish this easily but its a pain now since its limited.

Example I want to binary search by Student name from Student's class. How will I need to implement and receive data into this manually implemented ADT of mine?

public class SortedArrayList<T extends Comparable<T>> implements SortedListInterface<T>{

     private T[] list;


   private boolean binarySearch(int first, int last, T desiredItem) {

       int mid = (first + last) / 2;

          if(desiredItem.getFullName().equals(list[mid]) 
                // This part over here. How do I access attributes from Student class in this ADT so that I can access the data and do comparison for the binary search..

   }         



}

How do I access attributes from Student class into my own ADT so that I can do comparisons on binary search algorithm?!

I am literally stuck.

I would appreciate someone giving me directions. I repeat again no BUILT-IN APIs from JAVA, implementation manually only

ADT SortedList Interface

    public interface SortedListInterface <T extends Comparable<T>> {


        public boolean add(T element);


        public T get(int index);


        public boolean search(T element);


        public T remove(int index);


        public void clear();


        public int getLength();


        public boolean isEmpty();


        public boolean isFull();


    }

ADT SortedList Implementation Code

public class SortedArrayList<T extends Comparable<T>> implements SortedListInterface<T>{

  //Data Types  

  private T[] list;
  private int length;
  private static final int SIZE = 10;


  // Constructors

  public SortedArrayList() {
    this(SIZE);
  }

  public SortedArrayList(int size) {
    length = 0;
    list = (T[]) new Comparable[SIZE]; // an array of instances of a class implementing Comparable interface and able to use compareto method but its overidden instead
  }


  // Setter & Getters

  @Override
  public int getLength() {
    return length;
  }

  @Override
  public boolean isEmpty() {
    return length == 0;
  }

  @Override
  public boolean isFull() {
    return false;
  }

  @Override
  public void clear() {
    length = 0;
  }


  // Array Expansion

  private boolean isArrayFull() {
    return length == list.length;
  }

  private void expandArray() {
    T[] oldList = list;
    int oldSize = oldList.length;

    list = (T[]) new Object[2 * oldSize];

    for (int i = 0; i < oldSize; i++) // copy old array elements into new array elements
      list[i] = oldList[i];

  }




  // ADT METHODs


  // Add New Elements Function


  @Override
  public boolean add(T element) {
    int i = 0;

    while (i < length && element.compareTo(list[i]) > 0) // return 0 with equal , return more than 1 if element larger than list[i] , return -1 if less
      i++;

    makeRoom(i + 1);
    list[i] = element;
    length++;
    return true;
  }  


  private void makeRoom(int index) {  // accepts given index
    int newIndex = index - 1;
    int lastIndex = length - 1;

    for (int i = lastIndex; i >= newIndex; i--) 
      list[i + 1] = list[i];

  }



  //Remove Elements Function

  @Override
  public T remove(int index) {  // accepts given index

    T result = null;

    if ( index >= 1 && index <= length ) {

      result = list[index - 1];

      if (index < length) 
        removeGap(index);

      length--;
    }

    return result;
  }

  private void removeGap(int index) { // accepts given index and remove the gap where the element its removed

    int removedIndex = index - 1;
    int lastIndex = length - 1;

    for (int i = removedIndex; i < lastIndex; i++) 
      list[i] = list[i + 1]; // shifts elements back to remove the gap

  }


  // Get Element

  @Override
  public T get(int index) { // accepts given index and return the object

    T object = null;

    if ( index >= 1 && index <= length) 
      object = list[index - 1];

    return object;

  }


  // Search Algorithms

  @Override
  public boolean search(T element) {

    return binarySearch(element);

  }

  private boolean binarySearch(// Implementation here) {
       // Implementation here
  } 




  //To String Method

  @Override
  public String toString() {

    String result = "";

    for (int i = 0; i < length; i++) 
      result += list[i] + "\n";

    return result;

  }



}

Student Class Implementation

public class Student implements Comparable<Student>{


   // Data Types 

   private Name name;
   private char gender;
   private String icNo;
   private String mobileNo;
   private Course course;
   private int group;
   private String dOB;


   // Constructors

   public Student() {
   }

   public Student(Name name, char gender, String icNo, String mobileNo, Course course, int group, String dOB) {
        this.name = name;
        this.gender = gender;
        this.icNo = icNo;
        this.mobileNo = mobileNo;
        this.course = course;
        this.group = group;
        this.dOB = dOB;
    }

   public Student(Name name) {
        this.name = name;
    }


   // setter

   public void setName(Name name) {
        this.name = name;
    }

    public void setGender(char gender) {
        this.gender = gender;
    }

    public void setIcNo(String icNo) {
        this.icNo = icNo;
    }

    public void setMobileNo(String mobileNo) {
        this.mobileNo = mobileNo;
    }

    public void setCourse(Course course) {
        this.course = course;
    }

    public void setGroup(int group) {
        this.group = group;
    }

    public void setdOB(String dOB) {
        this.dOB = dOB;
    }


    // getter


    public Name getName() {
        return name;
    }

    public char getGender() {
        return gender;
    }

    public String getIcNo() {
        return icNo;
    }

    public String getMobileNo() {
        return mobileNo;
    }

    public Course getCourse() {
        return course;
    }

    public int getGroup() {
        return group;
    }

    public String getdOB() {
        return dOB;
    }

    @Override
    public String toString() {
        return "Student{" + "name=" + name + ", gender=" + gender + ", icNo=" + icNo + ", mobileNo=" + mobileNo + ", course=" + course + ", group=" + group + ", dOB=" + dOB + '}';
    }

   public int compareTo(Student object) { // Sort according to name if name same then sort according to gender and so on.

    int c = this.name.getFullName().compareTo(object.getName().getFullName());

    if(c == 0)
        c = this.gender - object.getGender(); 

    if(c == 0)
        c = this.icNo.compareTo(object.getIcNo());  

    if(c == 0)
        c = this.mobileNo.compareTo(object.getMobileNo());

    if(c == 0)
        c = this.group - object.getGroup();

    if(c == 0)
        c = this.dOB.compareTo(object.getdOB());

    return c;

  }


}

Course Class

public class Course {


    // Data Types

    private String courseCode;
    private String courseName;
    private double courseFee;


    // Constructors

    public Course() {
    }

    public Course(String courseCode, String courseName, double courseFee) {
        this.courseCode = courseCode;
        this.courseName = courseName;
        this.courseFee = courseFee;
    }

    // setter

    public void setCourseCode(String courseCode) {
        this.courseCode = courseCode;
    }

    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }

    public void setCourseFee(double courseFee) {
        this.courseFee = courseFee;
    }


    // getter

    public String getCourseCode() {
        return courseCode;
    }

    public String getCourseName() {
        return courseName;
    }

    public double getCourseFee() {
        return courseFee;
    }

    @Override
public String toString() {
    return "CourseCode = " + courseCode + "Course Name = " + courseName + "Course Fee = " + courseFee;
}




}

Name Class

public class Name {

    // Data Types

    private String firstName;
    private String lastName;


    // Constructors

    public Name() {
    }

    public Name(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    // setter

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    // getter

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public String getFullName(){
        return firstName + " " + lastName;
    }

    @Override
    public String toString() {
        return "Name{" + "firstName=" + firstName + ", lastName=" + lastName + '}';
    }
Cash-
  • 67
  • 1
  • 10
  • How would I able to receive data for comparison from other objects or classes in this ADT? So that I can use it in my binary search method. – Cash- Nov 09 '19 at 16:04
  • Student has attributes full name , mobile phone etc like how do I receive these data via parameter in this ADT above so I can use it in my binary search algorithm. – Cash- Nov 09 '19 at 16:17
  • [edit] your question and post the interface code. It will start with `public interface SortedListInterface {` and be followed by a list of method declarations. – Abra Nov 09 '19 at 17:38
  • @Abra , I have edited the post. Please check my interfaces and see if that's a possibly to implement binary search. – Cash- Nov 10 '19 at 02:50
  • Post code for class `Name` and class `Course`. – Abra Nov 10 '19 at 18:40
  • @Abra , hey thanks for the response your answer kinda make sense to me. I assume I don’t fully understand the comparable interface. That’s why I do not know how to use compareTo. Do you still need the code for my Name and course class? It’s actually same as the Student class , setters , getters and toString as well as some parameter constructors. I will try your implementation once I have access to my computer. I am currently using mobile at the moment – Cash- Nov 11 '19 at 00:33
  • _Do you still need the code for my Name and course class?_ Yes, I still need the code for classes `Name` and `Course` so as to help you with the implementation of the `Comparable` interface which class `Student` needs to implement. – Abra Nov 11 '19 at 05:17
  • @Abra , Hello. I have updated the post with Course and Name class. – Cash- Nov 11 '19 at 08:32
  • @Abra , please check latest comment. Thank you then I can finalize the answer. Again. Thank you so much for your help! – Cash- Nov 17 '19 at 00:59

1 Answers1

1

The binary search algorithm relies on comparing a value being searched for with values in the list being searched. That's why the declaration of your class that implements the SortedListInterface is:

SortedArrayList<T extends Comparable<T>>

Note the extends Comparable<T>.
Comparable is an interface through which you can compare two objects. Hence in the search() method that you have to implement, you know that every object in the list defines the compareTo() method and you simply use that method to compare the object being searched for with individual objects in the list.

Here is a simple implementation of the binary search algorithm in the context of your project.

private T[] list; // The list to search.

private int count; // The number of non-null elements in 'list'.

public boolean search(T element) {
    boolean found = false;
    int lo = 0;
    int hi = count - 1;
    while (lo <= hi) {
        int mid = (lo + hi) / 2;
        if (list[mid].compareTo(element) < 0) {
            lo = mid + 1;
        }
        else if (list[mid].compareTo(element) > 0) {
            hi = mid - 1;
        }
        else {
            found = true;
            break;
        }
    }
    return found;
}

With a method, you have a method parameter. In the method code you use the parameter name. But when you invoke that method from other code, you provide a value which is substituted for the parameter. In the same way, the code above uses a type parameter which is substituted with the name of an actual class when you create an instance of class SortedArrayList. In your case, T is substituted with Student and class Student must implement the compareTo() method. Hence method search(), in class SortedArrayList does not need to know about the members in class Student.

So you would first create an instance of SortedArrayList like this:

SortedArrayList<Student> theList = new SortedArrayList<>();

Then you can call the search() method like this:

Student s = new Student(/* relevant parameter values */);
theList.search(s);

EDIT

I understand that you don't necessarily want to search for a Student, you may want to search for the Name of a student or a student's mobile phone number. In that case I believe you need a Comparator. Here is the code for class SortedArrayList with the addition of a Comparator

import java.util.Comparator;
import java.util.Objects;

public class SortedArrayList<T extends Comparable<T>> implements SortedListInterface<T> {
    private static final int SIZE = 10;

    private Comparator<? super T> comparator;
    private T[] list;
    private int count;

    @SuppressWarnings("unchecked")
    public SortedArrayList(Comparator<? super T> c) {
        comparator = c;
        list = (T[]) new Comparable[SIZE]; // No way to verify that 'list' only contains instances of 'T'.

        /* NOTE: Following is not allowed.
        list = new T[SIZE]; // Cannot create a generic array of T
        */
    }

    @Override
    public boolean add(T element) {
        Objects.requireNonNull(element, "Cannot add null element.");
        boolean result = false;
        if (count == 0) {
            list[0] = element;
            count = 1;
            result = true;
        }
        else {
            if (!isFull()) {
                int i = 0;
                while (list[i] != null) {
                    if (element.compareTo(list[i]) < 0) {
                        break;
                    }
                    i++;
                }
                if (list[i] != null) {
                    for (int j = count - 1; j >= i; j--) {
                        list[j + 1] = list[j];
                    }
                }
                list[i] = element;
                count++;
                result = true;
            }
        }
        return result;
    }

    @Override
    public T get(int index) {
        checkIndex(index);
        return list[index];
    }

    @Override
    public boolean search(T element) {
        if (comparator == null) {
            return binarySearchComparable(element);
        }
        else {
            return binarySearchComparator(element);
        }
    }

    @Override
    public T remove(int index) {
        checkIndex(index);
        T removed = list[index];
        list[index] = null;
        for (int i = index; i < count; i++) {
            list[i] = list[i + 1];
        }
        count--;
        list[count] = null;
        return removed;
    }

    @Override
    public void clear() {
        for (int i = 0; i < count; i++) {
            list[i] = null;
        }
        count = 0;
    }

    @Override
    public int getLength() {
        return count;
    }

    @Override
    public boolean isEmpty() {
        return count == 0;
    }

    @Override
    public boolean isFull() {
        return count == SIZE;
    }

    private boolean binarySearchComparable(T element) {
        boolean found = false;
        int lo = 0;
        int hi = count - 1;
        while (lo <= hi) {
            int mid = (lo + hi) / 2;
            if (list[mid].compareTo(element) < 0) {
                lo = mid + 1;
            }
            else if (list[mid].compareTo(element) > 0) {
                hi = mid - 1;
            }
            else {
                found = true;
                break;
            }
        }
        return found;
    }

    private boolean binarySearchComparator(T key) {
        int low = 0;
        int high = count - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            T midVal = list[mid];
            int cmp = comparator.compare(midVal, key);
            if (cmp < 0)
                low = mid + 1;
            else if (cmp > 0)
                high = mid - 1;
            else
                return true; // key found
        }
        return false;  // key not found.
    }

    private void checkIndex(int index) {
        if (index < 0) {
            throw new IllegalArgumentException("Negative index.");
        }
        if (index >= count) {
            throw new IllegalArgumentException(String.format("Supplied index %d is not less than %d", index, count));
        }
    }
}

Here is an example Comparator for the Name of a Student

import java.util.Comparator;

public class NameComparator implements Comparator<Student> {

    @Override
    public int compare(Student student1, Student student2) {
        int result;
        if (student1 == null) {
            if (student2 == null) {
                result = 0;
            }
            else {
                result = -1;
            }
        }
        else {
            if (student2 == null) {
                result = 1;
            }
            else {
                result = student1.getName().getFullName().compareTo(student2.getName().getFullName());
            }
        }
        return result;
    }
}

So in order to search the list according to any combination of Student attributes, simply implement an appropriate Comparator and pass it to the SortedArrayList class.

EDIT 2

Following your comments from November 17, 2019.
Below is code for a "name and mobile" Comparator. As I wrote in my previous Edit, you need to write an appropriate Comparator for a given combination of Student attributes.

import java.util.Comparator;

/**
 * Compares {@code Student} name and mobile phone number.
 */
public class NameAndMobileComparator implements Comparator<Student> {
    @Override
    public int compare(Student student1, Student student2) {
        int result;
        if (student1 == null) {
            if (student2 == null) {
                result = 0;
            }
            else {
                result = -1;
            }
        }
        else {
            if (student2 == null) {
                result = 1;
            }
            else {
                result = student1.getName().getFullName().compareTo(student2.getName().getFullName());
                if (result == 0) {
                    result = student1.getMobileNo().compareTo(student2.getMobileNo());
                }
            }
        }
        return result;
    }
}
Abra
  • 19,142
  • 7
  • 29
  • 41
  • Do you still need the class name and course code? It’s the same as students class implementation. I will try your solution once I get home. – Cash- Nov 11 '19 at 00:34
  • Besides that let’s say I want to search by name or search by group number. How would i implement it in this ADT list I made? That’s the main purpose of this project to be honest to be able to filter by attributes of a class. – Cash- Nov 11 '19 at 00:45
  • But yes implement it in binary search format instead – Cash- Nov 11 '19 at 00:46
  • @Cash- Method `search()` in interface `SortedListInterface` takes a parameter whose type is the same as the type of each element in the list and not an attribute of that type. So if you want to search according to an attribute, you need to write an appropriate implementation of interface `Comparable` in class `Student`. So if you want help with that, then yes, I need the code for classes `Name` and `Course`. – Abra Nov 11 '19 at 05:26
  • Hello thank you for getting back. I will post the code. What are you looking for specially? The attributes of course and name class? Their actually the same as student class just that less members. So yeah if you want to wait for me to post the code might take a while instead of visualising how the code looks and implement from there. – Cash- Nov 11 '19 at 05:29
  • @Cash- I don't think it's a good idea for me to try to provide an answer based on a guess of what your code is. Please [edit] your question and post the code for classes `Name` and `Course`. I am in no hurry to answer your question. I will wait until you post your code. – Abra Nov 11 '19 at 05:37
  • Hello. I have updated the post with Course and Name class. Feel free to take a look. – Cash- Nov 11 '19 at 08:32
  • Just to let you know I can’t use any built in Java API like the collections class which has a binary search to search by members of a class combined with the usage of comparator. It requires to be pure manual implementation. – Cash- Nov 12 '19 at 01:12
  • By the way I have my own way to look for attributes if it’s possible it’s going to be list[i].toString().contains(“keyword”) in the binary search implementation , since I have no other ways to do it. I am also quite a rush to finish this mini project I am assigned it – Cash- Nov 13 '19 at 00:53
  • Let me know that approach above is appropriate. Might not really make sense but it’s my back up approach – Cash- Nov 13 '19 at 00:54
  • Will post the binary implementation of my approach later. – Cash- Nov 13 '19 at 00:55
  • Sorry for the late response. Apparently I haven't tried out your code. But looks like is what I expected to use comparator since I did my own google search lots of results are recommending comparator so I got no choice it that API. Apparently you need to implement method compareTo itself so it doesn't matter if I used a pre-built API library from Java. – Cash- Nov 17 '19 at 00:56
  • 1 Final favor from you. How are you going to implement the algorithm to search for multiple same items in a binary search function? Since these functions you wrote above only search for a single item that matches. – Cash- Nov 17 '19 at 00:57
  • How will you implement a binary search function that will continue searching for the items that matches a criteria instead of searching 1 time and stop the search I want it to continue searching and then stop once it cannot find any matching items anymore. – Cash- Nov 17 '19 at 00:57
  • My approach is to implement exponential search in the binary code above to let it go for multiple items and doing a count as well. What is your approach for this algorithm in binary search? It needs to count the occurrence of the same items too. Example, I want to search by student name John. and there 3 people with the same name in the list and it will return 3 results found as well as displaying the 3 students inforamtion with name start with John. – Cash- Nov 17 '19 at 00:58
  • Is my approach for implementing exponential search algorithm combined with binary search a good approach? Or is there a better way you would implement? If so please show me. Then I can finalize your answer. Thanks for your help. Sorry if I am asking too much. – Cash- Nov 17 '19 at 00:58
  • @Cash- Lots of comments but basically one question: Find all matching keys. See [Finding multiple entries with binary search](https://stackoverflow.com/questions/12144802/finding-multiple-entries-with-binary-search) – Abra Nov 17 '19 at 01:48
  • Btw tho, if I decided to do search by keyword say name " John " passing into the parameter of the binary search. This will be another whole new implementation than using compartor? Because that was actually my intentions from the beginning searching attributes with the user's input say I search mobile " 013223 " it will search through the list with binary search and return all results that has mobile matching " 0132333 " with binary search method. – Cash- Nov 17 '19 at 01:58
  • `int mid = lo + hi / 2;` This does not do what you want. Division takes precedence over addition, so this is equivalent to `int mid = lo + (hi / 2);` – kaya3 Nov 17 '19 at 01:59
  • @Cash- create an instance of `Student` that contains your search criteria and pass it to the `search()` method. – Abra Nov 17 '19 at 02:10
  • @Abra , Okay. Well that's another step. Guess there's no other way but to create another step. Thinking I could actually pass in a parameter. But the implementation will become kinda complex combined with comparator. – Cash- Nov 17 '19 at 02:12
  • @Abra , This approach (low + high) >>> 1 is the same as ( low + high ) / 2 ? Just that you want to prevent overflow? Can I replace it with ( low + high ) / 2 ? – Cash- Nov 17 '19 at 02:22
  • @Cash- _Can I replace it with ( low + high ) / 2 ?_ Just try it and see if it works. – Abra Nov 17 '19 at 02:24
  • @Abra , lol for some reason I tried the basic comparable binary search. When its true my netbeans remain running without any output likes it crashed. I tried printing the result it still remains running but no output onconsole. – Cash- Nov 17 '19 at 02:57
  • @Abra , When its false the program runs successfully but when its true it remains running and never stops. – Cash- Nov 17 '19 at 02:58
  • 1
    You'll get an infinite loop because you're checking `.equals` instead of if `.compareTo(...) == 0`. The `Student` class doesn't override `.equals`. – kaya3 Nov 17 '19 at 03:16
  • @kaya3 , thank you I changed to compareto == 0. Din't notice that. My bad for using his code blindly without understanding. – Cash- Nov 17 '19 at 03:20
  • @kaya3 , I am kinda confused of this comparator. Is there anyway I can initiate the function based on Abra's code? Sorry if I am asking too many help. if( comparator == null ) <--- where do I know when its not null? In the search function above the code – Cash- Nov 17 '19 at 03:45
  • int cmp = comparator.compare(midVal, key); <--- this part here is returning null. I need to understand how do i know ifs not null so I can use the comparator binary search. – Cash- Nov 17 '19 at 04:16
  • public SortedArrayList(Comparator super TYPE> c) Is there anything I need to pass in here? – Cash- Nov 17 '19 at 04:37