If statement 长生不老药二进制搜索

If statement 长生不老药二进制搜索,if-statement,binary-search,elixir,If Statement,Binary Search,Elixir,我在Elixir中构建了一个二进制搜索,但最终使用了3个if子句: if actual == guessed_number, do: if actual > guessed_number do: if actual < guessed_number do: 如果实际==猜测的数字,请执行以下操作: 如果实际值>猜测值,请执行以下操作: 如果实际数 ... 实际值>猜测值-> ... 实际值 ... 结束 免责声明:不要在生产中使用此选项,这比简单的线性搜索慢,因为链表不允许在固

我在Elixir中构建了一个二进制搜索,但最终使用了3个if子句:

if actual == guessed_number, do:

if actual > guessed_number do:

if actual < guessed_number do:
如果实际==猜测的数字,请执行以下操作:
如果实际值>猜测值,请执行以下操作:
如果实际数<猜测数,请执行以下操作:

有可能不使用条件句吗?可能使用模式匹配?

使用模式匹配无法做到这一点。但是,如果,您可以使用类似于Erlang的
cond

cond do
    actual == guessed_number ->
        ...
    actual > guessed_number ->
        ...
    actual < guessed_number ->
        ...
end
cond do
实际==猜测的数字->
...
实际值>猜测值->
...
实际值<猜测值->
...
结束

免责声明:不要在生产中使用此选项,这比简单的线性搜索慢,因为链表不允许在固定时间内进行随机访问。这篇文章仅仅是关于模式匹配方面的


从理论上讲,你可以使用保护条款,但如果你使用过度,它们会让事情变得更糟。假设您从这样的实现开始:

defmodule MyEnum do
  def binsearch(collection, key) do
    binsearch(collection, key, 1, length(collection))
  end

  defp binsearch(collection, key, lo, hi) do
    if hi < lo do
      -1
    else
      mid = div(lo + hi, 2)
      item = Enum.at(collection, mid)
      cond do
        key < item -> binsearch(collection, key, lo, mid-1)
        key > item -> binsearch(collection, key, mid+1, hi)
        true       -> mid
      end
    end
  end
end
现在,您还可以将
cond
拉入,但这并不是真正的改进:

defmodule MyEnum do
  def binsearch(collection, key) do
    binsearch(collection, key, 1, length(collection))
  end

  defp binsearch(_collection, _key, low, hi) when hi < low do
    -1
  end

  defp binsearch(collection, key, low, hi) do
    mid = div(low + hi, 2)
    item = Enum.at(collection, mid)
    binsearch(collection, key, item, low, mid, hi)
  end

  defp binsearch(collection, key, item, low, mid, _hi) when key < item do
    binsearch(collection, key, low, mid-1)
  end

  defp binsearch(collection, key, item, _low, mid, hi) when key > item do
    binsearch(collection, key, mid+1, hi)
  end

  defp binsearch(_collection, _key, _item, _low, mid, _hi) do
    mid
  end
end
defmodule MyEnum do
def binsearch(收集、钥匙)do
binsearch(集合,键,1,长度(集合))
结束
当hi<低do时,解除设定B搜索(_收集,_键,低,高)
-1
结束
defp binsearch(收集、按键、低位、高位)do
中间=分区(低+高,2)
item=Enum.at(集合,mid)
B搜索(收集、键、项、低、中、高)
结束
当按键<项目do时,解除锁定搜索(收集、按键、项目、低、中、高)
B搜索(收集、键、低、中1)
结束
当按键>项目执行时,解除按键搜索(收集、按键、项目、低、中、高)
binsearch(收藏、按键、mid+1、hi)
结束
defp binsearch(_collection,_key,_item,_low,mid,_hi)do
中间
结束
结束

我也尝试过这种方法,在我看来这是有效的,但不是我想要的。谢谢你的详细回复。是的,切换cond for guard子句可能会有点复杂。只有在集合有O(1)个查找时,二进制搜索才有效
Enum.at
以线性时间运行,因此此二进制搜索比简单的线性搜索慢。谢谢,这是一个很好的观点。当我写答案时,我正处于使用长生不老药的早期阶段,可能因为我专注于模式匹配而错过了这一点。我建议在顶部添加一个关于时间复杂性的注释,这样其他人就不会感到困惑。AFAIK不可能在常规链表上进行
O(log(n)
二进制搜索。
defmodule MyEnum do
  def binsearch(collection, key) do
    binsearch(collection, key, 1, length(collection))
  end

  defp binsearch(_collection, _key, low, hi) when hi < low do
    -1
  end

  defp binsearch(collection, key, low, hi) do
    mid = div(low + hi, 2)
    item = Enum.at(collection, mid)
    binsearch(collection, key, item, low, mid, hi)
  end

  defp binsearch(collection, key, item, low, mid, _hi) when key < item do
    binsearch(collection, key, low, mid-1)
  end

  defp binsearch(collection, key, item, _low, mid, hi) when key > item do
    binsearch(collection, key, mid+1, hi)
  end

  defp binsearch(_collection, _key, _item, _low, mid, _hi) do
    mid
  end
end