static S_16 FAR PASCAL
SearchItemInPage(IDX_PAGE FAR *lpIdxPage, IDX_KEYS FAR *lpKey, U_32 u32KeyType)
{
S_16 s16Low;
S_16 s16High;
S_16 s16Mid;
/*
* ディスクアクセスに比べれば無視できるレベルだが、
* 一応高速化のためにバイナリサーチを使用する。
*
* キーとマッチしたら、マッチしたキーの添え字を、
* マッチしなかったら、一つ小さいキーの添え字を返す。
* 下のAのようなページがあって、キー0をサーチしたら、
* DummyITEMの添え字が返される。
* +-------+-------+-------+
* A | Dummy | 1 | 2 |
* +-------+-------+-------+
* / | \
* / NIL \
* +-------+-------+-------+ +-------+-------+-------+
* B | Dummy | -1 | 0 | C | Dummy | 4 | 5 |
* +-------+-------+-------+ +-------+-------+-------+
* そしてそのDummyITEMは、1より小さい値の集まりであるBページに
* アクセスするために使用される。
*
* また、Aページでキー3をサーチすると、2のITEMの添え字が返る。
* この関数を呼び出した親の関数は、その添え字を
* 2より大きな値の集まりであるCページにアクセスするために使用する。
*
* このルーチンはコード部よりコメントの方が長い。許してください。
*/
s16Low = 1;
s16High = lpIdxPage->s16ItemUsed + (S_16)1;
while (s16Low < s16High) {
s16Mid = (s16Low + s16High) / (S_16)2;
if (IsamKeyComp(&lpIdxPage->item[s16Mid].keys,
lpKey, u32KeyType) <= 0) {
s16Low = s16Mid + (S_16)1;
} else {
s16High = s16Mid;
}
}
return --s16High;
}
else {
/*
* このページ内にあったが、
* しかしそいつは子を持っていて、
* サクサク削除するわけにはいかない。
* その前に子供達の世話が必要である
*
* +-----+-----+
* A| 7 | 8 |
* +-----+-----+
* / \
* +-----+-----+ +-----+-----+
* B| 3 | 4 | D| 9 | |
* +-----+-----+ +-----+-----+
* \
* +-----+-----+
* C| 5 | 6 |
* +-----+-----+
*
* 上のようなTreeで7を削除しようとした場合、
* この状態になる。
* その場合、下のようにする。
*
* +-----+-----+
* A| 6 | 8 |
* +-----+-----+
* / \
* +-----+-----+ +-----+-----+
* B| 3 | 4 | D| 9 | |
* +-----+-----+ +-----+-----+
* \
* +-----+-----+
* C| 5 | |
* +-----+-----+
*
* この動きを置き換えといい、
* これを行っているのがReplaceItem()である。
*/
nResult = ReplaceItem(lpFld, s32TruthPtr, lpfUnderFlow,
s32PagePtr, s16High, lps16StsCode);
if (*lpfUnderFlow != FALSE) {
/*
* 次のようなTreeを考えてみよう。(次数2)
*
* +----+----+----+----+
* A| 20 | 30 | 40 | |
* +----+----+----+----+
* / \
* +----+----+--+--+ +----+----+--+--+
* B| 25 | 27 | | | C| 34 | 36 | | |
* +----+----+--+--+ +----+----+--+--+
*
* 上のようなTreeで27を削除しようとした場合
* 下のようになる。
*
* +----+----+----+----+
* A| 20 | 30 | 40 | |
* +----+----+----+----+
* / \
* +----+----+--+--+ +----+----+--+--+
* B| 25 | | | | C| 34 | 36 | | |
* +----+----+--+--+ +----+----+--+--+
*
* ここで問題が発生する。BTreeの基本特性で
* 次数2(1ページの項目数は2*2=4)のBTreeは
* 1ページ内の項目数は2より小さくならない
* したがって、ページBのITEM数が明らかに不
* 足している。この状態をアンダーフローと
* いう。
* Bが不足しているからといって単純にCページ
* から34を持ってくるわけにもいかない。それ
* は「30より左の子ページにあるITEMはすべて
* 30より小さくなければならない」という規則
* に反し、またCのページはアンダーフローを
* 再び引き起こす。
* この場合は30をAからBに引きずり下ろし、
* BとCを併合する。するとTreeは下のように
* なる。
* これを行っているのがUnderFlow()である。
*
* +----+----+----+----+
* A| 20 | 40 | | |
* +----+----+----+----+
* /
* +----+----+----+----+
* B| 25 | 30 | 34 | 36 |
* +----+----+----+----+
*/
nResult = UnderFlow(lpFld, s32PagePtr,
lpfUnderFlow, s32TruthPtr,
s16High - (S_16)1, lps16StsCode);
ふう。(^^;コードが解決する問題が本質的に複雑な場合、こういったコメントが力を発揮します。
| コメントへ戻る | _ | Top of Site |