『アルゴリズムとデータ構造』を Rust で実装してみるシリーズ。9章のスタックとキュー。
Rust のグローバルな変数は、制限が多く使いづらい。
スタックはこんな感じ。
const MAX: usize = 100_000; // スタック配列の最大サイズ
static mut ST: [i32; MAX] = [0; MAX]; // スタックを表す配列
static mut TOP: usize = 0; // スタックの先頭を表す添字
// スタックを初期化する
pub fn init() {
unsafe {
TOP = 0; // スタックの添字を初期位置に
}
}
// スタックが空かどうかを判定する
fn is_empty() -> bool {
unsafe {
TOP == 0 // スタックサイズが 0 かどうか
}
}
// スタックが満杯かどうかを判定する
fn is_full() -> bool {
unsafe {
TOP == MAX // スタックサイズが MAX かどうか
}
}
// push
pub fn push(x: i32) {
if is_full() {
println!("error: stack is full.");
return;
}
unsafe {
ST[TOP] = x; // x を格納して
TOP += 1; // TOP を進める
}
}
// pop
pub fn pop() -> i32 {
if is_empty() {
println!("error: stack is empty.");
return -1;
}
unsafe {
TOP -= 1; // TOP をデクリメントして
return ST[TOP]; // TOP の位置にある要素を返す
}
}
キューはこんな感じ。
const MAX: usize = 100_000; // キュー配列の最大サイズ
static mut QU: [i32; MAX] = [0; MAX]; // キューを表す配列
static mut TAIL: usize = 0; // キューの要素区間を表す変数
static mut HEAD: usize = 0; // キューの要素区間を表す変数
// キューを初期化する
pub fn init() {
unsafe {
TAIL = 0;
HEAD = 0;
}
}
// キューが空かどうかを判定する
fn is_empty() -> bool {
unsafe { HEAD == TAIL }
}
// キューが満杯かどうかを判定する
fn is_full() -> bool {
unsafe { HEAD == (TAIL + 1) % MAX }
}
// enqueue
pub fn enqueue(x: i32) {
if is_full() {
println!("error: queue is full.");
return;
}
unsafe {
QU[TAIL] = x;
TAIL += 1;
if TAIL == MAX {
TAIL = 0;
} // リングバッファの終端に来たら 0 に
}
}
// dequeue
pub fn dequeue() -> i32 {
if is_empty() {
println!("error: queue is empty.");
return -1;
}
unsafe {
let res = QU[HEAD];
HEAD += 1;
if HEAD == MAX {
HEAD = 0;
} // リングバッファの終端に来たら 0 に
res
}
}
GitHub のリポジトリはこちら https://github.com/quantized-cube/book_algorithm_solution_rust
コメント