pub struct PQ<T> {
data: Vec<T>,
need_swap: fn(&T, &T) -> bool,
}
impl<T: PartialOrd> PQ<T> {
pub fn new_min_pq() -> Self {
PQ {
data: Vec::new(),
need_swap: |a, b| a > b,
}
}
pub fn new_max_pq() -> Self {
PQ {
data: Vec::new(),
need_swap: |a, b| a < b,
}
}
pub fn push(&mut self, val: T) {
let pos = self.data.len();
self.data.push(val);
self.swim(pos);
}
fn get_parent_pos(pos: usize) -> Option<usize> {
if 0 == pos {
None
} else {
let parent = (pos + 1) / 2 - 1;
Some(parent)
}
}
fn get_child_pos(pos: usize, len: usize) -> Option<(usize, Option<usize>)> {
let left = (pos + 1) * 2 - 1;
if left >= len {
None
} else if left == len - 1 {
Some((left, None))
} else {
Some((left, Some(left + 1)))
}
}
fn sink(&mut self, pos: usize) {
let mut i = pos;
let len = self.data.len();
let data = &mut self.data;
while let Some(child_pos) = Self::get_child_pos(i, len) {
let (l, r) = child_pos;
let mut target = i;
if (self.need_swap)(&data[target], &data[l]) {
target = l;
}
if let Some(r) = r {
if (self.need_swap)(&data[target], &data[r]) {
target = r;
}
}
if target != i {
data.swap(target, i);
i = target;
} else {
break;
}
}
}
fn swim(&mut self, pos: usize) {
let mut i = pos;
while let Some(p) = Self::get_parent_pos(i) {
if (self.need_swap)(&self.data[p], &self.data[i]) {
self.data.swap(p, i);
i = p;
} else {
break;
}
}
}
pub fn peek(&self) -> Option<&T> {
self.data.get(0)
}
pub fn size(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.get(0).is_none()
}
pub fn pop(&mut self) -> Option<T> {
if self.data.is_empty() {
None
} else {
let ans = Some(self.data.swap_remove(0));
self.sink(0);
ans
}
}
}
pub struct IndexPQ<T> {
keys: Vec<Option<T>>,
data: Vec<usize>,
qp: Vec<usize>,
need_swap: fn(&T, &T) -> bool,
}
impl<T: PartialOrd> IndexPQ<T> {
pub fn new_min_pq(count: usize) -> Self {
let mut keys = Vec::with_capacity(count);
let qp = vec![0; count];
for _ in 0..count {
keys.push(None);
}
IndexPQ {
keys,
qp,
data: Vec::new(),
need_swap: |a, b| a > b,
}
}
pub fn new_max_pq(count: usize) -> Self {
let mut keys = Vec::with_capacity(count);
let qp = vec![0; count];
for _ in 0..count {
keys.push(None);
}
IndexPQ {
keys,
data: Vec::new(),
qp,
need_swap: |a, b| a < b,
}
}
pub fn push(&mut self, k: usize, val: T) {
assert!(self.keys.len() > k);
assert!(self.keys[k].is_none(), "修改数据请用change()");
self.keys[k] = Some(val);
self.data.push(k);
let pos = self.data.len() - 1;
self.qp[k] = pos;
self.swim(pos);
}
fn get_parent_pos(pos: usize) -> Option<usize> {
if 0 == pos {
None
} else {
let parent = (pos + 1) / 2 - 1;
Some(parent)
}
}
fn get_child_pos(pos: usize, len: usize) -> Option<(usize, Option<usize>)> {
let left = (pos + 1) * 2 - 1;
if left >= len {
None
} else if left == len - 1 {
Some((left, None))
} else {
Some((left, Some(left + 1)))
}
}
fn sink(&mut self, pos: usize) {
let mut i = pos;
let len = self.data.len();
while let Some(child_pos) = Self::get_child_pos(i, len) {
let (l, r) = child_pos;
let mut target = i;
let data = &self.data;
if (self.need_swap)(self.get_key(data[target]), self.get_key(data[l])) {
target = l;
}
if let Some(r) = r {
if (self.need_swap)(self.get_key(data[target]), self.get_key(data[r])) {
target = r;
}
}
if target != i {
self.swap(target, i);
i = target;
} else {
break;
}
}
}
fn get_key(&self, k: usize) -> &T {
self.keys[k].as_ref().unwrap()
}
fn swim(&mut self, pos: usize) {
let mut i = pos;
while let Some(p) = Self::get_parent_pos(i) {
if (self.need_swap)(self.get_key(self.data[p]), self.get_key(self.data[i])) {
self.swap(p, i);
i = p;
} else {
break;
}
}
}
fn swap(&mut self, a: usize, b: usize) {
self.data.swap(a, b);
self.qp.swap(self.data[b], self.data[a])
}
pub fn peek(&self) -> Option<(usize, &T)> {
self.data.first().map(|i| (*i, self.get_key(*i)))
}
pub fn pop(&mut self) -> Option<(usize, T)> {
if self.data.is_empty() {
None
} else {
self.swap(0, self.data.len() - 1);
let k = self.data.pop().unwrap();
let key = self.keys[k].take().unwrap();
self.sink(0);
Some((k, key))
}
}
pub fn change(&mut self, k: usize, key: T) {
self.keys[k] = Some(key);
self.swim(self.qp[k]);
self.sink(self.qp[k]);
}
pub fn contains(&self, k: usize) -> bool {
self.keys[k].is_some()
}
}
#[cfg(test)]
mod test {
use crate::priority_queue::IndexPQ;
use super::PQ;
#[test]
fn test_min_pq() {
let mut pq = PQ::new_min_pq();
pq.push(2);
pq.push(1);
pq.push(5);
pq.push(3);
pq.push(4);
pq.push(6);
assert_eq!(pq.peek(), Some(&1));
assert_eq!(pq.pop(), Some(1));
assert_eq!(pq.pop(), Some(2));
assert_eq!(pq.pop(), Some(3));
assert_eq!(pq.pop(), Some(4));
assert_eq!(pq.pop(), Some(5));
assert_eq!(pq.pop(), Some(6));
assert_eq!(pq.pop(), None);
}
#[test]
fn test_max_pq() {
let mut pq = PQ::new_max_pq();
pq.push(2);
pq.push(1);
pq.push(5);
pq.push(3);
pq.push(4);
pq.push(6);
assert_eq!(pq.peek(), Some(&6));
assert_eq!(pq.pop(), Some(6));
assert_eq!(pq.pop(), Some(5));
assert_eq!(pq.pop(), Some(4));
assert_eq!(pq.peek(), Some(&3));
assert_eq!(pq.pop(), Some(3));
assert_eq!(pq.pop(), Some(2));
assert_eq!(pq.pop(), Some(1));
assert_eq!(pq.pop(), None);
assert_eq!(pq.pop(), None);
}
#[test]
fn test_min_index_pq() {
let mut pq = IndexPQ::new_min_pq(6);
pq.push(0, 2);
pq.push(1, 1);
pq.push(2, 5);
pq.push(3, 3);
pq.push(4, 4);
pq.push(5, 6);
assert_eq!(pq.peek(), Some((1, &1)));
assert_eq!(pq.pop(), Some((1, 1)));
pq.change(0, 7);
assert_eq!(pq.pop(), Some((3, 3)));
assert_eq!(pq.pop(), Some((4, 4)));
assert_eq!(pq.pop(), Some((2, 5)));
assert_eq!(pq.pop(), Some((5, 6)));
assert_eq!(pq.pop(), Some((0, 7)));
assert_eq!(pq.pop(), None);
}
#[test]
fn test_max_index_pq() {
let mut pq = IndexPQ::new_max_pq(6);
pq.push(0, 2);
pq.push(1, 1);
pq.push(2, 5);
pq.push(3, 3);
pq.push(4, 4);
pq.push(5, 6);
assert_eq!(pq.peek(), Some((5, &6)));
assert_eq!(pq.pop(), Some((5, 6)));
pq.change(4, 7);
assert_eq!(pq.pop(), Some((4, 7)));
assert_eq!(pq.pop(), Some((2, 5)));
assert_eq!(pq.peek(), Some((3, &3)));
assert_eq!(pq.pop(), Some((3, 3)));
assert_eq!(pq.pop(), Some((0, 2)));
assert_eq!(pq.pop(), Some((1, 1)));
assert_eq!(pq.pop(), None);
assert_eq!(pq.pop(), None);
}
}