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

広告

posted by fanblog

2017年11月29日

《その156》 クイックソートを行う汎用関数


 クイックソートを行う汎用関数

 次のプログラムは、新版明解C++中級編 p.126 にあるクイックソートを行う汎用関数 quicksort のコードを少しだけ変更して、それに、動作確認用のプログラムを付け足したものです。

// ------------------------------------
#include <random>
#include <string>
#include <iostream>
using namespace std;

// x, yの指すnバイトの領域を交換する関数。
void memswap(void* x, void* y, size_t n)
{
unsigned char* a
= reinterpret_cast<unsigned char*>(x);
unsigned char* b
= reinterpret_cast<unsigned char*>(y);

for (; n--; a++, b++) {
unsigned char c = *a;
*a = *b;
*b = c;
}
}

void quicksort(
void* base, // 配列へのポインタ
size_t nmemb, // 要素の個数
size_t size, // 要素1つ分の大きさ

// 比較関数用の仮引数
int(*compar)(const void*, const void*))
{
if (nmemb > 1) {
// 配列 base の先頭要素へのポインタを
// キャストして、char* v に代入

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

size_t pl = 0; // 検索範囲左端
size_t pr = nmemb - 1; // 検索範囲右端
size_t pt = (pl + pr) / 2; // 基準値の位置

do {
// &v[pt * size] は基準値への
// ポインタ &base[pt] に対応します。

while (
compar(
reinterpret_cast<const void*>(&v[pl * size]),
&v[pt * size]
) < 0
) {
// 検索範囲左端からチェックしていき、
// 基準値のほうが大きければ、
// 検索範囲左端の位置 pl を
// インクリメント。
// 基準値以上の値を見つけたら、pl
// はその位置で停止。

pl++;
}

while (
compar(
reinterpret_cast<const void*>(&v[pr * size]),
&v[pt * size]
) > 0
) {
// 検索範囲右端からチェックしていき、
// 基準値のほうが小さければ、
// 検索範囲右端の位置 pr を
// デクリメント。
// 基準値以下の値を見つけたら、pr
// はその位置で停止。

pr--;
}

if (pl <= pr) {
// 検索範囲の左端と右端が逆転していないとき。
pt = (pl == pt) ? pr : (pr == pt) ? pl : pt;
// 検索範囲の左端が基準値の位置に達している
// 場合は、基準値の位置を現時点での
// 右端の位置に更新。
// 検索範囲の右端が基準値の位置に達している
// 場合は、基準値の位置を現時点での
// 左端の位置に更新。
// それ以外なら、基準値の位置は更新しません。
// ※以上の操作は、関数 memswapが値を交換し
// ても基準値の値が変化しないように
// するため。

// 配列要素 base[pl], base[pr] の値を交換

memswap(
const_cast<void*>
(reinterpret_cast<const void*>(&v[pl * size])),
const_cast<void*>
(reinterpret_cast<const void*>(&v[pr * size])),
size
);

pl++;
if (pr == 0) // 符号無し整数 0 からのデクリメントを避ける。
goto LABEL;
pr--;
}
} while (pl <= pr);

if (0 < pr)
// 左側 0、要素数 pr + 1 として、quicksort関数を再帰呼出し。
quicksort(
const_cast<void*>
(reinterpret_cast<const void*>(&v[0])),
pr + 1,
size,
compar
);
LABEL:
if (pl < nmemb - 1)
// 左側 pl、要素数 nmemb - pl として、quicksort関数を再帰呼出し。
quicksort(
const_cast<void*>
(reinterpret_cast<const void*>(&v[pl * size])),
nmemb - pl,
size,
compar
);
}
}


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;
}


int main() {
char a[][5]
= { "cba", "cabd", "abc", "bcd",
"cab", "b", "a", "cba", "aa" };
const char* p[]
= { "cba", "cabd", "abc", "bcd",
"cab", "b", "a", "cba", "aa" };

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

quicksort(a, sizeof(a) / sizeof(a[0]), sizeof(a[0]),
reinterpret_cast<int(*)(const void*, const void*)>(acmp));

cout << "→ ";
for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
std::cout << a[i] << " ";
std::cout << "\n\n";


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

quicksort(p, sizeof(p) / sizeof(p[0]), sizeof(p[0]),
reinterpret_cast<int(*)(const void*, const void*)>(pcmp));

cout << "→ ";
for (int i = 0; i < sizeof(p) / sizeof(p[0]); i++)
std::cout << p[i] << " ";
std::cout << "\n\n";


// ------------------------------------
random_device rd;

int num[20];
cout << "\n◆ ";
for (int i = 0; i < 20; i++) {
num[i] = rd() % 90 + 10;
cout << num[i] << ' ';
}
cout << '\n';

quicksort(num, sizeof(num) / sizeof(num[0]), sizeof(num[0]),
reinterpret_cast<int(*)(const void*, const void*)>(ncmp));

cout << "→ ";
for (int i = 0; i < sizeof(num) / sizeof(num[0]); i++)
std::cout << num[i] << ' ';
std::cout << '\n';
}


e03_001902.png


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

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

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

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





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

お名前:

メールアドレス:


ホームページアドレス:

コメント:

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

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

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

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