recursion - 如果 Rust 中的语句类型不匹配,则递归函数

标签 recursion types rust

fn recursive_binary_search<T: Ord>(list: &mut [T], target: T) -> bool {
    if list.len() < 1 {
        return false;
    }
    let guess = list.len() / 2;
    if target == list[guess] {
        return true;
    } else if list[guess] > target {
        return recursive_binary_search(&mut list[0..guess], target);
    } else if list[guess] < target {
        return recursive_binary_search(&mut list[guess..list.len()], target);
    }
}

编译器在 if target == list[guess] 上抛出一个错误 saying

src/main.rs:33:5: 39:6 error: mismatched types [E0308]
src/main.rs:33     if target == list[guess] {
                   ^
src/main.rs:33:5: 39:6 help: run `rustc --explain E0308` to see a detailed explanation
src/main.rs:33:5: 39:6 note: expected type `bool`
src/main.rs:33:5: 39:6 note:    found type `()`
error: aborting due to previous error

我想不出如何重写这个函数来满足类型检查器的要求。我假设这是因为我将返回类型设置为 bool 并且有一个返回函数调用?

最佳答案

dikaiosune's answer 解释了这个问题:if 的结果类型是 (),它被返回而不是 bool

这里有一些更地道的编写代码的方法:

我会先用隐式返回来编写它:

fn recursive_binary_search<T: Ord + Eq>(list: &[T], target: T) -> bool {
    if list.len() < 1 {
        return false;
    }

    let guess = list.len() / 2;

    if target == list[guess] {
        true
    } else if list[guess] > target {
        recursive_binary_search(&list[0..guess], target)
    } else {
        recursive_binary_search(&list[guess..list.len()], target)
    }
}

然后我将只执行一次比较,而不是可能执行两次。如果比较很昂贵,可以节省一些时间,但它与 match 一起看起来也不错:

use std::cmp::Ordering;

fn recursive_binary_search<T: Ord + Eq>(list: &[T], target: T) -> bool {
    if list.is_empty() {
        return false;
    }

    let guess = list.len() / 2;

    match target.cmp(&list[guess]) {
        Ordering::Less    => recursive_binary_search(&list[..guess], target),
        Ordering::Greater => recursive_binary_search(&list[guess..], target),
        Ordering::Equal   => true,
    }
}

您还可以删除范围的开始和结束部分,并使用 is_empty 作为保护子句。

然后如果搜索一个大于最大值的值就会出现栈溢出的问题...需要在递归时忽略pivot:

use std::cmp::Ordering;

fn recursive_binary_search<T: Ord>(list: &[T], target: T) -> bool {
    if list.is_empty() {
        return false;
    }

    let guess = list.len() / 2;

    match target.cmp(&list[guess]) {
        Ordering::Less    => recursive_binary_search(&list[..guess], target),
        Ordering::Greater => recursive_binary_search(&list[guess+1..], target),
        Ordering::Equal   => true,
    }
}

fn main() {
    assert!(!recursive_binary_search(&[1,2,3,4,5], 0));
    assert!(recursive_binary_search(&[1,2,3,4,5], 1));
    assert!(recursive_binary_search(&[1,2,3,4,5], 2));
    assert!(recursive_binary_search(&[1,2,3,4,5], 3));
    assert!(recursive_binary_search(&[1,2,3,4,5], 4));
    assert!(recursive_binary_search(&[1,2,3,4,5], 5));
    assert!(!recursive_binary_search(&[1,2,3,4,5], 6));
}

如果您不是出于学习目的实现此功能,请使用内置的 binary_search

关于recursion - 如果 Rust 中的语句类型不匹配,则递归函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37554325/

相关文章:

python - 使用动态规划解决一个版本的背包问题

sql - 使用从列到两列的递归查询

scala - 如何编写递归匿名函数?

typescript - Typescript中两个函数的联合类型

eclipse - 在IntelliJ IDEA 10中显示 "raw type"警告列表

rust - 如何使用带有 Rocket 的 abonander/multipart 解析多部分表单?

c - 通过在堆上分配堆栈部分来避免堆栈溢出?

c - c中有多少种浮点类型?

rust - 不能将变量借用为可变的,因为在重构解析器时它也被借用为不可变的

rust - 使用 kcov 时如何从代码覆盖中排除测试函数?