2016-05-31 31 views
2
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]一个错误说if语句类型不匹配拉斯特

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 

我无法弄清楚如何重写这个功能,以满足类型检查递归函数。我认为这是因为我有返回类型设置为布尔和有返回函数调用?

回答

5

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的保护条款。

再就是如果搜索相比,最大的值的值的堆栈溢出的问题......你需要忽略枢轴复发时:

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

+1

是不是Eq特质不必要? Ord包含PartialOrd + Eq。是的,当然这只是为了学习的目的。 – leshow

+0

@leshow yep;我没有想到它就复制了它;在最后一个版本中删除了也修复了无限递归错误。 – Shepmaster

+0

感谢与比赛的提示,这是一个很好的写作方法。 – leshow

5

这里的问题是,锈评估if/else if/else if返回值,因为它缺乏一个else条款,并且不计算任何值语句有型()。顺便提一句,你所提供的代码包含了所有的可能性(片的当前索引处的项等于,小于或大于目标),但编译器不知道,除非你给它一个else条款底:

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] { 
     return true; 
    } else if list[guess] > target { 
     return recursive_binary_search(&list[0..guess], target); 
    } else { 
     return recursive_binary_search(&list[guess..list.len()], target); 
    } 
} 

PS:这个功能不需要可变的引用,所以我建议你使用普通引用如上面我的代码。

编辑:对于后人,这里是相同的代码W/O明确的回报:

fn recursive_binary_search<T: Ord>(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) 
    } 
}