
sentinelと呼ばれる、「番兵」というプログラミングについて、昔聞いた名称だったけど、久しぶりに聞いた単語だったので、改めて深掘りしてみることにした。
今読んでいる技術書に、アルゴリズムの話が書いてあって、そこに書かれていた「番兵」っていう手法は、聞いたことはあったけど、あまりよく理解できていない事に気がついた。
もしかし、自分のコーディングにいい風を吹き込んでくれるんじゃないかと密かに期待しつつ、色々と調べてわかったことを書き残しておきます。
番兵とは?
番兵って、
見張りをする兵士の事です。
プログラミングにおける「番兵(sentinel)」とは、
データ構造やアルゴリズムの中で、
処理を簡略化したり終了条件を明確にするために置かれる特別な値や要素のことです。
なんだかこの説明では、わかりにくいな〜。
基本概念
データの末尾や境界に置く「特別な値」で、ループや探索の終了を知らせるために使う。
目的
・ループの終了条件を簡単にする。
・if文による境界チェックを減らし、コードを簡潔にする。
・エラーを防止する。
なるほど、要するになんとなく便利だということがわかった。
代表的な使い方
以下のコードで番兵を使ったプログラミングが確認できる。
1. 線形探索での番兵
# C言語
int find(int x, int a[], int n) {
a[n] = x; // ← 番兵を末尾に置く
int i = 0;
while (a[i] != x) i++; // 終了条件を簡略化
return (i < n) ? i : -1;
}
通常なら i < n のチェックが必要だが、番兵を置くことで不要に。
2. リンクリストでの番兵ノード
# C言語
struct Node {
int value;
struct Node* next;
};
struct Node sentinel = {0, &sentinel}; // 番兵ノード
リストの先頭や末尾に番兵を置くことで、「nullチェック」を省略できる
3. 入力処理での番兵値
# Python
while True:
num = int(input())
if num == -1: # -1 を番兵にする
break
print(num)
ユーザー入力が特定の値になったら終了する。
4. 配列探索での番兵
# Javascript番兵ナシ
function find(arr, target) {
for (let i = 0; i < arr.length; i++) {
if (arr[i] === target) return i;
}
return -1;
}
console.log(find([1, 3, 5, 7], 5)); // → 2
console.log(find([1, 3, 5, 7], 9)); // → -1
# Javascript番兵アリ
function findWithSentinel(arr, target) {
const n = arr.length;
arr.push(target); // ← 番兵を末尾に追加
let i = 0;
while (arr[i] !== target) i++;
arr.pop(); // 番兵を削除して元に戻す
return i < n ? i : -1;
}
console.log(findWithSentinel([1, 3, 5, 7], 5)); // → 2
console.log(findWithSentinel([1, 3, 5, 7], 9)); // → -1
arr.push(target) が番兵の役割。
while ループの中で i < arr.length のチェックが不要になる。
境界チェックを簡略化できる。
番兵のメリット
番兵という判定用フラグというか、変数を用意することで、境界条件チェックが減り、コードがスッキリする。
そして、ループのバグを減らせるし、無駄な回数を減らすこともできる。
パフォーマンスがわずかに上がる(比較回数が減る場合がある)。
注意点
番兵値が「実際のデータに含まれない」ことを保証する必要がある。
複雑なデータ構造(例えばツリーやグラフ)では、使い方に工夫が必要になる場合がある。
あとがき
個人的に期待していたアルゴリズムというよりは、判定をするための変数や配列を用意するその変数のことが番兵ということですね。
確かに、膨大なループ処理をするときに、メモリに判定パターンを持っておくことで、複雑な判定を回避できる場合がありますからね。
個人的によく使うのは、連想配列のkey値のアリナシで判断するパターンは、手軽に使いやすいのでよく使っていました。
アレを番兵っていう言い方をするんだったんだ・・・
と、気がついた今日のブログでした。
0 件のコメント:
コメントを投稿