Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用比较器的二进制搜索_Java_Comparator_Binary Search_Functor - Fatal编程技术网

Java 使用比较器的二进制搜索

Java 使用比较器的二进制搜索,java,comparator,binary-search,functor,Java,Comparator,Binary Search,Functor,我正在努力让它工作。我需要编写一个函子,它将使用二进制搜索算法来查找长度在12到15个单位之间的阶梯 以下是二进制搜索: public static <AnyType> int binarySearch(GenericSimpleArrayList<AnyType> a, AnyType x, Comparator<? super AnyType> cmp) { int low = 0; int high = a.size() - 1;

我正在努力让它工作。我需要编写一个函子,它将使用二进制搜索算法来查找长度在12到15个单位之间的阶梯

以下是二进制搜索:

public static <AnyType> int binarySearch(GenericSimpleArrayList<AnyType> a, AnyType x, Comparator<? super AnyType> cmp) {
    int low = 0;
    int high = a.size() - 1;
    int mid;
    while (low <= high) {
        mid = (low + high) / 2;
        if (cmp.compare(a.get(mid), x) < 0) {
            low = mid + 1;
        } else if (cmp.compare(a.get(mid), x) > 0) {
            high = mid - 1;
        } else {
            return mid;
        }
    }
    return NOT_FOUND; // NOT_FOUND = -1
}
publicstaticintbinarysearch(genericsimplearraylista,AnyType x,Comparator尝试以下方法:

public class FindLadder implements Comparator<Ladder>{
  @Override
  public int compare(Ladder lhs, Ladder rhs) {
    if(lhs.length() < rhs.length() && lhs.length() > 12) // Suppose rhs.length() is 15
    {
        return 0;
    }
    if(lhs.length() < 12) {
        return -1;
    }
    else {
        return 1;
    }
  }
}
公共类FindLadder实现比较器{
@凌驾
公共整数比较(左梯形图、右梯形图){
if(lhs.length()12)//假设rhs.length()为15
{
返回0;
}
如果(左侧长度()<12){
返回-1;
}
否则{
返回1;
}
}
}
用x=15调用
binarySearch()
。就像
LibraryComparator.binarySearch(l,新梯形图(15),新FindLadder());


我硬编码了
12
。没有其他方法。

您显然希望/需要实现您自己的二进制搜索,但还是让我参考内置方法

从以下文件的javadoc:

返回搜索键的索引(如果它包含在列表中);否则,
((插入点)-1)
。插入点定义为将键插入列表的点:大于键的第一个元素的索引,或
list.size()
如果列表中的所有元素都小于指定的键。请注意,这保证了当且仅当找到键时返回值>=0

这里的关键是插入点,或者换句话说,返回的索引指向第一个元素,即>=搜索值,或者
size()
(如果不存在这样的元素)。没有
NOT\u FOUND
返回值

由于您需要介于
12
15
之间的值,请搜索
12
,然后通过破解Collections.binarySearch验证是否找到了值,以及该值是否为短版本 该框架具有,您应该使用它们

内置的
binarySearch
函数始终将pivot元素作为第二个参数提供给比较器。这是未记录的行为,但我们可以使用以下比较器利用这一点:

public static class FindLadderInterval implements Comparator<Ladder> {
  public final int min, max;
  public FindLadderInterval(int min, int max) {
    this.min = min;
    this.max = max;
  }
  @Override
  public int compare(Ladder lhs, Ladder rhs) {
    // ignore rhs
    int length = lhs.length();
    return length < this.min ? -1 : length > this.max ? 1 : 0;
  }
}
工作示例:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Main2 {

  public static class Ladder {
    private final int _length;

    public Ladder(int length) {
      this._length = length;
    }

    public int length() {
      return this._length;
    }

    @Override
    public String toString() {
      return "Ladder(" + this._length + ")";
    }
  }

  public static class FindLadderInterval implements Comparator<Ladder> {
    public final int min, max;

    public FindLadderInterval(int min, int max) {
      this.min = min;
      this.max = max;
    }

    @Override
    public int compare(Ladder lhs, Ladder rhs) {
      // ignore rhs
      int length = lhs.length();
      return length < this.min ? -1 : length > this.max ? 1 : 0;
    }
  }

  public static void main(String[] args) {
    List<Ladder> list = new ArrayList<Ladder>();

    list.add(new Ladder(1));
    list.add(new Ladder(2));
    list.add(new Ladder(6));
    list.add(new Ladder(13));
    list.add(new Ladder(17));
    list.add(new Ladder(21));

    int index = Collections.binarySearch(list, null,
        new FindLadderInterval(12, 15));
    System.out.println("index: " + index);
    System.out.println("ladder: " + list.get(index));
  }
}
要使用内置的
Collections.binarySearch
或您的函数,您需要提供一个具有代表性的元素,这在按字符串长度排序时非常困难。要查找长度为15的字符串,必须提供长度为15的字符串。这就是为什么我更喜欢python样式的排序,它使用key函数或选择器。基本上,您不需要比较,只需要映射到一个可比较的值。例如,从
String
Integer
的映射,如
s->s.length()
。这样就可以实现像这样的甜美函数(lambdas使它变得漂亮):


确保binarySearch算法的前提条件:

  • 项目必须提前按升序存储
  • 您必须提供具有要查找的功能的项
那就试试这个

public int compare(Ladder lhs, Ladder rhs) {
    boolean isLhsInRange = lhs.length() >= 12 && lhs.length() <= 15;
    boolean isRhsInRange = rhs.length() >= 12 && rhs.length() <= 15;
    if(isLhsInRange && isRhsInRange) return 0;
    else return lhs.length() - rhs.length();
}
public int比较(梯形图左侧、右侧){

布尔值isLhsInRange=lhs.length()>=12&&lhs.length()=12&&rhs.length()好的,我有另一个类似的functor类做同样的事情。我如何调用binarySearch方法,同时也应用我需要的条件?我不确定这是否正确。可能的返回值是
-1
0
1
@SarahvdByl我不能得到你说的东西?@Saud例如,在我的主方法中,我curre使用
LibraryComparator.binarySearch(l,15,new Length());
这不起作用。我不知道如何指定我正在搜索12到15个单位长的阶梯。@SarahvdByl您的
binarySearch
方法只有一个参数
x
,它可以与其他阶梯进行比较。如果您想获得特定范围内的阶梯,需要两个参数
x
y
。任何需要在
A
B
之间查找内容的搜索方法,其本质上都需要同时知道
A
B
,即上下边界。您的搜索方法只需要1
x
,那么您如何分辨这两个数字
12
15
嗯,这就是我正在努力的地方。我看不到任何可能的方法。我可以硬编码它,因为我知道我要寻找的梯子的位置,但显然可以在函子中做一些事情来避免这种情况。@SarahvdByl我编辑了我的答案。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Main2 {

  public static class Ladder {
    private final int _length;

    public Ladder(int length) {
      this._length = length;
    }

    public int length() {
      return this._length;
    }

    @Override
    public String toString() {
      return "Ladder(" + this._length + ")";
    }
  }

  public static class FindLadderInterval implements Comparator<Ladder> {
    public final int min, max;

    public FindLadderInterval(int min, int max) {
      this.min = min;
      this.max = max;
    }

    @Override
    public int compare(Ladder lhs, Ladder rhs) {
      // ignore rhs
      int length = lhs.length();
      return length < this.min ? -1 : length > this.max ? 1 : 0;
    }
  }

  public static void main(String[] args) {
    List<Ladder> list = new ArrayList<Ladder>();

    list.add(new Ladder(1));
    list.add(new Ladder(2));
    list.add(new Ladder(6));
    list.add(new Ladder(13));
    list.add(new Ladder(17));
    list.add(new Ladder(21));

    int index = Collections.binarySearch(list, null,
        new FindLadderInterval(12, 15));
    System.out.println("index: " + index);
    System.out.println("ladder: " + list.get(index));
  }
}
public static <T, R extends Comparable<? super R>> int intervalBinarySearchBy(
    List<T> list, R min, R max, Function<? super T, ? extends R> selector) {
  int idx = binarySearchBy(list, max, selector);
  if (idx >= 0) return idx;
  // Collections.binarySearch returns the insertion index binary
  // negated if the element was not found
  idx = ~idx;
  return (idx < list.size()
    && min.compareTo(selector.apply(list.get(idx))) <= 0) ? idx : -1;
}
List<Person> list = getPersons();
Person youngest = minBy(list, p -> p.getAge());
Person tallest = maxBy(list, p -> p.getHeight());
Person person42 = findBy(list, 42, p -> p.getAge());
sortBy(list, p -> p.getAge());
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;

public class Main {

  public static class Collections2 {

    /**
     * Mimics Collections.binarySearch
     * 
     * @param list
     * @param pivotKey
     * @param selector
     * @return
     */
    public static <T, R extends Comparable<? super R>> int binarySearchBy(
        List<T> list, R pivotKey,
        Function<? super T, ? extends R> selector) {
      int low = 0;
      int high = list.size() - 1;
      while (low <= high) {
        int mid = (low + high) >>> 1;
        int ord = selector.apply(list.get(mid)).compareTo(pivotKey);
        if (ord < 0) {
          low = mid + 1;
        } else if (ord > 0) {
          high = mid - 1;
        } else {
          return mid;
        }
      }
      return ~high; // bitwise negated insertion point /* -(a+1) == ~a */
    }

    /**
     * Finds the index of the last element in the interval, or returns -1 if
     * no such element was found.
     * 
     * @param list
     * @param min
     * @param max
     * @param selector
     * @return
     */
    public static <T, R extends Comparable<? super R>> int intervalBinarySearchBy(
        List<T> list, R min, R max, Function<? super T, ? extends R> selector) {
      int idx = binarySearchBy(list, max, selector);
      if (idx >= 0) return idx;
      // Collections.binarySearch returns the insertion index binary
      // negated if the element was not found
      idx = ~idx;
      return (idx < list.size()
        && min.compareTo(selector.apply(list.get(idx))) <= 0) ? idx : -1;
    }

    public static <T, R extends Comparable<? super R> > Comparator<T> comparatorBy(
        Function<? super T, ? extends R> selector) {
      return (a, b) -> selector.apply(a).compareTo(selector.apply(b));
    }
  }

  public static Function<Ladder, Integer> LENGTH_OF = a -> a.length();

  public static class Ladder {
    private final int _length;

    public Ladder(int length) {
      this._length = length;
    }

    public int length() {
      return this._length;
    }

    @Override
    public String toString() {
      return "Ladder(" + this._length + ")";
    }
  }

  public static void main(String[] args) {
    List<Ladder> list = new ArrayList<Ladder>();
    list.add(new Ladder(5));
    list.add(new Ladder(9));
    list.add(new Ladder(14));
    list.add(new Ladder(7));
    list.add(new Ladder(22));
    list.add(new Ladder(23));
    list.add(new Ladder(11));
    list.add(new Ladder(9));

    Collections.sort(list, Collections2.comparatorBy(LENGTH_OF));

    int i = 0;
    for (Ladder s : list) {
      System.out.println("" + (i++) + ": " + s);
    }

    int foundIdx = Collections2.intervalBinarySearchBy(list, 12, 15,
        LENGTH_OF);
    System.out.println("Index: " + foundIdx);
    System.out.println(list.get(foundIdx));
  }
}
public int compare(Ladder lhs, Ladder rhs) {
    boolean isLhsInRange = lhs.length() >= 12 && lhs.length() <= 15;
    boolean isRhsInRange = rhs.length() >= 12 && rhs.length() <= 15;
    if(isLhsInRange && isRhsInRange) return 0;
    else return lhs.length() - rhs.length();
}