#列表 #光标 #节点 #循环 #光标位置 #常数时间 #拥有

cyclic_list

一个具有拥有节点的双链表,实现为循环列表

1 个不稳定版本

0.1.0 2021年8月29日

#965 in 算法

MIT 许可证

135KB
2K SLoC

双链表

这个包提供了一个具有拥有节点的双链表,实现为循环列表。

用法

首先,在您的 Cargo.toml 中添加依赖项

[dependencies]
cyclic_list = "0.1"

然后在您的项目中使用它。

示例

use cyclic_list::List;
use std::iter::FromIterator;

let mut list = List::from_iter([1, 2, 3, 4]);

let mut cursor = list.cursor_start_mut();

cursor.insert(0); // insert 0 at the beginning of the list
assert_eq!(cursor.current(), Some(&1));
assert_eq!(cursor.view(), &List::from_iter([0, 1, 2, 3, 4]));

cursor.seek_to(3); // move the cursor to position 3, and removes it.
assert_eq!(cursor.remove(), Some(3));
assert_eq!(cursor.view(), &List::from_iter([0, 1, 2, 4]));

cursor.push_front(5); // pushing front to the list is also allowed
assert_eq!(cursor.view(), &List::from_iter([5, 0, 1, 2, 4]));

简介

List 允许在常数时间内插入、移除任何给定位置上的元素。作为妥协,访问或修改任何位置上的元素需要 O(n) 时间。

内存布局

内存布局如下所示

         ┌─────────────────────────────────────────────────────────────────────┐
         ↓                                                     (Ghost) Node N  │
   ╔═══════════╗           ╔═══════════╗                        ┌───────────┐  │
   ║   next    ║ ────────→ ║   next    ║ ────────→ ┄┄ ────────→ │   next    │ ─┘
   ╟───────────╢           ╟───────────╢     Node 2, 3, ...     ├───────────┤
┌─ ║   prev    ║ ←──────── ║   prev    ║ ←──────── ┄┄ ←──────── │   prev    │
│  ╟───────────╢           ╟───────────╢                        ├───────────┤
│  ║ payload T ║           ║ payload T ║                        ┊No payload ┊
│  ╚═══════════╝           ╚═══════════╝                        └╌╌╌╌╌╌╌╌╌╌╌┘
│      Node 0                  Node 1                               ↑   ↑
└───────────────────────────────────────────────────────────────────┘   │
╔═══════════╗                                                           │
║   ghost   ║ ──────────────────────────────────────────────────────────┘
╟───────────╢
║   (len)   ║
╚═══════════╝
    List

迭代

通过 IterIterMut 迭代器遍历列表。这些是两端迭代器,像数组一样遍历列表(融合且非循环)。IterMut 提供了元素的可变性(但不包括列表的链接结构)。

示例

use cyclic_list::List;
use std::iter::FromIterator;

let mut list = List::from_iter([1, 2, 3]);
let mut iter = list.iter();
assert_eq!(iter.next(), Some(&1));
assert_eq!(iter.next(), Some(&2));
assert_eq!(iter.next(), Some(&3));
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None); // Fused and non-cyclic

list.iter_mut().for_each(|item| *item *= 2);
assert_eq!(Vec::from_iter(list), vec![2, 4, 6]);

游标视图

除了迭代之外,游标 CursorCursorMut 提供了更灵活地查看列表的方法。

正如其名所示,它们像游标一样可以向前或向后移动列表。在一个长度为 n 的列表中,游标有 n + 1 个有效位置,通过 0, 1, ..., n 进行索引,其中 n 是列表的幽灵节点。

游标也可以用作迭代器,但它们是循环的且不融合。

警告:尽管游标迭代器有 rev 方法,但它们 作为两端迭代器行为。相反,它们创建一个新的迭代器,该迭代器反转游标的运动方向。

示例

use cyclic_list::List;
use std::iter::FromIterator;

let list = List::from_iter([1, 2, 3]);
// Create a cursor iterator
let mut cursor_iter = list.cursor_start().into_iter();
assert_eq!(cursor_iter.next(), Some(&1));
assert_eq!(cursor_iter.next(), Some(&2));
assert_eq!(cursor_iter.next(), Some(&3));
assert_eq!(cursor_iter.next(), None);
assert_eq!(cursor_iter.next(), Some(&1)); // Not fused and cyclic

// Create a cursor back iterator which reverses the moving direction
// of the cursor
let mut cursor_iter = cursor_iter.rev();
assert_eq!(cursor_iter.next(), Some(&1)); // Iterate in reversed direction
assert_eq!(cursor_iter.next(), None); // Pass through the ghost node boundary
assert_eq!(cursor_iter.next(), Some(&3)); // Reaches the ghost node

游标变异

CursorMut 提供了许多在任意位置变异列表的有用方式。

  • insert:在游标处插入新项目;
  • remove:移除游标处的项目;
  • backspace:移除游标前的项目;
  • split:从游标位置分割列表到末尾;
  • splice:在光标位置之前插入另一个列表;

示例

use cyclic_list::List;
use std::iter::FromIterator;

let mut list = List::from_iter([1, 2, 3, 4]);

let mut cursor = list.cursor_start_mut();

cursor.insert(5); // becomes [5, 1, 2, 3, 4], points to 1
assert_eq!(cursor.current(), Some(&1));

assert!(cursor.seek_forward(2).is_ok());
assert_eq!(cursor.remove(), Some(3)); // becomes [5, 1, 2, 4], points to 4
assert_eq!(cursor.current(), Some(&4));

assert_eq!(cursor.backspace(), Some(2)); // becomes [5, 1, 4], points to 4
assert_eq!(cursor.current(), Some(&4));

assert_eq!(Vec::from_iter(list), vec![5, 1, 4]);

开发计划

以下是本项目的开发计划。

  • 基本支持:push、pop、insert、remove;
  • 光标支持:移动、搜索、insert、remove、split、splice;
  • 迭代器支持:从/到迭代器、不可变/可变迭代器、双端迭代器、类似光标的迭代器;
  • 容器操作
    • rotate
    • reverse
  • 算法支持
    • drain
    • find
    • sort
    • 子范围视图
  • 高级主题
    • 动态大小类型
    • 并发支持

无运行时依赖

特性