アフィリエイト広告を利用しています

広告

posted by fanblog

2017年11月27日

《その153》 2分探索関数のプログラム例


 2 ブン
 2分探索関数のプログラム例

 新版明解C++中級編 p.122 にある汎用2分探索関数 binsearch のコードには、一部に誤植があると思うので、修正した binsearch関数と、それを利用するプログラムを以下に書きます。

 修正箇所は、binsearch関数の赤文字の部分です。
元のコードのままだと、pr が負になった状態で while文が実行される場合があり得ます。

  comp < 0 で pl=0, pr=1 の状況のとき、
  pc = (pl + pr) / 2 より pc = 0 ですから、
元のコードのままでは、次の
  pr = pc - 1
の計算で、pr が負になります。そして、そのまま while文に戻ることになってしまいます。


// ------------------------------------
#include <string>
#include <iostream>

void* binsearch(
const void* key,
const void* base,
size_t nmemb, size_t size,
int(*compar)(const void*, const void*)
) {
if (nmemb > 0) {
const char* x
= reinterpret_cast<const char*>(base);
size_t pl = 0; // 探索範囲先頭の添字
size_t pr = nmemb - 1; // 探索範囲末尾の添字
size_t pc; // 探索範囲中央の添字

while (true) {
pc = (pl + pr) / 2;
int comp
= compar(
key,
reinterpret_cast<const void*>(&x[pc * size])
);
if (comp == 0) // 探索成功
return const_cast<void*>(
reinterpret_cast<const void*>(&x[pc * size])
);
else if (pl == pr) // 探索範囲がなくなった
break;
else if (comp > 0)
pl = pc + 1; // 探索範囲を後半に絞り込む
else if (pc > 0) // comp < 0
pr = pc - 1; // 探索範囲を前半に絞り込む
else // comp < 0 && pc == 0
break;
}
}
return NULL; // 探索失敗
}

int acmp(char* x, char* y) { // 比較関数
return strcmp(x, y);
}
int pcmp(char* x, char** y) { // 比較関数
return strcmp(x, *y);
}
int ncmp(int* x, int* y) { // 比較関数
return *x < *y ? -1 : *x > *y ? 1 : 0;
}
void existence(int n) { std::cout << n << "番目\n"; }
void non_existence() { std::cout << "該当なし\n"; }

int main() {
char a[][5]
= { "aaa", "aab", "abaa", "abb",
"bab", "bab", "bab", "bbb" };
const char* p[]
= { "aaa", "aab", "abaa", "abb",
"bab", "bab", "bab", "bbb" };
int num[]
= { 11, 21, 25, 31, 37, 44, 54,
57, 65, 65, 65, 71, 88, 99 };

// ------------------------------------
std::cout << "◆";
for (int i = 0; i < 8; i++)
std::cout << a[i] << ' ';
std::cout << '\n';

char key1[10];
std::cout << " 探索する文字列 : ";
std::cin >> key1;
std::cout << " " << key1 << " → ";

void* f = binsearch(
key1,
a,
sizeof(a) / sizeof(a[0]),
sizeof(a[0]),
reinterpret_cast<int(*)(
const void*,
const void*
)>(acmp)
);

if (f == 0) non_existence();
else
existence((char(*)[5])f - a + 1);

// ------------------------------------
std::cout << "\n◆";
for (int i = 0; i < 8; i++)
std::cout << p[i] << ' ';
std::cout << '\n';

char key2[10];
std::cout << " 探索する文字列 : ";
std::cin >> key2;
std::cout << " " << key2 << " → ";


f = binsearch(
key2,
p,
sizeof(p) / sizeof(p[0]),
sizeof(p[0]),
reinterpret_cast<int(*)(
const void*,
const void*
)>(pcmp)
);

if (f == 0) non_existence();
else
existence((char**)f - p + 1);

// ------------------------------------
std::cout << "\n◆";
for (int i = 0; i < 14; i++)
std::cout << num[i] << ' ';
std::cout << '\n';

int key;
std::cout << " 探索する整数値 : ";
std::cin >> key;
std::cout << " " << key << " → ";

f = binsearch(
&key,
num,
sizeof(num) / sizeof(num[0]),
sizeof(num[0]),
reinterpret_cast<int(*)(
const void*,
const void*
)>(ncmp)
);

if (f == 0) non_existence();
else
existence((int*)f - num + 1);
}

e03_001602.png
 元のコードのままだと、最後の探索( 10 を探索 )で、プログラムが暴走してしまいます。



新版 明解C 入門編 (明解シリーズ)

新品価格
¥2,916から
(2017/11/10 13:13時点)

新版 明解C 中級編 (明解シリーズ)

新品価格
¥2,916から
(2017/11/10 13:14時点)





この記事へのコメント
コメントを書く

お名前:

メールアドレス:


ホームページアドレス:

コメント:

※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバックURL
https://fanblogs.jp/tb/7011824
※ブログオーナーが承認したトラックバックのみ表示されます。

この記事へのトラックバック

 たまに、クリック お願いします m(_ _)m

 AA にほんブログ村 IT技術ブログ C/C++へ

こうすけ:メール kousuke_cpp@outlook.jp

【1】★★C++ 記事目次★★ ← 利用可能です。
・新版明解C++入門編 / 新版明解C++中級編
・その他 C++ 関連記事

【2】★★こうすけ@C#★★
・C# の初歩的な記事


検索
<< 2018年08月 >>
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
プロフィール
こうすけさんの画像
こうすけ

 たまに、クリック お願いします m(_ _)m

 AA にほんブログ村 IT技術ブログ C/C++へ

こうすけ:メール kousuke_cpp@outlook.jp

【1】★★C++ 記事目次★★ ← 利用可能です。
・新版明解C++入門編 / 新版明解C++中級編
・その他 C++ 関連記事

【2】★★こうすけ@C#★★
・C# の初歩的な記事


×

この広告は30日以上新しい記事の更新がないブログに表示されております。