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

広告

posted by fanblog

2017年11月28日

《その155》 「 2分探索関数 」 の改良


 「 2分探索関数 」 の改良

 新版明解C++中級編 p.124 にある改良版2分探索関数 binsearchx のコードは、少し誤植があり、そのままではうまく動作しないので、修正した binsearchx関数と、それを利用するプログラムを以下に書きました。

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

void* binsearchx(
const void* key, // キー値へのポインタ
const void* base, // 配列へのポインタ
size_t nmemb, // 要素の個数
size_t size, // 要素1つ分の大きさ
int(*compar)(const void*, const void*)) {
if (nmemb > 0) {
// 検索対象の配列の先頭要素へのポインタ
// の値を const char*型の x に代入

const char* x
= reinterpret_cast<const char*>(base);

// 最初の検索左端は base[0]
size_t pl = 0;

// 最初の検索右端は base[nmemb - 1]
size_t pr = nmemb - 1;

// 比較関数は、&x[pc * size]
// すなわち &base[pc] の指す base[pc]
// の値とkeyの指す値とを比較すること
// になります。

size_t pc;

while (1) {
// pc の値を決めます。
pc = (pl + pr) / 2;

// ポインタ key と
// ポインタ &x[pc * size] を
// 比較関数に渡して、
// 調査結果を int型の comp
// で受け取ります。
// ポインタ &x[pc * size] は
// ポインタ &base[pc] と同じ
// アドレスなので、
// 比較関数内で keyの指す値
// と base[pc] の値とを比較
// でます。

int comp = compar(
key,
reinterpret_cast<const void*>
(&x[pc * size])
);

// comp == 0 は検索成功。
if (comp == 0) {

// base[pc] が keyの指す値と一致
// することが分かりましたが、
// もっと先頭寄りに同じ値が
// あるかも知れないので、
// 添字の値をデクリメントし
// ながら調べてみます。

for (; pc > pl; pc--) {
if (compar(
key,
reinterpret_cast<const void*>
(&x[(pc - 1) * size])
)
)
// compar関数から、0 以外
// の値が返ってきたの
// で、base[pc]より前
// にはもう同じ値は
// ないことが判明。
// よって、この時点で
// break;

break;
}

// ポインタ &x[pc * size]すなわち
// base[pc] を指すポインタ
// を void型にキャストして
// 返却します。

return const_cast<void*>(
reinterpret_cast<const void*>
(&x[pc * size])
);
}

// 探索範囲の先頭と末尾が一致したら、
// 見つからなかったということなの
// で break; し、
// 関数の末尾に飛んで、
// return NULL;

else if (pl == pr)
break;

// comp > 0 ということは、
// keyの指す値 > base[pc]
// よって、探索範囲を後半に
// 絞り込みます。

else if (comp > 0)
pl = pc + 1;

// この行まで来たということは、
// comp < 0
// つまり、
// keyの指す値 < base[pc]
// よって、探索範囲を前半に絞り
// 込みます。

else if (pc > 0)
pr = pc - 1;

// この行まで来たということは、
// comp < 0 && pc == 0
// これ以上、探索範囲を前方にで
// きないので、
// break; し、
// 関数の末尾まで進んで、
// return NULL;

else
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", "ab", "bab", "bab",
"bab", "bab", "bbba" };
const char* p[]
= { "aaa", "ab", "bab", "bab",
"bab", "bab", "bbba" };
int num[]
= { 11, 25, 25, 25, 25, 25,
25, 57, 65, 77, 80 };

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

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

void* f = binsearchx(
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 < 7; i++)
std::cout << p[i] << ' ';
std::cout << '\n';

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

f = binsearchx(
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 < 11; i++)
std::cout << num[i] << ' ';
std::cout << '\n';

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

f = binsearchx(
&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_001802.png


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

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

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

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





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

お名前:

メールアドレス:


ホームページアドレス:

コメント:

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

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

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

 たまに、クリック お願いします 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日以上新しい記事の更新がないブログに表示されております。