module refactor

This commit is contained in:
2023-12-18 11:40:03 +08:00
parent 9a522ccb07
commit 9291180936
14 changed files with 640 additions and 591 deletions
+251
View File
@@ -0,0 +1,251 @@
use std::collections::BTreeSet;
use std::collections::HashMap;
use std::marker::PhantomData;
use super::keychecker::KeyChecker;
use super::levtrie::DistanceCalculator;
use super::result::Result;
use super::trienode::TrieKey;
use super::trienode::TrieNode;
pub enum VisitOutcome {
Continue,
Skip,
EarlyExit,
}
pub struct Trie<KEY, KEYCHECKER, PAYLOAD>
where
KEY: TrieKey,
KEYCHECKER: KeyChecker<KEY>,
{
pub nodes: Vec<TrieNode<KEY, PAYLOAD>>,
payload_initializer: fn() -> PAYLOAD,
tails: BTreeSet<usize>,
checker: PhantomData<KEYCHECKER>,
}
impl<KEY, KEYCHECKER, PAYLOAD> Trie<KEY, KEYCHECKER, PAYLOAD>
where
KEY: TrieKey,
KEYCHECKER: KeyChecker<KEY>,
{
pub fn empty(initializer: fn() -> PAYLOAD) -> Trie<KEY, KEYCHECKER, PAYLOAD> {
Trie {
nodes: vec![TrieNode::new0(None, initializer)],
payload_initializer: initializer,
tails: BTreeSet::new(),
checker: PhantomData::default(),
}
}
pub fn trie_from_words<T: IntoIterator, U: IntoIterator>(
initializer: fn() -> PAYLOAD,
wordlist: U,
) -> Trie<KEY, KEYCHECKER, PAYLOAD>
where
T: IntoIterator<Item = KEY>,
U: IntoIterator<Item = T>,
{
let mut result = Trie::empty(initializer);
for word in wordlist {
result.add(word);
}
result
}
pub fn get_node_mut(&mut self, index: usize) -> &mut TrieNode<KEY, PAYLOAD> {
&mut self.nodes[index]
}
pub fn get_node(&self, index: usize) -> &TrieNode<KEY, PAYLOAD> {
&self.nodes[index]
}
pub fn nodes(&self) -> usize {
self.nodes.len()
}
fn add_node(&mut self, key: Option<KEY>, parent: usize, prev: Option<usize>) -> usize {
let mut result = TrieNode::new0(key, self.payload_initializer);
let result_index = self.nodes();
result.parent = Some(parent);
match prev {
Some(prev_node) => {
self.get_node_mut(prev_node).next = Some(result_index);
result.prev = prev;
}
None => {
let parent_node = self.get_node_mut(parent);
match parent_node.child {
None => {
parent_node.child = Some(result_index);
}
Some(parent_child) => {
let mut node = parent_child;
loop {
let next = self.get_node(node).next;
match next {
Some(next_node) => {
node = next_node;
}
None => {
break;
}
}
}
self.get_node_mut(node).next = Some(result_index);
result.prev = Some(node)
}
}
}
}
self.nodes.push(result);
result_index
}
pub fn add<T: IntoIterator>(&mut self, path: T) -> (bool, usize)
where
T: IntoIterator<Item = KEY>,
{
let mut result = false;
let mut pnode = 0;
'wordLoop: for key in path {
let mut cnode = self.get_node(pnode).child;
loop {
match cnode {
Some(cnode_index) => {
let cnode_node = self.get_node(cnode_index);
if KEYCHECKER::check(cnode_node.key, Some(key)) {
pnode = cnode_index;
continue 'wordLoop;
} else if self.get_node(cnode_index).next.is_none() {
break;
} else {
cnode = self.get_node(cnode_index).next;
}
}
None => {
break;
}
}
}
pnode = self.add_node(Some(key), pnode, cnode);
result = true;
}
if result {
let tail = self.add_node(None, pnode, None);
self.tails.insert(tail);
let mut node = Some(tail);
loop {
match node {
Some(n) => {
let current_node = self.get_node_mut(n);
current_node.ref_count += 1;
node = current_node.parent;
}
None => {
break;
}
}
}
(true, tail)
} else {
(false, pnode)
}
}
pub fn search(&mut self, path: Vec<KEY>) -> Option<usize> {
let mut result: Option<usize> = None;
let visit_pre = |stack: &Vec<usize>| -> VisitOutcome {
if stack.len() == 1 {
VisitOutcome::Continue
} else {
let last = *stack.last().expect("");
let index = stack.len() - 2;
let node = self.get_node(last);
if index < path.len() {
if KEYCHECKER::check(node.key, Some(path[index])) {
VisitOutcome::Continue
} else {
VisitOutcome::Skip
}
} else {
if node.key.is_none() {
result = Some(last);
}
VisitOutcome::EarlyExit
}
}
};
let visit_post = |stack: &Vec<usize>| {};
self.walk(visit_pre, visit_post);
result
}
pub fn lineal_descendant(&self, start: usize) -> Vec<&KEY> {
let mut chars: Vec<&KEY> = vec![];
let mut node_option = Some(start);
loop {
match node_option {
Some(node) => {
let key = &self.get_node(node).key;
match key {
Some(key) => {
chars.push(key);
}
None => {}
}
node_option = self.get_node(node).parent;
}
None => {
break;
}
}
}
chars.reverse();
chars
}
pub fn walk<CB1, CB2>(&self, mut visit_pre: CB1, mut visit_post: CB2)
where
CB1: FnMut(&Vec<usize>) -> VisitOutcome,
CB2: FnMut(&Vec<usize>),
{
let mut stack: Vec<(usize, Option<usize>)> = vec![];
let mut public_stack: Vec<usize> = vec![];
let root_node = self.get_node(0);
stack.push((0, root_node.child));
public_stack.push(0);
visit_pre(&public_stack);
while !stack.is_empty() {
let last = &mut stack.last_mut().unwrap();
match last.1 {
Some(child_node_id) => {
let child_node = self.get_node(child_node_id);
last.1 = child_node.next;
public_stack.push(child_node_id);
let visit_pre_outcome = visit_pre(&public_stack);
match visit_pre_outcome {
VisitOutcome::Continue => {
stack.push((child_node_id, child_node.child));
}
VisitOutcome::Skip => {
stack.push((child_node_id, None));
}
VisitOutcome::EarlyExit => return,
}
}
None => {
visit_post(&public_stack);
stack.pop();
public_stack.pop();
}
}
}
}
pub fn tails(&self) -> &BTreeSet<usize> {
&self.tails
}
}