Skip to content

Commit 4b7d4dc

Browse files
committed
feat: add interpolation search
1 parent dbd8386 commit 4b7d4dc

2 files changed

Lines changed: 131 additions & 0 deletions

File tree

crates/dsa/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ path = "src/algorithms/searching/binary_search.rs"
5858
name = "jump-search"
5959
path = "src/algorithms/searching/jump_search.rs"
6060

61+
[[bin]]
62+
name = "interpolation-search"
63+
path = "src/algorithms/searching/interpolation_search.rs"
64+
6165
# Sorting
6266
[[bin]]
6367
name = "bubble_sort"
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
//! # Interpolation Search
2+
//!
3+
//! To run/test, please run the following commands in your terminal
4+
//!
5+
//! ```sh
6+
//! cargo run --bin interpolation-search
7+
//! ```
8+
//!
9+
//! ```sh
10+
//! cargo test --bin interpolation-search
11+
//! ```
12+
//!
13+
//! Interpolation search is an improvement of a binary search algorithm that
14+
//! uses a more efficient way to find the desired element in a sorted array.
15+
//!
16+
//! Instead of checking the middle element, interpolation search uses a linear
17+
//! interpolation formula with the help of probe elements to find the next
18+
//! position to be checked.
19+
//!
20+
//! In a uniformly distributed sorted array, the time complexity of interpolation
21+
//! search is O(log log n), making it faster than binary search's O(log n).
22+
//!
23+
//! Example:
24+
//!
25+
//! we have an array `[1, 3, 4, 6, 7, 8, 9, 11, 15]` and we want to find out an
26+
//! index of `7`.
27+
//!
28+
//! ### Interpolation Formula
29+
//!
30+
//! The position to be probed is calculated using the formula:
31+
//!
32+
//! ```
33+
//! pos = low + ((item - array[low]) * (high - low)) / (array[high] - array[low])
34+
//! ```
35+
//!
36+
//!
37+
//! ### steps
38+
//! 1. calculate the probe position using interpolation formula
39+
//! 2. compare the item at probe position with the desired item
40+
//! 3. if the item matches, return the index
41+
//! 4. if the item is less than the desired item, repeat the process in the
42+
//! right sub-array, otherwise, repeat in the left sub-array.
43+
//! 5. if the item is not found, return None
44+
//!
45+
use std::cmp::Ordering::{Equal, Greater, Less};
46+
use utils::parse_input; // common library for this repository
47+
48+
fn interpolation_search(
49+
array: &Vec<i32>,
50+
low: Option<usize>,
51+
high: Option<usize>,
52+
item: i32,
53+
) -> Option<usize> {
54+
if array.is_empty() {
55+
return None;
56+
}
57+
58+
// initially, probe the entire array if probe is not provided
59+
let (Some(mut low), Some(mut high)) = (low, high) else {
60+
return interpolation_search(array, Some(0), Some(array.len() - 1), item);
61+
};
62+
63+
// check if the item is within the range of the array
64+
// `high` and `low` are usize types, so they do not need to be checked for
65+
// negative values
66+
if high >= array.len() || low >= array.len() {
67+
return None;
68+
}
69+
70+
// if the item is out of the range of the current sub-array
71+
// this also avoids division by zero in the interpolation formula
72+
if array[high] == array[low] && array[low] != item {
73+
return None;
74+
}
75+
let position = low as i32
76+
+ ((item as i32 - array[low]) * (high - low) as i32) / (array[high] - array[low]);
77+
78+
if position < 0 || position as usize >= array.len() {
79+
return None;
80+
}
81+
match array[position as usize].cmp(&item) {
82+
Less => {
83+
low = position as usize + 1;
84+
}
85+
Greater => {
86+
if position as usize == 0 {
87+
return None;
88+
}
89+
high = position as usize - 1;
90+
}
91+
Equal => return Some(position as usize),
92+
}
93+
return interpolation_search(array, Some(low), Some(high), item);
94+
}
95+
96+
fn main() {
97+
let sorted_array = vec![1, 4, 7, 8, 9, 10, 11, 12, 15, 20];
98+
println!("Sorted Array: {:?}", &sorted_array);
99+
// ! input() is a common library function, not included in std
100+
if let Ok(search_item) = parse_input("Enter a number to search: ") {
101+
return match interpolation_search(&sorted_array, None, None, search_item) {
102+
Some(idx) => println!("The item {} is at index: {}", search_item, idx),
103+
None => println!("The item {} does not exist in the array", search_item),
104+
};
105+
}
106+
println!("Invalid number Entered")
107+
}
108+
#[cfg(test)]
109+
mod tests {
110+
use crate::interpolation_search;
111+
112+
#[test]
113+
fn search_ok() {
114+
assert_eq!(
115+
interpolation_search(&vec![1, 4, 2, 5, 7], None, None, 5),
116+
Some(3)
117+
)
118+
}
119+
120+
#[test]
121+
fn search_err() {
122+
assert_eq!(
123+
interpolation_search(&vec![1, 4, 2, 5, 7], None, None, 8),
124+
None
125+
)
126+
}
127+
}

0 commit comments

Comments
 (0)