平衡2分探索木の一種であるAA木をカーソルで実現したソースコードです。
wikipediaのAA木の記事にある疑似コードをほぼそのまま写しています。
AIZU ONLINE JUDGEのITP2_8_B「Map:Delete」でAcceptedになったRustのソースコードです。
use std::cmp::min;
use std::fmt::Display;
#[derive(Copy, Clone)]
struct Node<T1, T2> {
left_child: usize,
right_child: usize,
level: usize,
value: std::option::Option<(T1, T2)>,
}
impl<T1, T2> Node<T1, T2> {
fn new() -> Self {
Node {
left_child: 0,
right_child: 0,
level: 0,
value: None,
}
}
}
const SIZE: usize = 60_0000;
struct AATree<T1, T2> {
size: usize,
space: [Node<T1, T2>; SIZE],
available: usize,
}
impl<T1: Copy + PartialOrd + Display, T2: Copy> AATree<T1, T2> {
fn debug(&self, cursor: usize) {
if cursor == 0 {
if self.space[cursor].left_child == 0 {
return;
} else {
self.debug(self.space[cursor].left_child);
}
} else {
if let Some((key, _)) = self.space[cursor].value {
println!("{}, {}", cursor, key);
}
if self.space[cursor].left_child != 0 {
self.debug(self.space[cursor].left_child);
}
if self.space[cursor].right_child != 0 {
self.debug(self.space[cursor].right_child);
}
}
}
fn skew(&mut self, cursor: usize, parent_cursor: usize, left_or_right: bool) -> usize {
if cursor == 0 {
return 0;
} else if self.space[cursor].left_child == 0 {
return cursor;
} else if self.space[self.space[cursor].left_child].level == self.space[cursor].level {
let l = self.space[cursor].left_child;
self.space[cursor].left_child = self.space[l].right_child;
self.space[l].right_child = cursor;
if left_or_right {
self.space[parent_cursor].left_child = l;
} else {
self.space[parent_cursor].right_child = l;
}
return l;
} else {
return cursor;
}
}
fn split(&mut self, cursor: usize, parent_cursor: usize, left_or_right: bool) -> usize {
if cursor == 0 {
return 0;
} else if self.space[cursor].right_child == 0
|| self.space[self.space[cursor].right_child].right_child == 0
{
return cursor;
} else if self.space[cursor].level
== self.space[self.space[self.space[cursor].right_child].right_child].level
{
let r = self.space[cursor].right_child;
self.space[cursor].right_child = self.space[r].left_child;
self.space[r].left_child = cursor;
self.space[r].level += 1;
if left_or_right {
self.space[parent_cursor].left_child = r;
} else {
self.space[parent_cursor].right_child = r;
}
return r;
} else {
return cursor;
}
}
fn move_list_for_insert(
&mut self,
key: T1,
x: T2,
_cursor: usize,
parent_cursor: usize,
left_or_right: bool,
) {
let old_available = self.available;
self.available = self.space[old_available].left_child;
self.space[old_available].left_child = 0;
self.space[old_available].right_child = 0;
self.space[old_available].value = Some((key, x));
if left_or_right {
self.space[parent_cursor].left_child = old_available;
} else {
self.space[parent_cursor].right_child = old_available;
}
}
fn inside_insert(
&mut self,
key: T1,
x: T2,
mut cursor: usize,
parent_cursor: usize,
left_or_right: bool,
) {
if cursor == 0 {
if parent_cursor == 0 && self.space[cursor].left_child != 0 {
self.inside_insert(key, x, self.space[cursor].left_child, cursor, true);
return;
}
self.size += 1;
self.move_list_for_insert(key, x, cursor, parent_cursor, left_or_right);
return;
} else {
if let Some((node_key, _)) = &self.space[cursor].value {
if key < *node_key {
self.inside_insert(key, x, self.space[cursor].left_child, cursor, true);
} else if key > *node_key {
self.inside_insert(key, x, self.space[cursor].right_child, cursor, false);
} else {
self.space[cursor].value = Some((key, x));
}
}
}
cursor = self.skew(cursor, parent_cursor, left_or_right);
self.split(cursor, parent_cursor, left_or_right);
}
pub fn insert(&mut self, key: T1, x: T2) {
self.inside_insert(key, x, 0, 0, true);
}
fn move_list_for_delete(&mut self, cursor: usize, parent_cursor: usize, left_or_right: bool) {
let old_available = self.available;
self.available = cursor;
self.space[cursor].left_child = old_available;
self.space[cursor].right_child = 0;
self.space[cursor].value = None;
if left_or_right {
self.space[parent_cursor].left_child = 0;
} else {
self.space[parent_cursor].right_child = 0;
}
}
fn successor(&self, mut cursor: usize) -> (usize, usize, bool) {
let mut parent_cursor = cursor;
cursor = self.space[cursor].right_child;
let mut left_or_right = false;
while self.space[cursor].left_child != 0 {
parent_cursor = cursor;
cursor = self.space[cursor].left_child;
left_or_right = true;
}
return (cursor, parent_cursor, left_or_right);
}
fn predecessor(&self, mut cursor: usize) -> (usize, usize, bool) {
let mut parent_cursor = cursor;
cursor = self.space[cursor].left_child;
let mut left_or_right = true;
while self.space[cursor].right_child != 0 {
parent_cursor = cursor;
cursor = self.space[cursor].right_child;
left_or_right = false;
}
return (cursor, parent_cursor, left_or_right);
}
fn decrease_level(&mut self, cursor: usize) -> usize {
let should_be = min(
self.space[self.space[cursor].left_child].level,
self.space[self.space[cursor].right_child].level,
) + 1;
if should_be < self.space[cursor].level {
self.space[cursor].level = should_be;
if should_be < self.space[self.space[cursor].right_child].level {
self.space[self.space[cursor].right_child].level = should_be;
}
}
return cursor;
}
fn inside_delete(
&mut self,
key: T1,
mut cursor: usize,
parent_cursor: usize,
left_or_right: bool,
) {
if cursor == 0 {
if parent_cursor == 0 {
if self.space[cursor].left_child != 0 {
self.inside_delete(key, self.space[cursor].left_child, cursor, true);
}
}
return;
} else {
if let Some((node_key, _)) = &self.space[cursor].value {
if key < *node_key {
self.inside_delete(key, self.space[cursor].left_child, cursor, true);
} else if key > *node_key {
self.inside_delete(key, self.space[cursor].right_child, cursor, false);
} else {
if self.space[cursor].left_child == 0 && self.space[cursor].right_child == 0 {
self.move_list_for_delete(cursor, parent_cursor, left_or_right);
return;
} else if self.space[cursor].left_child == 0 {
let (l, _parent_l, _left_or_right) = self.successor(cursor);
if let Some((l_key, l_x)) = self.space[l].value {
self.inside_delete(
l_key,
self.space[cursor].right_child,
cursor,
false,
);
self.space[cursor].value = Some((l_key, l_x));
}
} else {
let (l, _parent_l, _left_or_right) = self.predecessor(cursor);
if let Some((l_key, l_x)) = self.space[l].value {
self.inside_delete(l_key, self.space[cursor].left_child, cursor, true);
self.space[cursor].value = Some((l_key, l_x));
}
}
}
}
}
cursor = self.decrease_level(cursor);
cursor = self.skew(cursor, parent_cursor, left_or_right);
self.skew(self.space[cursor].right_child, cursor, false);
if self.space[cursor].right_child != 0 {
self.skew(
self.space[self.space[cursor].right_child].right_child,
self.space[cursor].right_child,
false,
);
}
cursor = self.split(cursor, parent_cursor, left_or_right);
self.split(self.space[cursor].right_child, cursor, false);
}
pub fn delete(&mut self, key: T1) {
self.inside_delete(key, 0, 0, true);
}
pub fn get(&self, key: T1) -> Option<T2> {
if self.space[0].left_child == 0 {
return None;
}
let mut cursor = self.space[0].left_child;
loop {
if let Some((node_key, node_x)) = self.space[cursor].value {
if key < node_key {
if self.space[cursor].left_child == 0 {
return None;
} else {
cursor = self.space[cursor].left_child;
continue;
}
} else if key > node_key {
if self.space[cursor].right_child == 0 {
return None;
} else {
cursor = self.space[cursor].right_child;
continue;
}
} else {
return Some(node_x);
}
}
}
}
pub fn new() -> Self {
let mut space = [Node::<T1, T2>::new(); SIZE];
for i in 1..space.len() - 1 {
space[i].left_child = i + 1;
}
Self {
size: 0,
space: space,
available: 1,
}
}
}
fn main() {
let stdin = std::io::read_to_string(std::io::stdin()).unwrap();
let stdin: Vec<&str> = stdin.split_whitespace().collect();
let mut aa_tree = AATree::<&str, u32>::new();
let mut i = 1;
loop {
if i >= stdin.len() {
break;
}
let q = stdin[i].parse::<u32>().unwrap();
if q == 0 {
let key = stdin[i + 1];
let x = stdin[i + 2].parse::<u32>().unwrap();
aa_tree.insert(key, x);
i += 3;
} else if q == 1 {
let key = stdin[i + 1];
if let Some(x) = aa_tree.get(key) {
println!("{}", x);
} else {
println!("0");
}
i += 2;
} else if q == 2 {
let key = stdin[i + 1];
aa_tree.delete(key);
i += 2;
}
}
}