[英]How to Implement Binary Search Manually In My Own ADT [ JAVA ]
好吧,我被困在如何實現將從其他類接收數據的二進制搜索。
我正在嘗試在我自己的 ADT 中實現它。
我已經手動實現了一個列表 ADT,但現在我想添加一個手動使用二進制搜索算法並且不使用任何內置 Java API 的搜索操作。
例如,這是我手動實現的排序列表界面。
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
}
}
問題是我將創建一個學生 class ,我將在其中將學生 class 的實例添加到上面的 sortedArrayList 中。
就像我將如何在 generics 類型的 sortedArrayList 中接收要放入二進制搜索算法的數據?
請注意,我不允許使用任何 JAVA 內置 API,所有內容都必須手動實現,否則我可以輕松完成此操作,但由於其限制,現在很痛苦。
示例 我想從學生的 class 中按學生姓名進行二分搜索。 我需要如何在我的這個手動實現的 ADT 中實現和接收數據?
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..
}
}
如何將 Student class 中的屬性訪問到我自己的 ADT 中,以便我可以對二進制搜索算法進行比較?!
我真的被卡住了。
我會很感激有人給我指示。 我再次重復沒有來自 JAVA 的內置 API,僅手動實現
ADT 排序列表接口
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 實現代碼
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;
}
}
學生 Class 實現
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;
}
}
課程 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;
}
}
名稱 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 + '}';
}
二分搜索算法依賴於將正在搜索的值與正在搜索的列表中的值進行比較。 這就是為什么實現SortedListInterface
的 class 的聲明是:
SortedArrayList<T extends Comparable<T>>
請注意extends Comparable<T>
。
Comparable
是一個可以比較兩個對象的接口。 因此,在您必須實現的search()
方法中,您知道列表中的每個 object 都定義了compareTo()
方法,您只需使用該方法將正在搜索的 object 與列表中的各個對象進行比較。
這是在您的項目上下文中二進制搜索算法的簡單實現。
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;
}
使用方法,您有一個方法參數。 在方法代碼中,您使用參數名稱。 但是當您從其他代碼調用該方法時,您提供了一個替換參數的值。 同樣,當您創建 class SortedArrayList
的實例時,上面的代碼使用類型參數替換為實際 class 的名稱。 在您的情況下, T
替換為Student
並且 class Student
必須實現compareTo()
方法。 因此方法search()
,在 class SortedArrayList
不需要知道 class Student
中的成員。
所以你首先要像這樣創建一個SortedArrayList
的實例:
SortedArrayList<Student> theList = new SortedArrayList<>();
然后你可以像這樣調用search()
方法:
Student s = new Student(/* relevant parameter values */);
theList.search(s);
我了解您不一定要搜索Student
,您可能想搜索學生的Name
或學生的手機號碼。 在那種情況下,我相信你需要一個Comparator 。 這是 class SortedArrayList
的代碼,添加了一個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));
}
}
}
這是Student
Name
的示例Comparator
器
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;
}
}
因此,為了根據Student
屬性的任意組合搜索列表,只需實現適當的Comparator
並將其傳遞給SortedArrayList
class。
關注您 2019 年 11 月 17 日的評論。
下面是“姓名和手機” Comparator
器的代碼。 正如我在之前的Edit中所寫,您需要為給定的Student
屬性組合編寫一個適當的Comparator
。
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;
}
}
與所有二進制搜索一樣,這需要一個排序列表。 特別是,該算法要求列表必須按升序排序。
Start from a middle point.
int p = (high - low)/2;
If the value at p is greater than the target.
high = p;
p = low + (high - low)/2;
if the value at p is less than the target.
low = p;
p = low + (high - low)/2;
continue until low > high
編輯:
以下可能是一種檢索要在 ADT 中搜索的對象的方法。
public static void main(String[] args) {
MyFoo<Student> s = new MyFoo<>(new Student());
System.out.println(s.doit());
MyFoo<Account> a = new MyFoo<>(new Account());
System.out.println(a.doit());
}
}
interface SearchableItem {
Object getItem();
}
class MyFoo<T extends SearchableItem> {
T obj;
public MyFoo(T item) {
this.obj = item;
}
public Object doit() {
return obj.getItem();
}
}
class Student implements SearchableItem {
String name = "Melissa";
public Object getItem() {
return name;
}
}
class Account implements SearchableItem {
double balance = 10220;
public Object getItem() {
return balance;
}
}
您只能按用於對列表進行排序的順序進行二進制搜索。
看起來列表是按列表元素中的Comparable
實現排序的,因此您必須使用它。
例如,如果您想按姓名對學生進行排序和搜索,則Student.compareTo
必須按姓名排序,而您的二分搜索必須根據list[mid].compareTo(desiredItem)
做出決定
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.