在二进制搜索中,如果找不到该元素,为什么约定从它应该做的地方减去一个?
In binarysearch, if the element isn't found, why is the convention to subtract one from where it should do?
我知道这已经深入到本质上了,但是当进行二分查找并且找不到元素时,return (-(insertion point) -1)
的合理性是什么?特别是 -1
部分。 Java 就是这样做的,我不明白为什么他们制定了约定 -1
而不是 -(insertion point)
。显然,否定是表示在 array/list 中实际上没有找到该值。我猜它来自 C,在 C 中更容易进行一些取反和减一的按位运算。
注意:我见过使用此约定的 C、C++ 和 Java 编写的代码,我想知道该约定从何而来?
这是因为插入点可能为零,而 int 没有 -0(与浮点数不同),因此您需要一些其他方式来明确表示它。
正如 Javadoc 中所说:
Note that this guarantees that the return value will be >= 0 if and only if the key is found.
当然,还有其他方式表示插入位置;这恰好非常优雅,因为它不需要额外的信息,例如容器的大小,以便用于适当地插入元素。
就公约的起源地而言 - 我敢打赌,时间的迷雾!
作为纯粹的猜想,我可以想象它会出现在 C(或者甚至更早的语言)中,它是一种比其他方法更简洁的编码值的方法。
一个"obvious"替代编码可能是用符号位表示presence/absence,其余位表示插入位置:
S PPPP....P
^ 0 means "present", 1 means "absent"
^---....^ These bits denote the position in the container.
在设置了符号位的情况下提取位置,需要屏蔽这些位。这在 Java 中很容易,其中 int 被定义为具有 32 位(只需使用 value & 0x7FFFFFF
);但是要用可移植的 C 语言编写它,您需要执行以下操作:
value = binarySearch(...);
if (value < 0) {
insertionPosition = value & ~(1 << sizeof(int) * 8 - 1);
...
}
(如果说的不太对,请原谅 - 这就是为什么 Java 程序员不应该尝试编写 C...)
即使是固定宽度,也有点神秘:
value = binarySearch(...);
if (value < 0) {
insertionPosition = value & 0x7FFFFFFF; // What's this magic number?!
...
}
如果你不得不在很多地方写的话,这很丑陋,而且很容易出错。当然,您可以编写一个小方法来为您做这个数学运算,但方法调用很昂贵(至少,它们可能在过去已经回归)。
使用 (-(insertion point) -1)
约定,您可以编写简单、易读、快速的代码:
value = binarySearch(...);
if (value < 0) {
insertionPosition = -value - 1;
...
}
我知道这已经深入到本质上了,但是当进行二分查找并且找不到元素时,return (-(insertion point) -1)
的合理性是什么?特别是 -1
部分。 Java 就是这样做的,我不明白为什么他们制定了约定 -1
而不是 -(insertion point)
。显然,否定是表示在 array/list 中实际上没有找到该值。我猜它来自 C,在 C 中更容易进行一些取反和减一的按位运算。
注意:我见过使用此约定的 C、C++ 和 Java 编写的代码,我想知道该约定从何而来?
这是因为插入点可能为零,而 int 没有 -0(与浮点数不同),因此您需要一些其他方式来明确表示它。
正如 Javadoc 中所说:
Note that this guarantees that the return value will be >= 0 if and only if the key is found.
当然,还有其他方式表示插入位置;这恰好非常优雅,因为它不需要额外的信息,例如容器的大小,以便用于适当地插入元素。
就公约的起源地而言 - 我敢打赌,时间的迷雾!
作为纯粹的猜想,我可以想象它会出现在 C(或者甚至更早的语言)中,它是一种比其他方法更简洁的编码值的方法。
一个"obvious"替代编码可能是用符号位表示presence/absence,其余位表示插入位置:
S PPPP....P
^ 0 means "present", 1 means "absent"
^---....^ These bits denote the position in the container.
在设置了符号位的情况下提取位置,需要屏蔽这些位。这在 Java 中很容易,其中 int 被定义为具有 32 位(只需使用 value & 0x7FFFFFF
);但是要用可移植的 C 语言编写它,您需要执行以下操作:
value = binarySearch(...);
if (value < 0) {
insertionPosition = value & ~(1 << sizeof(int) * 8 - 1);
...
}
(如果说的不太对,请原谅 - 这就是为什么 Java 程序员不应该尝试编写 C...)
即使是固定宽度,也有点神秘:
value = binarySearch(...);
if (value < 0) {
insertionPosition = value & 0x7FFFFFFF; // What's this magic number?!
...
}
如果你不得不在很多地方写的话,这很丑陋,而且很容易出错。当然,您可以编写一个小方法来为您做这个数学运算,但方法调用很昂贵(至少,它们可能在过去已经回归)。
使用 (-(insertion point) -1)
约定,您可以编写简单、易读、快速的代码:
value = binarySearch(...);
if (value < 0) {
insertionPosition = -value - 1;
...
}