簡體   English   中英

實現我自己的 Collections.binarySearch 方法

[英]Implementing my own Collections.binarySearch method

目前我正在自學 java 並且正在我的教科書中做一個練習,它要求我在一個帶有相應電話號碼的文本文件中取 1000 個名字,並基本上詢問用戶他們想要搜索什么。

我的代碼現在所做的是使用Collections.binarySearch查找電話號碼或查找姓名。 然而,我想知道如何實現我自己的二分搜索,因為本章基本上是對搜索和排序的介紹,所以我想我自己會學到更多。

這是我的代碼的重要部分

這里我使用了comparable接口

public int compareTo(Item otherObject)
   {
      Item other = (Item) otherObject;
      return key.compareTo(other.key);
   }

然后我通過以下方式將電話號碼和姓名添加到 ArrayLists 中

 // Read a line containing the name
       String name = in.nextLine();
         // Read a line containing the number
       String number = in.nextLine();
         // Store the name and number in the byName array list
         byName.add(new Item(name, number));
         // Store the number and name in the byNumber array list
         byNumber.add(new Item(number, name));

然后調用另一個方法

int index = Collections.binarySearch(byName, new Item(k,""));
   if(index<0) return null;
   return byName.get(index).getValue();

我還有另一種可以通過電話搜索的byPhone

從而正確地找到一切。

我的問題

我想知道的是如何實現我自己的方法來執行二進制搜索。 我已經對數組進行了二進制搜索並在數組中找到了一個數字,但是由於我們正在處理對象和數組列表,因此我很難真正理解該方法將如何設置。

例如我想做一個這樣的方法:

int myBinarySearch(ArrayList<Item> thisItem, Object Item)
    {
            // search logic here
    }

但是我不確定這是否是正確的方法。 鑒於我在數組列表中有一堆需要排序的對象,而不是一個簡單的數組,有人可以指導我如何准確地格式化我的方法以進行二分查找。

當前工作代碼

這是我當前使用Collections.binarySearch工作方法的完整代碼

/Item.java:

/**
   An item with a key and a value.
*/
public class Item implements Comparable<Item>
{
   private String key;
   private String value;
   /**
      Constructs an Item object.
      @param k the key string
      @param v the value of the item
   */
   public Item(String k, String v)
   {
      key = k;
      value = v;
   }
   /**
      Gets the key.
      @return the key
   */
   public String getKey()
   {
      return key;
   }
   /**
      Gets the value.
      @return the value
   */
   public String getValue()
   {
      return value;
   }
   public int compareTo(Item otherObject)
   {
      Item other = (Item) otherObject;
      return key.compareTo(other.key);
   }
}

//LookupTable.java:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
/**
   A table for lookups and reverse lookups
*/
public class LookupTable
{
   private ArrayList<Item> byName;
   private ArrayList<Item> byNumber;
   /**
      Constructs a LookupTable object.
   */
   public LookupTable()
   {
      byName = new ArrayList<Item>();
      byNumber = new ArrayList<Item>();
   }
   /**
      Reads name and number pairs from the Scanner
      and adds them to the byName and byNumber array lists.
      @param in the scanner for reading the input
   */
   public void read(Scanner in)
   {
      while (in.hasNextLine())
      {
         // Read a line containing the name
       String name = in.nextLine();
         // Read a line containing the number
       String number = in.nextLine();
         // Store the name and number in the byName array list
         byName.add(new Item(name, number));
         // Store the number and name in the byNumber array list
         byNumber.add(new Item(number, name));
      }
      // Sort the byName Items so we can binary search
      Collections.sort(byName);
      // Sort the byNumber Items so we can binary search
      Collections.sort(byNumber);
   }
   /**
      Looks up an item in the table.
      @param k the key to find
      @return the value with the given key, or null if no
      such item was found.
   */
   public String lookup(String k)
   {
      // Use the Collections.binarySearch() method to find the
      // position of the matching name in the byName array list.
      // Return null if position is less than 0 (not found).
      // Otherwise, return the number for the found name.
     int index = Collections.binarySearch(byName, new Item(k,""));
   if(index<0) return null;
   return byName.get(index).getValue();
   }
   /**
      Looks up an item in the table.
      @param v the value to find
      @return the key with the given value, or null if no
      such item was found.
   */
   public String reverseLookup(String v)
   {
      // Use the Collections.binarySearch() method to find the
      // position of the matching number in the byNumber array list.
      // Return null if position is less than 0 (not found).
      // Otherwise, return the name for the found number.
     int index = Collections.binarySearch(byNumber, new Item(v, ""));
   if(index<0) return null;
   return byNumber.get(index).getValue();
   }
}

//PhoneLookup.java:

import java.io.IOException;
import java.io.FileReader;
import java.util.Scanner;
/* The input file has the format
Abbott, Amy
408-924-1669
Abeyta, Ric
408-924-2185
Abrams, Arthur
408-924-6120
Abriam-Yago, Kathy
408-924-3159
Accardo, Dan
408-924-2236
Acevedo, Elvira
408-924-5200
Acevedo, Gloria
408-924-6556
Achtenhagen, Stephen
408-924-3522
. . .
*/
public class PhoneLookup
{
   public static void main(String[] args) throws IOException
   {
      Scanner in = new Scanner(System.in);
      System.out.println("Enter the name of the phonebook file: ");
      String fileName = in.nextLine();
      LookupTable table = new LookupTable();
      FileReader reader = new FileReader(fileName);
      table.read(new Scanner(reader));
      boolean more = true;
      while (more)
      {
         System.out.println("Lookup N)ame, P)hone number, Q)uit?");
         String cmd = in.nextLine();
         if (cmd.equalsIgnoreCase("Q"))
            more = false;
         else if (cmd.equalsIgnoreCase("N"))
         {
            System.out.println("Enter name:");
            String n = in.nextLine();
            System.out.println("Phone number: " + table.lookup(n));
         }
         else if (cmd.equalsIgnoreCase("P"))
         {
            System.out.println("Enter phone number:");
            String n = in.nextLine();
            System.out.println("Name: " + table.reverseLookup(n));
         }
      }
   }
}

您可以從 JDK 源代碼中找到 JDK 是如何做到的。 java.util.Collections

private static <T>
    int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key)

與您正在工作的人非常相似。

二分查找是一種非常簡單的算法。 在偽代碼中,它是:

find(list, item):
    if list is empty
        return not found
    get middle item from list
    if item matches middle
        return middle
    else if item is before middle
        return find(list before middle, item)
    else
        return find(list after middle, item)

必須對列表進行排序以允許此操作。 您可以使用List.subList來避免進行任何復制或傳遞索引。

在您的情況下,您希望能夠按多個條件進行搜索。 如果您將一個參數傳遞給您的方法來定義您正在搜索的內容,那將是最有意義的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM