use std::{
collections::hash_map::DefaultHasher,
hash::{Hash, Hasher},
};
use super::ST;
pub struct LinearProbingHashST<K, V> {
capacity: usize,
len: usize,
keys: Vec<Option<K>>,
vals: Vec<Option<V>>,
}
impl<K: Default + Ord + Hash, V: Default> Default for LinearProbingHashST<K, V> {
fn default() -> Self {
Self::new(4)
}
}
impl<K: Ord + Hash, V> LinearProbingHashST<K, V> {
pub fn new(capacity: usize) -> Self {
let mut keys = Vec::with_capacity(capacity);
for _ in 0..capacity {
keys.push(None);
}
let mut vals = Vec::with_capacity(capacity);
for _ in 0..capacity {
vals.push(None);
}
LinearProbingHashST {
capacity,
len: 0,
keys,
vals,
}
}
pub fn hash(&self, k: &K) -> usize {
Self::hash_for_m(k, self.capacity)
}
pub fn hash_for_m(k: &K, m: usize) -> usize {
let mut hasher = DefaultHasher::new();
k.hash(&mut hasher);
hasher.finish() as usize % m
}
fn resize(&mut self, m: usize) {
let mut st = Self::new(m);
for i in 0..self.capacity {
if let Some(key) = self.keys[i].take() {
st.put(key, self.vals[i].take().unwrap());
}
}
self.capacity = st.capacity;
self.keys = st.keys;
self.vals = st.vals;
}
fn need_resize(&self) -> bool {
self.len >= self.capacity / 2
}
}
impl<K: Ord + Hash, V> ST<K, V> for LinearProbingHashST<K, V> {
fn put(&mut self, key: K, value: V) {
if self.need_resize() {
self.resize(self.capacity * 2);
}
assert!(!self.need_resize());
let mut i = self.hash(&key);
while let Some(current_key) = &self.keys[i] {
if &key == current_key {
self.vals[i] = Some(value);
return;
}
i = (i + 1) % self.capacity;
}
self.keys[i] = Some(key);
self.vals[i] = Some(value);
self.len += 1;
}
fn get(&self, key: &K) -> Option<&V> {
if self.is_empty() {
return None;
}
let mut i = self.hash(key);
while let Some(current_key) = &self.keys[i] {
if key == current_key {
return self.vals[i].as_ref();
}
let next_i = (i + 1) % self.capacity;
if next_i == i {
break;
}
i = next_i;
}
None
}
fn delete(&mut self, key: &K) {
let mut i = self.hash(key);
while let Some(current_key) = &self.keys[i] {
if key == current_key {
self.keys[i] = None;
self.vals[i] = None;
self.len -= 1;
i = (i + 1) % self.capacity;
while self.keys[i].is_some() {
self.len -= 1;
let key = self.keys[i].take().unwrap();
let value = self.vals[i].take().unwrap();
self.put(key, value);
i = (i + 1) % self.capacity;
}
return;
}
i = (i + 1) % self.capacity;
}
if self.len <= self.capacity / 8 {
self.resize(self.capacity / 2);
}
}
fn is_empty(&self) -> bool {
self.len == 0
}
fn size(&self) -> usize {
self.len
}
fn min(&self) -> Option<&K> {
self.keys.iter().filter_map(|f| f.as_ref()).min()
}
fn max(&self) -> Option<&K> {
self.keys.iter().filter_map(|f| f.as_ref()).max()
}
fn floor(&self, key: &K) -> Option<&K> {
self.keys
.iter()
.filter_map(|f| f.as_ref())
.filter(|f| f <= &key)
.max()
}
fn ceiling(&self, key: &K) -> Option<&K> {
self.keys
.iter()
.filter_map(|f| f.as_ref())
.filter(|f| f >= &key)
.min()
}
fn rank(&self, key: &K) -> usize {
self.keys
.iter()
.filter_map(|f| f.as_ref())
.filter(|f| f < &key)
.count()
}
fn select(&self, k: usize) -> Option<&K> {
let mut keys: Vec<&K> = self.keys.iter().filter_map(|f| f.as_ref()).collect();
keys.sort();
keys.get(k).copied()
}
fn contains(&self, key: &K) -> bool {
self.get(key).is_some()
}
fn delete_min(&mut self) {
if let Some(min) = self.min() {
let min = unsafe { (min as *const K).as_ref().unwrap() };
self.delete(min);
}
}
fn delete_max(&mut self) {
if let Some(max) = self.max() {
let max = unsafe { (max as *const K).as_ref().unwrap() };
self.delete(max);
}
}
fn size_in(&self, lo: &K, hi: &K) -> usize {
if hi < lo {
0
} else if self.contains(hi) {
self.rank(hi) - self.rank(lo) + 1
} else {
self.rank(hi) - self.rank(lo)
}
}
}
#[cfg(test)]
mod test {
#[test]
fn test() {
use super::LinearProbingHashST;
use crate::search::ST;
use rand::seq::SliceRandom;
let mut st = LinearProbingHashST::new(1);
let mut rng = rand::thread_rng();
let n = 530;
let mut arr: Vec<usize> = (1..=n).collect();
arr.shuffle(&mut rng);
for (i, key) in arr.iter().enumerate() {
assert_eq!(st.get(key), None);
st.put(key.clone(), key + 10);
assert_eq!(st.get(key), Some(&(key + 10)));
assert_eq!(st.size(), i + 1);
}
let mut arr: Vec<usize> = (1..=n).collect();
arr.shuffle(&mut rng);
for (i, key) in arr.iter().enumerate() {
assert_eq!(st.get(key), Some(&(key + 10)));
st.delete(&key);
assert_eq!(st.get(key), None);
assert_eq!(st.size(), arr.len() - i - 1);
}
}
}