Skip to content

Instantly share code, notes, and snippets.

@devfans
Last active February 26, 2021 08:51
Show Gist options
  • Select an option

  • Save devfans/e8db38674c5514ca5b7ab2f81af70157 to your computer and use it in GitHub Desktop.

Select an option

Save devfans/e8db38674c5514ca5b7ab2f81af70157 to your computer and use it in GitHub Desktop.
use std::hash::{ Hasher, Hash };
use std::collections::{LinkedList, hash_map::DefaultHasher};
fn hash<K>(k: K) -> usize where K: Hash{
let mut hasher = DefaultHasher::new();
k.hash(&mut hasher);
hasher.finish() as usize
}
struct HashMap<K, V> {
store: Box<[LinkedList<(K, V, bool)>]>,
size: usize,
}
impl<K, V> HashMap<K, V> where K: Clone + Hash + Eq, V: Clone {
pub fn new(n: usize) -> Self {
let mut store = Vec::new();
store.resize(n, LinkedList::<(K, V, bool)>::new());
Self {
store: store.into_boxed_slice(),
size: n,
}
}
pub fn insert(&mut self, k: K, v: V) {
let idx = hash(k.clone());
let state = self.store.get_mut(idx % self.size).unwrap();
let mut added = false;
for item in state.iter_mut() {
if !item.2 {
if !added {
item.0 = k.clone();
item.1 = v.clone();
item.2 = true;
added = true;
}
} else if item.0 == k {
if added {
item.2 = false
} else {
item.1 = v.clone();
item.2 = true;
added = true
}
}
}
if !added {
state.push_back((k, v, true));
}
}
pub fn get(&self, k: K) -> Option<V>{
let idx = hash(k.clone());
let state = self.store.get(idx % self.size).unwrap();
for item in state.iter() {
if item.2 && item.0 == k {
return Some(item.1.clone())
}
}
None
}
pub fn get_mut(&mut self, k: K) -> Option<&mut V>{
let idx = hash(k.clone());
let state = self.store.get_mut(idx % self.size).unwrap();
for item in state.iter() {
if item.2 && item.0 == k {
return Some(&mut item.1)
}
}
None
}
pub fn clear(&mut self) {
for state in self.store.iter_mut() {
state.clear();
}
}
pub fn len(&self) -> usize {
let mut size = 0;
for state in self.store.iter() {
for item in state.iter() {
if item.2 {
size += 1;
}
}
}
size
}
pub fn iter(&self) -> HashMapIterator<'_, K, V> {
HashMapIterator::new(self)
}
pub fn iter_mut(&mut self) -> HashMapIteratorMut<'_, K, V> {
HashMapIteratorMut::new(self)
}
}
struct HashMapIterator<'a, K, V> {
map: &'a HashMap<K, V>,
i: usize,
j: usize,
}
impl<'a, K, V> HashMapIterator<'a, K, V> {
pub fn new(map: &'a HashMap<K, V>) -> Self {
Self {
map: map,
i: 0,
j: 0,
}
}
}
impl<'a, K: Clone + Eq + Hash, V> Iterator for HashMapIterator<'a, K, V> {
type Item = (&'a K, &'a V);
fn next(&mut self) -> Option<Self::Item> {
loop {
if self.i >= self.map.store.len() {
return None;
}
let state = self.map.store.get(self.i).unwrap();
let mut k = 0;
for item in state.iter() {
if k == self.j && item.2 {
self.j+=1;
return Some((&item.0, &item.1))
}
k+=1;
}
self.j = 0;
self.i+=1;
}
}
}
struct HashMapIteratorMut<'a, K, V> {
map: &'a mut HashMap<K, V>,
i: usize,
j: usize,
}
impl<'a, K, V> HashMapIteratorMut<'a, K, V> {
pub fn new(map: &'a mut HashMap<K, V>) -> Self {
Self {
map: map,
i: 0,
j: 0,
}
}
}
impl<'a, K: Clone + Eq + Hash, V: Clone> Iterator for HashMapIteratorMut<'a, K, V> {
type Item = (K, &'a mut V);
fn next(&mut self) -> Option<Self::Item> {
let mut key: Option<K>;
'outer: loop {
if self.i >= self.map.store.len() {
return None;
}
let state = self.map.store.get_mut(self.i).unwrap();
let mut k = 0;
for item in state.iter_mut() {
if k == self.j && item.2 {
self.j+=1;
key = Some(item.0.clone());
break 'outer
}
k+=1;
}
self.j = 0;
self.i+=1;
}
// FIXME
key.map(|x| (x, self.map.get_mut(x).unwrap()))
}
}
fn main() {
let mut a = LinkedList::new();
a.push_back(3);
let mut b = a.clone();
b.push_back(4);
println!("Hello, world! {:?}", (a, b));
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hashmap() {
let mut m = HashMap::<&str, isize>::new(10);
assert_eq!(m.len(), 0);
m.insert("Hi", 1);
m.insert("Hello", 2);
assert_eq!(m.len(), 2);
assert_eq!(m.get("Hi"), Some(1));
assert_eq!(m.get("Hello"), Some(2));
m.insert("Hi", 3);
assert_eq!(m.get("Hi"), Some(3));
for (k, v) in m.iter() {
println!("{:?}:{:?}", k, v);
}
m.clear();
assert_eq!(m.len(), 0);
// assert!(false);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment