递归二分查找

  1. use std::cmp::Ordering;
  2. pub fn binary_search_rec<T: Ord>(
  3. list_of_items: &[T],
  4. target: &T,
  5. left: &usize,
  6. right: &usize,
  7. ) -> Option<usize> {
  8. if left >= right {
  9. return None;
  10. }
  11. let middle: usize = left + (right - left) / 2;
  12. match target.cmp(&list_of_items[middle]) {
  13. Ordering::Less => binary_search_rec(list_of_items, target, left, &middle),
  14. Ordering::Greater => binary_search_rec(list_of_items, target, &(middle + 1), right),
  15. Ordering::Equal => Some(middle),
  16. }
  17. }
  18. #[cfg(test)]
  19. mod tests {
  20. use super::*;
  21. const LEFT: usize = 0;
  22. #[test]
  23. fn fail_empty_list() {
  24. let list_of_items = vec![];
  25. assert_eq!(
  26. binary_search_rec(&list_of_items, &1, &LEFT, &list_of_items.len()),
  27. None
  28. );
  29. }
  30. #[test]
  31. fn success_one_item() {
  32. let list_of_items = vec![30];
  33. assert_eq!(
  34. binary_search_rec(&list_of_items, &30, &LEFT, &list_of_items.len()),
  35. Some(0)
  36. );
  37. }
  38. #[test]
  39. fn success_search_strings() {
  40. let say_hello_list = vec!["hi", "olá", "salut"];
  41. let right = say_hello_list.len();
  42. assert_eq!(
  43. binary_search_rec(&say_hello_list, &"hi", &LEFT, &right),
  44. Some(0)
  45. );
  46. assert_eq!(
  47. binary_search_rec(&say_hello_list, &"salut", &LEFT, &right),
  48. Some(2)
  49. );
  50. }
  51. #[test]
  52. fn fail_search_strings() {
  53. let say_hello_list = vec!["hi", "olá", "salut"];
  54. for target in &["adiós", "你好"] {
  55. assert_eq!(
  56. binary_search_rec(&say_hello_list, target, &LEFT, &say_hello_list.len()),
  57. None
  58. );
  59. }
  60. }
  61. #[test]
  62. fn success_search_integers() {
  63. let integers = vec![0, 10, 20, 30, 40, 50, 60, 70, 80, 90];
  64. for (index, target) in integers.iter().enumerate() {
  65. assert_eq!(
  66. binary_search_rec(&integers, target, &LEFT, &integers.len()),
  67. Some(index)
  68. )
  69. }
  70. }
  71. #[test]
  72. fn fail_search_integers() {
  73. let integers = vec![0, 10, 20, 30, 40, 50, 60, 70, 80, 90];
  74. for target in &[100, 444, 336] {
  75. assert_eq!(
  76. binary_search_rec(&integers, target, &LEFT, &integers.len()),
  77. None
  78. );
  79. }
  80. }
  81. #[test]
  82. fn fail_search_unsorted_strings_list() {
  83. let unsorted_strings = vec!["salut", "olá", "hi"];
  84. for target in &["hi", "salut"] {
  85. assert_eq!(
  86. binary_search_rec(&unsorted_strings, target, &LEFT, &unsorted_strings.len()),
  87. None
  88. );
  89. }
  90. }
  91. #[test]
  92. fn fail_search_unsorted_integers_list() {
  93. let unsorted_integers = vec![90, 80, 70, 60, 50, 40, 30, 20, 10, 0];
  94. for target in &[0, 80, 90] {
  95. assert_eq!(
  96. binary_search_rec(&unsorted_integers, target, &LEFT, &unsorted_integers.len()),
  97. None
  98. );
  99. }
  100. }
  101. #[test]
  102. fn success_search_string_in_middle_of_unsorted_list() {
  103. let unsorted_strings = vec!["salut", "olá", "hi"];
  104. assert_eq!(
  105. binary_search_rec(&unsorted_strings, &"olá", &LEFT, &unsorted_strings.len()),
  106. Some(1)
  107. );
  108. }
  109. #[test]
  110. fn success_search_integer_in_middle_of_unsorted_list() {
  111. let unsorted_integers = vec![90, 80, 70];
  112. assert_eq!(
  113. binary_search_rec(&unsorted_integers, &80, &LEFT, &unsorted_integers.len()),
  114. Some(1)
  115. );
  116. }
  117. }