
解説クラスCopyClear(36)
解説クラスCopyClear(36)
2025年2月27初稿(初講)
この解説は、膨大なクラス「class CopyClear」の定義を
記載したファイル「CopyClear.h」の順番に従い解説して
行く為に今回は、「private:属性」の関数の説明を行う
事にします!今回は「sort_key()」関数からソート系の
説明します!
この解説文章は、
解説『解説クラスCopyClear(35)』の続きです
(4-15-116)関数「void sort_key(TypeSort* pl,TypeSort* pr){・・・}」
/************************************************************************/
/***** QUIC-SORT:キー付き昇順ソート *****/
/***** ※注1:データを交換するとき、TypeSort型=32bitsを利用して *****/
/***** int型=32bitsと見なして処理しています。 *****/
/************************************************************************/
void CopyClear::sort_key(
CopyClear::TypeSort *pl, // データの左側Ptr
CopyClear::TypeSort *pr // データの右側Ptr
){
TypeSort *pi; // 内部Ptr
TypeSort *pj; // 内部Ptr
short key; // 中央の値
int w; // 交換用の場所
pi = pl; // 左側をSet
pj = pr; // 右側をSet
key = ( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeSort) ) )->key; // セット
do{ // 以下繰り返し
while( pi->key < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < pj->key ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *(int*)pi; // 左右を
*pi = *pj; // 交換
*(int*)pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_key( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_key( pi, pr ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_key();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「key」は、キー付きを意味します!
この関数は、キー付きのデータ配列を昇順≪小さい方から
大きい方へ整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_key();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_key()」の【仮引数】
void CopyClear::sort_key(
CopyClear::TypeSort *pl, // データの左側Ptr
CopyClear::TypeSort *pr // データの右側Ptr
){
「TypeSort* pl,」は、データ配列左端「l=left省略」
「TypeSort* pr」は、データ配列右端「r=right省略」
ここで使用する専用の型「TypeSort」≪
解説『解説クラスCopyClear(1)』の「(3)
クラス内ローカル構造体定義」で解説≫
(D)関数「sort_key()」の【アルゴリズム】
){
TypeSort *pi; // 内部Ptr
TypeSort *pj; // 内部Ptr
short key; // 中央の値
int w; // 交換用の場所
pi = pl; // 左側をSet
pj = pr; // 右側をSet
key = ( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeSort) ) )->key; // セット
do{ // 以下繰り返し
while( pi->key < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < pj->key ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *(int*)pi; // 左右を
*pi = *pj; // 交換
*(int*)pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_key( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_key( pi, pr ); // この間をソート
} //
}
(D-1)ローカル変数
){
TypeSort *pi; // 内部Ptr
TypeSort *pj; // 内部Ptr
short key; // 中央の値
int w; // 交換用の場所
「TypeSort* pi;」は、内部ポインタ(左側用)
「TypeSort* pj;」は、内部ポインタ(右側用)
「short key;」は、中央の値(キー比較用)
「int w;」は、データ交換用の場所
(D―2)アルゴリズムコード
pi = pl; // 左側をSet
pj = pr; // 右側をSet
key = ( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeSort) ) )->key; // セット
do{ // 以下繰り返し
while( pi->key < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < pj->key ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *(int*)pi; // 左右を
*pi = *pj; // 交換
*(int*)pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_key( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_key( pi, pr ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=(pi+((int)pj-(int)pi)/(2*sizeof(TypeSort)))
->key;」は、左右の中央の場所(ポインタの中央)の
キー値「->key」を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(pi->key<key){pi++;}」は、while構文で
ループ条件「pi->key<key」は、「左側のキーの値が、
比較用の値未満」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、次の内側ループ
「while(key<pj->key){pj--;}」は、「右」側のキーの
値が、比較用の値越え」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*(int*)pi;*pi=*pj;*(int*)pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*(int)pi;*pi=*pj;*(int*)pj=w;pi++;pj--;}」で先ず
「w=*(int)pi;*pi=*pj;*(int*)pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
★備考★「w=*(int*)pi;」とか「*(int*)pj=w;」で
キャスト「型変換」として「(int*)」とローカル変数
「int w;」と「TypeSort型」と「int型」が4バイトに成る
事を確認した処理系で使用して居ます!この前提が崩れた
CPU&コンパイラシステムの場合は、書き換える必要が
有る事に留意!
そして「if(pl<pj){sort_key(pl,pj);}」で再帰呼び出しを
自分自身「sort_key()」関数をサブルーチン関数として
条件「pl<pj」=「元々の左側が内部の右側と左右関係が保
たれて居る」なら、再帰呼び出し「sort_key(pl,pj);」を
行う事で数学の「帰納的定義法」と考えて再帰呼び出しを
行った部分「plからpjのポインタの示す左右範囲」が昇順に
ソート済みと見なして処理する方法です!★備考★これが
再帰呼び出しを行う事で実現する「クイックソート」と呼ば
れる通常のデータでは最速と言われているアルゴリズムです
同じ様に「if(pi<pr){sort_key(pi,pr);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順に
ソート済みと見なして処理します!★備考★これが、
再帰呼び出しを行う事で実現する「クイックソート」と呼ば
れる通常のデータでは最速と言われているアルゴリズムです
コレは、多くの画像処理以外のプログラミングで使用されて
居ますので数学的帰納法をアルゴリズムに応用した事を理解
して下さい!C言語的には「再帰呼び出し」との文言で平気
で多用します!
(4-15-117)関数「void sort_key_rev(
TypeSort* pl,TypeSort* pr){・・・}」
/************************************************************************/
/***** QUIC-SORT:キー付き降順ソート *****/
/***** ※注1:データを交換するとき、TypeSort型=32bitsを利用して *****/
/***** int型=32bitsと見なして処理しています。 *****/
/************************************************************************/
void CopyClear::sort_key_rev(
CopyClear::TypeSort *pl, // データの左側Ptr
CopyClear::TypeSort *pr // データの右側Ptr
){
TypeSort *pi; // 内部Ptr
TypeSort *pj; // 内部Ptr
short key; // 中央の値
int w; // 交換用の場所
pi = pl; // 左側をSet
pj = pr; // 右側をSet
key = ( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeSort) ) )->key; // セット
do{ // 以下繰り返し
while( pi->key > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > pj->key ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *(int*)pi; // 左右を
*pi = *pj; // 交換
*(int*)pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_key_rev( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_key_rev( pi, pr ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_key_rev();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「key」は、キー付きを意味します!
「rev」は、英単語「reversal」の省略で「逆転」の意味
です!ソートを逆順≪降順「大きい方から小さい方へ整列」
≫で行います!
この関数は、キー付きのデータ配列を降順にソートする関数
★備考★降順≪大きい方からへ小さい方に整列≫
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_key_rev();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_key_rev()」の【仮引数】
void CopyClear::sort_key_rev(
CopyClear::TypeSort *pl, // データの左側Ptr
CopyClear::TypeSort *pr // データの右側Ptr
){
「TypeSort* pl,」は、データ配列左端「l=left省略」
「TypeSort* pr」は、データ配列右端「r=right省略」
ここで使用する専用の型「TypeSort」≪
解説『解説クラスCopyClear(1)』の「(3)
クラス内ローカル構造体定義」で解説≫
(D)関数「sort_key_rev()」の【アルゴリズム】
){
TypeSort *pi; // 内部Ptr
TypeSort *pj; // 内部Ptr
short key; // 中央の値
int w; // 交換用の場所
pi = pl; // 左側をSet
pj = pr; // 右側をSet
key = ( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeSort) ) )->key; // セット
do{ // 以下繰り返し
while( pi->key > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > pj->key ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *(int*)pi; // 左右を
*pi = *pj; // 交換
*(int*)pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_key_rev( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_key_rev( pi, pr ); // この間をソート
} //
}
(D-1)ローカル変数
){
TypeSort *pi; // 内部Ptr
TypeSort *pj; // 内部Ptr
short key; // 中央の値
int w; // 交換用の場所
「TypeSort* pi;」は、内部ポインタ(左側用)
「TypeSort* pj;」は、内部ポインタ(右側用)
「short key;」は、中央の値(キー比較用)
「int w;」は、データ交換用の場所
(D―2)アルゴリズムコード
pi = pl; // 左側をSet
pj = pr; // 右側をSet
key = ( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeSort) ) )->key; // セット
do{ // 以下繰り返し
while( pi->key > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > pj->key ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *(int*)pi; // 左右を
*pi = *pj; // 交換
*(int*)pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_key_rev( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_key_rev( pi, pr ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=(pi+((int)pj-(int)pi)/(2*sizeof(TypeSort)))
->key;」は、左右の中央の場所(ポインタの中央)の
キー値「->key」を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(pi->key>key){pi++;}」は、while構文で
ループ条件「pi->key>key」は、「左側のキーの値が、
比較用の値越え」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以下に成るまで繰り
返す」、次の内側ループ
「while(key>pj->key){pj--;}」は、「右」側のキーの
値が、比較用の値未満」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*(int*)pi;*pi=*pj;*(int*)pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*(int*)pi;*pi=*pj;*(int*)pj=w;pi++;pj--;}」で先ず
「w=*(int*)pi;*pi=*pj;*(int*)pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
キャスト「型変換」として「(int*)」とローカル変数
「int w;」と「TypeSort型」と「int型」が4バイトに成る
事を確認した処理系で使用して居ます!この前提が崩れた
CPU&コンパイラシステムの場合は、書き換える必要が
有る事に留意!
そして「if(pl<pj){sort_key_rev(pl,pj);}」で再帰呼び出しを
自分自身「sort_key_rev()」関数をサブルーチン関数として
条件「pl<pj」=「元々の左側が内部の右側と左右関係が保
たれて居る」なら、再帰呼び出し「sort_key_rev(pl,pj);」を
行う事で数学の「帰納的定義法」と考えて再帰呼び出しを
行った部分「plからpjのポインタの示す左右範囲」が降順に
ソート済みと見なして処理する方法です!★備考★これが
再帰呼び出しを行う事で実現する「クイックソート」と呼ば
れる通常のデータでは最速と言われているアルゴリズムです
同じ様に「if(pi<pr){sort_key_rev(pi,pr);}」で範囲
「piからpr」のポインタの示す左右範囲」が降順に
ソート済みと見なして処理します!★備考★これが、
再帰呼び出しを行う事で実現する「クイックソート」と呼ば
れる通常のデータでは最速と言われているアルゴリズムです
コレは、多くの画像処理以外のプログラミングで使用されて
居ますので数学的帰納法をアルゴリズムに応用した事を理解
して下さい!C言語的には「再帰呼び出し」との文言で平気
で多用します!
(4-15-118)関数「void hist_byte(int hist[],BYTE* p,int l){・・・}」
/************************************************************************/
/***** ヒストグラムソート用配列のヒストグラム算出 *****/
/************************************************************************/
void CopyClear::hist_byte(
int hist[], // ヒストグラム配列
BYTE *p, // データ配列のPtr
int l // 配列のサイズ
){
BYTE *pend; // 終点のPtr
up_fill_int( 0, hist, 256 ); // Histogram初期化
pend = p + l; // 終点作成
l >>= 3; // 8単位毎に
while( --l >= 0 ){ // データ配列の
hist[ *p++ ]++; // ヒストグラム算出
hist[ *p++ ]++; //
hist[ *p++ ]++; //
hist[ *p++ ]++; //
hist[ *p++ ]++; //
hist[ *p++ ]++; //
hist[ *p++ ]++; //
hist[ *p++ ]++; //
} //
while( p < pend ){ // 残りの
hist[ *p++ ]++; // ヒストグラム算出
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「hist_byte();」の【関数名】
「hist」は、英単語「histogram」の略でカタカナ語
ヒストグラムで日本語では度数分布です!
「byte」は、勿論、「BYTE型」、画素が1バイトデータを
意味!
この関数は、対象データ配列のソートする為のヒストグラム
を算出する関数
★備考★画像処理の「ランキングフィルター」と言う処理では、恐ろしい程の高速化を発揮するヒストグラムを使用したソート技法ですが、普通の処理では「最も遅いソーティングアルゴリズム」と思われます!何故、極めて遅いアルゴリズムがランキングフィルター系の関数で高速化処理に成るかは
エッセイ『ヒストグラムソートとランキングフィルター』で解説!
そして、この関数は、コレを使用している関数
「sort_byte_hist()」で使用しているだけでランキングフィ
ルター作成時の実験に使用しただけの関数です!
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void hist_byte();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「hist_byte()」の【仮引数】
void CopyClear::hist_byte(
int hist[], // ヒストグラム配列
BYTE *p, // データ配列のPtr
int l // 配列のサイズ
){
「int hist[],」は、ヒストグラムデータ
「BYTE* p,」は、ソート対象データ配列
「int l」は、対象データ配列のサイズ
(D)関数「hist_byte()」の【アルゴリズム】
){
BYTE *pend; // 終点のPtr
up_fill_int( 0, hist, 256 ); // Histogram初期化
pend = p + l; // 終点作成
l >>= 3; // 8単位毎に
while( --l >= 0 ){ // データ配列の
hist[ *p++ ]++; // ヒストグラム算出
hist[ *p++ ]++; //
hist[ *p++ ]++; //
hist[ *p++ ]++; //
hist[ *p++ ]++; //
hist[ *p++ ]++; //
hist[ *p++ ]++; //
hist[ *p++ ]++; //
} //
while( p < pend ){ // 残りの
hist[ *p++ ]++; // ヒストグラム算出
} //
}
(D-1)ローカル変数
){
BYTE *pend; // 終点のPtr
「BYTE *pend;」は、データ配列終点
(D―2)アルゴリズムコード
up_fill_int( 0, hist, 256 ); // Histogram初期化
pend = p + l; // 終点作成
l >>= 3; // 8単位毎に
while( --l >= 0 ){ // データ配列の
hist[ *p++ ]++; // ヒストグラム算出
hist[ *p++ ]++; //
hist[ *p++ ]++; //
hist[ *p++ ]++; //
hist[ *p++ ]++; //
hist[ *p++ ]++; //
hist[ *p++ ]++; //
hist[ *p++ ]++; //
} //
while( p < pend ){ // 残りの
hist[ *p++ ]++; // ヒストグラム算出
} //
}
「up_fill_int(0,hist,256);」は、ヒストグラムデータを
初期化≪0クリア≫
「pend=p+l;l>>=3;」は、終点ポインタをセットと
「l>>=3;」≪シフト演算で「÷8」★備考★極初期に
高速化を考えたので分かり易い依り早いアルゴリズムを
考えた残滓だが今のCPUでは余り意味が無い!≫で8単位
毎の数に変更
「while(--l>=0){・・ループ本体・・}」は、8単位毎に
ダウンカウンタ方式≪高速化処理≫で繰り返し、ループ本体
「hist[*p++]++;hist[*p++]++;hist[*p++]++;hist[*p++]++;
hist[*p++]++;hist[*p++]++;hist[*p++]++;hist[*p++]++;」
は、基本のヒストグラム算出「hist[*p++]++;」を8単位
並べた物です!★備考★「*p++」で画素データ配列の値取り
出しと次へポインタ進行、「hist[式]++;」で仮引数
「int hist[],」のヒストグラムデータの所定の場所を
「++」とヒストグラム(度数分布)自体カウントアップ
して居る事は、理解出来ますね!
そして余りの画素データ配列に対して
「while(p<pend){hist[*p++]++;}」で画素データ配列の
最後までヒストグラムデータ算出!
(4-15-119)関数「void sort_byte_hist(int sw,BYTE* p,int l){・・・}」
/************************************************************************/
/***** ヒストグラムソート:データ=8bits *****/
/************************************************************************/
void CopyClear::sort_byte_hist(
int sw, // 0:昇順、1:降順
BYTE *p, // データ配列のPtr
int l // 配列のサイズ
){
int hist[ 256 ]; // ヒストグラム配列
int *ph; // 上記へのポインタ
int i; // カウンタ
hist_byte( hist, p, l ); // ヒストグラム算出
if( sw == 0 ){ // 昇順なら
ph = hist; // HistogramPtrをSet
for( i = 0; i <= 255; i++ ){ // 0..255 の間で
l = *ph++; // 対応する頻度を取
while( --l >= 0 ){ // り出しその頻度分
*p++ = i; // データを書き込む
} //
} //
}else{ // 降順なら
ph = &hist[ 256 ]; // HistogramPtrをSet
for( i = 255; i >= 0; i-- ){ // 255..0 の間で
l = *--ph; // 対応する頻度を取
while( --l >= 0 ){ // り出しその頻度分
*p++ = i; // データを書き込む
} //
} //
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_byte_hist();」の【関数名】
「hist」は、英単語「histogram」の略でカタカナ語
ヒストグラムで日本語では度数分布です!
「byte」は、勿論、「BYTE型」、画素が1バイトデータを
意味!
「hist」は、ヒストグラムサーチアルゴリズムを使用して
ソートする為の関数です!
★備考★画像処理の「ランキングフィルター」と言う処理で
は、恐ろしい程の高速化を発揮するヒストグラムを使用した
ソート技法ですが、普通の処理では「最も遅いソーティング
アルゴリズム」と思われます!何故、極めて遅いアルゴリズ
ムがランキングフィルター系の関数で高速化処理に成るかは
エッセイ『ヒストグラムソートとランキングフィルター』で
解説!
そして、この関数「sort_byte_hist()」はランキングフィ
ルター作成時の実験に使用しただけの関数です!
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_byte_hist();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_byte_hist()」の【仮引数】
void CopyClear::sort_byte_hist(
int sw, // 0:昇順、1:降順
BYTE *p, // データ配列のPtr
int l // 配列のサイズ
){
「int sw,」は、ソーティング向き≪0:昇順、1:降順≫
★備考★昇順≪小さい方からへ大きい方に整列≫
★備考★降順≪大きい方からへ小さい方に整列≫
「BYTE* p,」は、ソート対象データ配列
「int l」は、対象データ配列のサイズ
(D)関数「sort_byte_hist()」の【アルゴリズム】
){
int hist[ 256 ]; // ヒストグラム配列
int *ph; // 上記へのポインタ
int i; // カウンタ
hist_byte( hist, p, l ); // ヒストグラム算出
if( sw == 0 ){ // 昇順なら
ph = hist; // HistogramPtrをSet
for( i = 0; i <= 255; i++ ){ // 0..255 の間で
l = *ph++; // 対応する頻度を取
while( --l >= 0 ){ // り出しその頻度分
*p++ = i; // データを書き込む
} //
} //
}else{ // 降順なら
ph = &hist[ 256 ]; // HistogramPtrをSet
for( i = 255; i >= 0; i-- ){ // 255..0 の間で
l = *--ph; // 対応する頻度を取
while( --l >= 0 ){ // り出しその頻度分
*p++ = i; // データを書き込む
} //
} //
} //
}
(D-1)ローカル変数
){
int hist[ 256 ]; // ヒストグラム配列
int *ph; // 上記へのポインタ
int i; // カウンタ
「int hist[256];」は、ヒストグラムデータ配列
「int* ph;」は、上記への操作ポインタ
「int i;」は、ループカウンタ
(D―2)アルゴリズムコード
hist_byte( hist, p, l ); // ヒストグラム算出
if( sw == 0 ){ // 昇順なら
ph = hist; // HistogramPtrをSet
for( i = 0; i <= 255; i++ ){ // 0..255 の間で
l = *ph++; // 対応する頻度を取
while( --l >= 0 ){ // り出しその頻度分
*p++ = i; // データを書き込む
} //
} //
}else{ // 降順なら
ph = &hist[ 256 ]; // HistogramPtrをSet
for( i = 255; i >= 0; i-- ){ // 255..0 の間で
l = *--ph; // 対応する頻度を取
while( --l >= 0 ){ // り出しその頻度分
*p++ = i; // データを書き込む
} //
} //
} //
}
「hist_byte(hist,p,l);」は、1バイト単位画素のデータ
配列からヒストグラムデータ算出
「if(sw==0){ph=hist;for(i=0;i<=255;i++){l=*ph++;
while(--l>=0){*p++=i;}}}」は、if構文「if(sw==0){
・・成立・・}」で条件「sw==0」と昇順ソートの場合が
「ph=hist;」と操作ポインタに先頭をセットし、
「for(i=0;i<=255;i++){・・外側ループ本体・・}」は、
二重ループの外側ループでアップカウンタ「i=0..255」
まで繰り返し、その外側ループ本体で、先ず、
「l=*ph++;」は、ヒストグラムデータ取り出し、
「while(--l>=0){*p++=i;}」は、while構文で内側
ループを構成し、内側ループ条件「--l>=0」とダウンカウ
ンタ方式≪取り出したヒストグラムの値分繰り返し≫で内側
ループ本体「p++=i;」と書き込む!
「else{ph=&hist[256];for(i=255;i>=0;i--){l=--ph;
while(--l>=0){p++=i;}}}」は、「else{・・不成立・・
}」と「降順」の場合の処理で、
「ph=&hist[256];」と操作ポインタに終点をセットし、
「for(i=255;i>=0;i--){外側ループ本体・・}」は、
二重ループの外側ループでダウンカウンタ「i=255..0」
まで繰り返し、その外側ループ本体で、先ず、
「l=--ph;」は、ヒストグラムデータ取り出し、
「while(--l>=0){*p++=i;}」は、while構文で内側
ループを構成し、内側ループ条件「--l>=0」とダウンカウ
ンタ方式≪取り出したヒストグラムの値分繰り返し≫で内側
ループ本体「*p++=i;」と書き込む!
★備考★アルゴリズムを読んで頂いて分かる様に1バイト
画素単位の画像データの様に画素値の取る範囲「0..255」
と狭い範囲で大量のデータが有るので同じ値が長く続く
データを意識して設計したアルゴリズムですと極めて限定
された使用状況が必要な処理と判るでしょう!
(4-15-120)関数「void sort_byte_0(BYTE* pl,BYTE* pr){・・・}」
/************************************************************************/
/***** QUIC-SORT:昇順ソート:データ=8bits *****/
/************************************************************************/
void CopyClear::sort_byte_0(
BYTE *pl, // データの左側Ptr
BYTE *pr // データの右側Ptr
){
BYTE *pi; // 内部Ptr: 左
BYTE *pj; // 内部Ptr: 右
BYTE key; // 中央の値
BYTE w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(BYTE) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_byte_0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_byte_0( pi, pr ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_byte_0();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「byte」は、1バイト符号無し「BYTE型」データを意味し
ます!
「0」は、昇順にソートする事を意味します!
この関数は、データ配列を昇順≪小さい方から大きい方へ
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_byte_0();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_byte_0()」の【仮引数】
void CopyClear::sort_byte_0(
BYTE *pl, // データの左側Ptr
BYTE *pr // データの右側Ptr
){
「BYTE* pl,」は、データ配列左端「l=left省略」
「BYTE* pr」は、データ配列右端「r=right省略」
(D)関数「sort_byte_0()」の【アルゴリズム】
){
BYTE *pi; // 内部Ptr: 左
BYTE *pj; // 内部Ptr: 右
BYTE key; // 中央の値
BYTE w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(BYTE) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_byte_0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_byte_0( pi, pr ); // この間をソート
} //
}
(D-1)ローカル変数
){
BYTE *pi; // 内部Ptr: 左
BYTE *pj; // 内部Ptr: 右
BYTE key; // 中央の値
BYTE w; // 交換用の場所
「BYTE* pi;」は、内部ポインタ(左側用)
「BYTE* pj;」は、内部ポインタ(右側用)
「BYTE key;」は、中央の値(キー比較用)
「BYTE w;」は、データ交換用の場所
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(BYTE) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_byte_0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_byte_0( pi, pr ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(BYTE)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、
比較用の値未満」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、次の内側ループ
「while(key<*pj){pj--;}」は、「右」側の
値が、比較用の値越え」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_byte_0(pl,pj);}」で再帰呼び出し
を自分自身「sort_byte_0()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_byte_0(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_byte_0(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が昇順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!
(4-15-121)関数「void sort_byte_1(BYTE* pl,BYTE* pr){・・・}」
/************************************************************************/
/***** QUIC-SORT:降順ソート:データ=8bits *****/
/************************************************************************/
void CopyClear::sort_byte_1(
BYTE *pl, // データの左側Ptr
BYTE *pr // データの右側Ptr
){
BYTE *pi; // 内部Ptr: 左
BYTE *pj; // 内部Ptr: 右
BYTE key; // 中央の値
BYTE w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(BYTE) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_byte_1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_byte_1( pi, pr ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_byte_1();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「byte」は、1バイト符号無し「BYTE型」データを意味し
ます!
「1」は、降順にソートする事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_byte_1();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_byte_1()」の【仮引数】
void CopyClear::sort_byte_1(
BYTE *pl, // データの左側Ptr
BYTE *pr // データの右側Ptr
){
「BYTE* pl,」は、データ配列左端「l=left省略」
「BYTE* pr」は、データ配列右端「r=right省略」
(D)関数「sort_byte_1()」の【アルゴリズム】
){
BYTE *pi; // 内部Ptr: 左
BYTE *pj; // 内部Ptr: 右
BYTE key; // 中央の値
BYTE w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(BYTE) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_byte_1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_byte_1( pi, pr ); // この間をソート
} //
}
(D)ローカル変数
){
BYTE *pi; // 内部Ptr: 左
BYTE *pj; // 内部Ptr: 右
BYTE key; // 中央の値
BYTE w; // 交換用の場所
「BYTE* pi;」は、内部ポインタ(左側用)
「BYTE* pj;」は、内部ポインタ(右側用)
「BYTE key;」は、中央の値(キー比較用)
「BYTE w;」は、データ交換用の場所
(D)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(BYTE) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_byte_1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_byte_1( pi, pr ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(BYTE)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、
比較用の値越え」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以下に成るまで繰り
返す」、次の内側ループ
「while(key>*pj){pj--;}」は、「右」側の
値が、比較用の値未満」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_byte_1(pl,pj);}」で再帰呼び出し
を自分自身「sort_byte_1()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_byte_1(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_byte_1(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が昇順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!
(4-15-122)関数「void sort_short_0(short* pl,short* pr){・・・}」
/************************************************************************/
/***** QUIC-SORT:昇順ソート:データ=16bits *****/
/************************************************************************/
void CopyClear::sort_short_0(
short *pl, // データの左側Ptr
short *pr // データの右側Ptr
){
short *pi; // 内部Ptr: 左
short *pj; // 内部Ptr: 右
short key; // 中央の値
short w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(short) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_short_0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_short_0( pi, pr ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_short_0();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「short」は、2バイト符号有り「short型」データを意味し
ます!
「0」は、昇順にソートする事を意味します!
この関数は、データ配列を昇順≪小さい方から大きい方へ
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_short_0();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_short_0()」の【仮引数】
void CopyClear::sort_short_0(
short *pl, // データの左側Ptr
short *pr // データの右側Ptr
){
「short* pl,」は、データ配列左端「l=left省略」
「short* pr」は、データ配列右端「r=right省略」
(D)関数「sort_short_0()」の【アルゴリズム】
){
short *pi; // 内部Ptr: 左
short *pj; // 内部Ptr: 右
short key; // 中央の値
short w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(short) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_short_0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_short_0( pi, pr ); // この間をソート
} //
}
(D-1)ローカル変数
){
short *pi; // 内部Ptr: 左
short *pj; // 内部Ptr: 右
short key; // 中央の値
short w; // 交換用の場所
「short* pi;」は、内部ポインタ(左側用)
「short* pj;」は、内部ポインタ(右側用)
「short key;」は、中央の値(キー比較用)
「short w;」は、データ交換用の場所
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(short) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_short_0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_short_0( pi, pr ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(short)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、
比較用の値未満」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、次の内側ループ
「while(key<*pj){pj--;}」は、「右」側の
値が、比較用の値越え」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_short_0(pl,pj);}」で再帰呼び出し
を自分自身「sort_short_0()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_short_0(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_short_0(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が昇順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!
(4-15-123)関数「void sort_short_1(short* pl,short* pr){・・・}」
/************************************************************************/
/***** QUIC-SORT:降順ソート:データ=16bits *****/
/************************************************************************/
void CopyClear::sort_short_1(
short *pl, // データの左側Ptr
short *pr // データの右側Ptr
){
short *pi; // 内部Ptr: 左
short *pj; // 内部Ptr: 右
short key; // 中央の値
short w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(short) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_short_1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_short_1( pi, pr ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_short_1();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「short」は、1バイト符号無し「short型」データを意味し
ます!
「1」は、降順にソートする事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_short_1();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_short_1()」の【仮引数】
void CopyClear::sort_short_1(
short *pl, // データの左側Ptr
short *pr // データの右側Ptr
){
「short* pl,」は、データ配列左端「l=left省略」
「short* pr」は、データ配列右端「r=right省略」
(D)関数「sort_short_1()」の【アルゴリズム】
){
short *pi; // 内部Ptr: 左
short *pj; // 内部Ptr: 右
short key; // 中央の値
short w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(short) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_short_1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_short_1( pi, pr ); // この間をソート
} //
}
(D-1)ローカル変数
){
short *pi; // 内部Ptr: 左
short *pj; // 内部Ptr: 右
short key; // 中央の値
short w; // 交換用の場所
「short* pi;」は、内部ポインタ(左側用)
「short* pj;」は、内部ポインタ(右側用)
「short key;」は、中央の値(キー比較用)
「short w;」は、データ交換用の場所
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(short) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_short_1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_short_1( pi, pr ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(short)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、
比較用の値越え」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以下に成るまで繰り
返す」、次の内側ループ
「while(key>*pj){pj--;}」は、「右」側の
値が、比較用の値未満」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_short_1(pl,pj);}」で再帰呼び出し
を自分自身「sort_short_1()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_short_1(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_short_1(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が昇順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!
(4-15-124)関数「void sort_long_0(long* pl,long* pr){・・・}」
/************************************************************************/
/***** QUIC-SORT:昇順ソート:データ=32bits *****/
/************************************************************************/
void CopyClear::sort_long_0(
long *pl, // データの左側Ptr
long *pr // データの右側Ptr
){
long *pi; // 内部Ptr: 左
long *pj; // 内部Ptr: 右
int key; // 中央の値
int w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(long) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_long_0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_long_0( pi, pr ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_long_0();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「long」は、4バイト符号有り「long型」データを意味し
ます!
「0」は、昇順にソートする事を意味します!
この関数は、データ配列を昇順≪小さい方から大きい方へ
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_long_0();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_long_0()」の【仮引数】
void CopyClear::sort_long_0(
long *pl, // データの左側Ptr
long *pr // データの右側Ptr
){
「long* pl,」は、データ配列左端「l=left省略」
「long* pr」は、データ配列右端「r=right省略」
(D)関数「sort_long_0()」の【アルゴリズム】
){
long *pi; // 内部Ptr: 左
long *pj; // 内部Ptr: 右
int key; // 中央の値
int w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(long) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_long_0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_long_0( pi, pr ); // この間をソート
} //
}
(D-1)ローカル変数
){
long *pi; // 内部Ptr: 左
long *pj; // 内部Ptr: 右
int key; // 中央の値
int w; // 交換用の場所
「long* pi;」は、内部ポインタ(左側用)
「long* pj;」は、内部ポインタ(右側用)
「int key;」は、中央の値(キー比較用)
「int w;」は、データ交換用の場所
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(long) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_long_0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_long_0( pi, pr ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(long)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、
比較用の値未満」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、次の内側ループ
「while(key<*pj){pj--;}」は、「右」側の
値が、比較用の値越え」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_long_0(pl,pj);}」で再帰呼び出し
を自分自身「sort_long_0()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_long_0(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_long_0(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が昇順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!
★★特注「note編集機能不具合」★★
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(long)))」と
コピペでテキストを記載したら、
「key=(pi+((int)pj-(int)pi)/(2sizeof(long)))」等と
主に「*」が消える事が多々ありますので注意して手作業で
修正して居るが、全て修正出来て無い部分が有る事に留意し
て読んで頂きたい!必ず、【<>code】機能で生のテキ
ストを必ず参考にして下さい!!
(4-15-125)関数「void sort_long_1(long* pl,long* pr){・・・}」
/************************************************************************/
/***** QUIC-SORT:降順ソート:データ=32bits *****/
/************************************************************************/
void CopyClear::sort_long_1(
long *pl, // データの左側Ptr
long *pr // データの右側Ptr
){
long *pi; // 内部Ptr: 左
long *pj; // 内部Ptr: 右
int key; // 中央の値
int w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(long) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_long_1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_long_1( pi, pr ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_long_1();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「long」は、4バイト符号有り「long型」データを意味し
ます!
「1」は、降順にソートする事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_long_1();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_long_1()」の【仮引数】
void CopyClear::sort_long_1(
long *pl, // データの左側Ptr
long *pr // データの右側Ptr
){
「long* pl,」は、データ配列左端「l=left省略」
「long* pr」は、データ配列右端「r=right省略」
(D)関数「sort_long_1()」の【アルゴリズム】
){
long *pi; // 内部Ptr: 左
long *pj; // 内部Ptr: 右
int key; // 中央の値
int w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(long) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_long_1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_long_1( pi, pr ); // この間をソート
} //
}
(D-1)ローカル変数
){
long *pi; // 内部Ptr: 左
long *pj; // 内部Ptr: 右
int key; // 中央の値
int w; // 交換用の場所
「long* pi;」は、内部ポインタ(左側用)
「long* pj;」は、内部ポインタ(右側用)
「int key;」は、中央の値(キー比較用)
「int w;」は、データ交換用の場所
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(long) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_long_1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_long_1( pi, pr ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(long)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、
比較用の値越え」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以下に成るまで繰り
返す」、次の内側ループ
「while(key>*pj){pj--;}」は、「右」側の
値が、比較用の値未満」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_long_1(pl,pj);}」で再帰呼び出し
を自分自身「sort_long_1()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_long_1(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が降順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_long_1(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が降順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!
(4-15-126)関数「void sort_long_0_key(long* pl,
long* pr,short* plx,short* prx){・・・}」
/************************************************************************/
/***** QUIC-SORT:昇順ソート:キー=32、添字=16 *****/
/************************************************************************/
void CopyClear::sort_long_0_key(
long *pl, // KeyDataの左側Ptr
long *pr, // KeyDataの右側Ptr
short *plx, // 添字Data左側Ptr
short *prx // 添字Data右側Ptr
){
long *pi; // 内部KeyPtr: 左
long *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
int key; // 中央の値
int w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(long) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_long_0_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_long_0_key( pi, pr, pix, prx ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_long_0_key();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「long」は、4バイト符号有り「long型」データを意味し
ます!
「0」は、昇順にソートする事を意味します!
「key」は、キー付きを意味し、連動して連動配列も中身の
入れ替えを行う事を意味します!
この関数は、データ配列を昇順≪小さい方から大きい方へ
整列≫にソートする関数でインデックス配列も連動して作成
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_long_0_key();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_long_0_key()」の【仮引数】
void CopyClear::sort_long_0_key(
long *pl, // KeyDataの左側Ptr
long *pr, // KeyDataの右側Ptr
short *plx, // 添字Data左側Ptr
short *prx // 添字Data右側Ptr
){
「long* pl,」は、データ配列左端「l=left省略」
「long* pr」は、データ配列右端「r=right省略」
「short* plx,」は、連動配列配列左端
「short* prx」は、連動配列配列左端
★備考★上記「long* pl,long* pr」をソート対象キー配列
として、ここ「short* plx,short* prx」は、連動して入れ
替えられる配列
(D)関数「sort_long_0_key()」の【アルゴリズム】
){
long *pi; // 内部KeyPtr: 左
long *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
int key; // 中央の値
int w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(long) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_long_0_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_long_0_key( pi, pr, pix, prx ); // この間をソート
} //
}
(D-1)ローカル変数
){
long *pi; // 内部KeyPtr: 左
long *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
int key; // 中央の値
int w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
「long* pi;」は、内部ポインタ(左側用)キー
「long* pj;」は、内部ポインタ(右側用)キー
「short* pix;」は、内部ポインタ(左側用)連動
「short* pjx;」は、内部ポインタ(右側用)連動
「int key;」は、中央の値(キー比較用)
「int w;」は、データ交換用の場所
「short wx;」は、データ交換用の場所連動
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(long) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_long_0_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_long_0_key( pi, pr, pix, prx ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「pix=plx;pjx=prx;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(long)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;pix++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、比較用の値
未満」の間「pi++;pix++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、
次の内側ループ
「while(key<*pj){pj--;pjx--;}」は、「右」側の値が、
比較用の値越え」の間「pj--;pjx--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;wx=*pix;
*pix=*pjx;*pjx=wx;pix++;pjx--;
wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして連動配列の入れ替えとして
「wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;」と配列入れ
替えを行い!「do構文」を終えると!
そして「if(pl<pj){sort_long_0_key(pl,pj,plx,pjx);}」
で再帰呼び出しを自分自身「sort_long_0_key()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sort_long_0_key(pl,pj,plx,pjx);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_long_0_key(pi,pr,pix,prx);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!
(4-15-127)関数「void sort_long_1_key(long* pl,
long* pr,short* plx,short* prx){・・・}」
/************************************************************************/
/***** QUIC-SORT:降順ソート:キー=32、添字1=16 *****/
/************************************************************************/
void CopyClear::sort_long_1_key(
long *pl, // KeyDataの左側Ptr
long *pr, // KeyDataの右側Ptr
short *plx, // 添字Data左側Ptr
short *prx // 添字Data右側Ptr
){
long *pi; // 内部KeyPtr: 左
long *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
int key; // 中央の値
int w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(long) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_long_1_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_long_1_key( pi, pr, pix, prx ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_long_1_key();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「long」は、4バイト符号有り「long型」データを意味し
ます!
「1」は、降順にソートする事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数
「key」は、キー付きを意味し、連動して連動配列も中身の
入れ替えを行う事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数でインデックス配列も連動して作成
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_long_1_key();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_long_1_key()」の【仮引数】
void CopyClear::sort_long_1_key(
long *pl, // KeyDataの左側Ptr
long *pr, // KeyDataの右側Ptr
short *plx, // 添字Data左側Ptr
short *prx // 添字Data右側Ptr
){
「long* pl,」は、データ配列左端「l=left省略」
「long* pr」は、データ配列右端「r=right省略」
「short* plx,」は、連動配列配列左端
「short* prx」は、連動配列配列左端
★備考★上記「long* pl,long* pr」をソート対象キー配列
として、ここ「short* plx,short* prx」は、連動して入れ
替えられる配列
(D)関数「sort_long_1_key()」の【アルゴリズム】
){
long *pi; // 内部KeyPtr: 左
long *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
int key; // 中央の値
int w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(long) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_long_1_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_long_1_key( pi, pr, pix, prx ); // この間をソート
} //
}
(D-1)ローカル変数
){
long *pi; // 内部KeyPtr: 左
long *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
int key; // 中央の値
int w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
「long* pi;」は、内部ポインタ(左側用)キー
「long* pj;」は、内部ポインタ(右側用)キー
「short* pix;」は、内部ポインタ(左側用)連動
「short* pjx;」は、内部ポインタ(右側用)連動
「int key;」は、中央の値(キー比較用)
「int w;」は、データ交換用の場所
「short wx;」は、データ交換用の場所連動
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(long) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_long_1_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_long_1_key( pi, pr, pix, prx ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「pix=plx;pjx=prx;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(long)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;pix++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、比較用の値
未満」の間「pi++;pix++;」ポインタを右側に移動を繰り返
すと、即ち、「左側がキーの値以下に成るまで繰り返す」、
次の内側ループ
「while(key>*pj){pj--;pjx--;}」は、「右」側の値が、
比較用の値越え」の間「pj--;pjx--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;wx=*pix;
*pix=*pjx;*pjx=wx;pix++;pjx--;
wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして連動配列の入れ替えとして
「wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;」と配列入れ
替えを行い!「do構文」を終えると!
そして「if(pl<pj){sort_long_1_key(pl,pj,plx,pjx);}」
で再帰呼び出しを自分自身「sort_long_1_key()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sort_long_1_key(pl,pj,plx,pjx);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が降順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_long_1_key(pi,pr,pix,prx);}」で範囲
「piからpr」のポインタの示す左右範囲」が降順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!
★★特注「note編集機能不具合」★★
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(long)))」と
コピペでテキストを記載したら、
「key=(pi+((int)pj-(int)pi)/(2sizeof(long)))」等と
主に「*」が消える事が多々ありますので注意して手作業で
修正して居るが、全て修正出来て無い部分が有る事に留意し
て読んで頂きたい!必ず、【<>code】機能で生のテキ
ストを必ず参考にして下さい!!
(4-15-128)関数「void sort_float_0(float* pl,float* pr){・・・}」
/************************************************************************/
/***** QUIC-SORT:昇順ソート:データ=単精度実数 *****/
/************************************************************************/
void CopyClear::sort_float_0(
float *pl, // データの左側Ptr
float *pr // データの右側Ptr
){
float *pi; // 内部Ptr: 左
float *pj; // 内部Ptr: 右
float key; // 中央の値
float w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(float) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_float_0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_float_0( pi, pr ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_float_0();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「float」は、単精度浮動小数型「float型」データを意味
します!
「0」は、昇順にソートする事を意味します!
この関数は、データ配列を昇順≪小さい方から大きい方へ
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_float_0();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_float_0()」の【仮引数】
void CopyClear::sort_float_0(
float *pl, // データの左側Ptr
float *pr // データの右側Ptr
){
「float* pl,」は、データ配列左端「l=left省略」
「float* pr」は、データ配列右端「r=right省略」
(D)関数「sort_float_0()」の【アルゴリズム】
){
float *pi; // 内部Ptr: 左
float *pj; // 内部Ptr: 右
float key; // 中央の値
float w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(float) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_float_0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_float_0( pi, pr ); // この間をソート
} //
}
(D-1)ローカル変数
){
float *pi; // 内部Ptr: 左
float *pj; // 内部Ptr: 右
float key; // 中央の値
float w; // 交換用の場所
「float* pi;」は、内部ポインタ(左側用)
「float* pj;」は、内部ポインタ(右側用)
「float key;」は、中央の値(キー比較用)
「float w;」は、データ交換用の場所
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(float) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_float_0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_float_0( pi, pr ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(float)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、
比較用の値未満」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、次の内側ループ
「while(key<*pj){pj--;}」は、「右」側の
値が、比較用の値越え」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_float_0(pl,pj);}」で再帰呼び出し
を自分自身「sort_float_0()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_float_0(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_float_0(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が昇順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!
(4-15-129)関数「void sort_float_1(float* pl,float* pr){・・・}」
/************************************************************************/
/***** QUIC-SORT:降順ソート:データ=単精度実数 *****/
/************************************************************************/
void CopyClear::sort_float_1(
float *pl, // データの左側Ptr
float *pr // データの右側Ptr
){
float *pi; // 内部Ptr: 左
float *pj; // 内部Ptr: 右
float key; // 中央の値
float w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(float) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_float_1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_float_1( pi, pr ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_float_1();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「float」は、単精度浮動小数型「float型」データを意味
します!
「1」は、降順にソートする事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_float_1();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_float_1()」の【仮引数】
void CopyClear::sort_float_1(
float *pl, // データの左側Ptr
float *pr // データの右側Ptr
){
「float* pl,」は、データ配列左端「l=left省略」
「float* pr」は、データ配列右端「r=right省略」
(D)関数「sort_float_1()」の【アルゴリズム】
){
float *pi; // 内部Ptr: 左
float *pj; // 内部Ptr: 右
float key; // 中央の値
float w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(float) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_float_1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_float_1( pi, pr ); // この間をソート
} //
}
(D-1)ローカル変数
){
float *pi; // 内部Ptr: 左
float *pj; // 内部Ptr: 右
float key; // 中央の値
float w; // 交換用の場所
「float* pi;」は、内部ポインタ(左側用)
「float* pj;」は、内部ポインタ(右側用)
「float key;」は、中央の値(キー比較用)
「float w;」は、データ交換用の場所
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(float) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_float_1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_float_1( pi, pr ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(float)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、
比較用の値越え」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以下に成るまで繰り
返す」、次の内側ループ
「while(key>*pj){pj--;}」は、「右」側の
値が、比較用の値未満」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_float_1(pl,pj);}」で再帰呼び出し
を自分自身「sort_float_1()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_float_1(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が降順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_float_1(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が降順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!
★★特注「note編集機能不具合」★★
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(float)))」と
コピペでテキストを記載したら、
「key=(pi+((int)pj-(int)pi)/(2sizeof(float)))」等と
主に「*」が消える事が多々ありますので注意して手作業で
修正して居るが、全て修正出来て無い部分が有る事に留意し
て読んで頂きたい!必ず、【<>code】機能で生のテキ
ストを必ず参考にして下さい!!
(4-15-130)関数「void sort_float_0_key(float* pl,
float* pr,short* plx,short* prx){・・・}」
/************************************************************************/
/***** QUIC-SORT:昇順ソート:キー=単精度、添字=16 *****/
/************************************************************************/
void CopyClear::sort_float_0_key(
float *pl, // KeyDataの左側Ptr
float *pr, // KeyDataの右側Ptr
short *plx, // 添字Data左側Ptr
short *prx // 添字Data右側Ptr
){
float *pi; // 内部KeyPtr: 左
float *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
float key; // 中央の値
float w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(float) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_float_0_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_float_0_key( pi, pr, pix, prx ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_float_0_key();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「float」は、単精度浮動小数型「float型」データを意味
します!
「0」は、昇順にソートする事を意味します!
「key」は、キー付きを意味し、連動して連動配列も中身の
入れ替えを行う事を意味します!
この関数は、データ配列を昇順≪小さい方から大きい方へ
整列≫にソートする関数でインデックス配列も連動して作成
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_float_0_key();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_float_0_key()」の【仮引数】
void CopyClear::sort_float_0_key(
float *pl, // KeyDataの左側Ptr
float *pr, // KeyDataの右側Ptr
short *plx, // 添字Data左側Ptr
short *prx // 添字Data右側Ptr
){
「float* pl,」は、データ配列左端「l=left省略」
「float* pr」は、データ配列右端「r=right省略」
「short* plx,」は、連動配列配列左端
「short* prx」は、連動配列配列左端
★備考★上記「float* pl,float* pr」をソート対象キー配列
として、ここ「short* plx,short* prx」は、連動して入れ
替えられる配列
(D)関数「sort_float_0_key()」の【アルゴリズム】
){
float *pi; // 内部KeyPtr: 左
float *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
float key; // 中央の値
float w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(float) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_float_0_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_float_0_key( pi, pr, pix, prx ); // この間をソート
} //
}
(D-1)ローカル変数
){
float *pi; // 内部KeyPtr: 左
float *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
float key; // 中央の値
float w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
「float* pi;」は、内部ポインタ(左側用)キー
「float* pj;」は、内部ポインタ(右側用)キー
「short* pix;」は、内部ポインタ(左側用)連動
「short* pjx;」は、内部ポインタ(右側用)連動
「float key;」は、中央の値(キー比較用)
「float w;」は、データ交換用の場所
「short wx;」は、データ交換用の場所連動
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(float) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_float_0_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_float_0_key( pi, pr, pix, prx ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「pix=plx;pjx=prx;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(float)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、
比較用の値未満」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、次の内側ループ
「while(key<*pj){pj--;}」は、「右」側の
値が、比較用の値越え」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;wx=*pix;
*pix=*pjx;*pjx=wx;pix++;pjx--;
wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして連動配列の入れ替えとして
「wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;」と配列入れ
替えを行い!「do構文」を終えると!
そして「if(pl<pj){sort_float_0_key(pl,pj,plx,pjx);}」
で再帰呼び出しを自分自身「sort_float_0_key()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sort_float_0_key(pl,pj,plx,pjx);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_float_0_key(pi,pr,pix,prx);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!
(4-15-131)関数「void sort_float_1_key(float* pl,
float* pr,short* plx,short* prx){・・・}」
/************************************************************************/
/***** QUIC-SORT:降順ソート:キー=単精度、添字1=16 *****/
/************************************************************************/
void CopyClear::sort_float_1_key(
float *pl, // KeyDataの左側Ptr
float *pr, // KeyDataの右側Ptr
short *plx, // 添字Data左側Ptr
short *prx // 添字Data右側Ptr
){
float *pi; // 内部KeyPtr: 左
float *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
float key; // 中央の値
float w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(float) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_float_1_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_float_1_key( pi, pr, pix, prx ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_float_1_key();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「float」は、単精度浮動小数型「float型」データを意味
します!
「1」は、降順にソートする事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数
「key」は、キー付きを意味し、連動して連動配列も中身の
入れ替えを行う事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数でインデックス配列も連動して作成
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_float_1_key();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_float_1_key()」の【仮引数】
void CopyClear::sort_float_1_key(
float *pl, // KeyDataの左側Ptr
float *pr, // KeyDataの右側Ptr
short *plx, // 添字Data左側Ptr
short *prx // 添字Data右側Ptr
){
「float* pl,」は、データ配列左端「l=left省略」
「float* pr」は、データ配列右端「r=right省略」
「short* plx,」は、連動配列配列左端
「short* prx」は、連動配列配列左端
★備考★上記「float* pl,float* pr」をソート対象キー配列
として、ここ「short* plx,short* prx」は、連動して入れ
替えられる配列
(D)関数「sort_float_1_key()」の【アルゴリズム】
){
float *pi; // 内部KeyPtr: 左
float *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
float key; // 中央の値
float w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(float) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_float_1_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_float_1_key( pi, pr, pix, prx ); // この間をソート
} //
}
(D-1)ローカル変数
){
float *pi; // 内部KeyPtr: 左
float *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
float key; // 中央の値
float w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
「float* pi;」は、内部ポインタ(左側用)キー
「float* pj;」は、内部ポインタ(右側用)キー
「short* pix;」は、内部ポインタ(左側用)連動
「short* pjx;」は、内部ポインタ(右側用)連動
「float key;」は、中央の値(キー比較用)
「float w;」は、データ交換用の場所
「short wx;」は、データ交換用の場所連動
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(float) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_float_1_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_float_1_key( pi, pr, pix, prx ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「pix=plx;pjx=prx;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(float)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;pix++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、比較用の値
未満」の間「pi++;pix++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、
次の内側ループ
「while(key>*pj){pj--;pjx--;}」は、「右」側の値が、
比較用の値未満」の間「pj--;pjx--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;wx=*pix;
*pix=*pjx;*pjx=wx;pix++;pjx--;
wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして連動配列の入れ替えとして
「wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;」と配列入れ
替えを行い!「do構文」を終えると!
そして「if(pl<pj){sort_float_1_key(pl,pj,plx,pjx);}」
で再帰呼び出しを自分自身「sort_float_1_key()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sort_float_1_key(pl,pj,plx,pjx);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が降順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_float_1_key(pi,pr,pix,prx);}」で範囲
「piからpr」のポインタの示す左右範囲」が降順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!
(4-15-132)関数「void sort_double_0(double* pl,
double* pr){・・・}」
/************************************************************************/
/***** QUIC-SORT:昇順ソート:データ=倍精度実数 *****/
/************************************************************************/
void CopyClear::sort_double_0(
double *pl, // データの左側Ptr
double *pr // データの右側Ptr
){
double *pi; // 内部Ptr: 左
double *pj; // 内部Ptr: 右
double key; // 中央の値
double w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(double) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_double_0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_double_0( pi, pr ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_double_0();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「double」は、倍精度浮動小数型「double型」データを意味
します!
「0」は、昇順にソートする事を意味します!
この関数は、データ配列を昇順≪小さい方から大きい方へ
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_double_0();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_double_0()」の【仮引数】
void CopyClear::sort_double_0(
double *pl, // データの左側Ptr
double *pr // データの右側Ptr
){
「double* pl,」は、データ配列左端「l=left省略」
「double* pr」は、データ配列右端「r=right省略」
(D)関数「sort_double_0()」の【アルゴリズム】
){
double *pi; // 内部Ptr: 左
double *pj; // 内部Ptr: 右
double key; // 中央の値
double w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(double) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_double_0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_double_0( pi, pr ); // この間をソート
} //
}
(D-1)ローカル変数
){
double *pi; // 内部Ptr: 左
double *pj; // 内部Ptr: 右
double key; // 中央の値
double w; // 交換用の場所
「double* pi;」は、内部ポインタ(左側用)
「double* pj;」は、内部ポインタ(右側用)
「double key;」は、中央の値(キー比較用)
「double w;」は、データ交換用の場所
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(double) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_double_0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_double_0( pi, pr ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(double)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、
比較用の値未満」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、次の内側ループ
「while(key<*pj){pj--;}」は、「右」側の
値が、比較用の値越え」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_double_0(pl,pj);}」で再帰呼び出し
を自分自身「sort_double_0()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_double_0(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_double_0(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が昇順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!
(4-15-133)関数「void sort_double_1(double* pl,
double* pr){・・・}」
/************************************************************************/
/***** QUIC-SORT:降順ソート:データ=倍精度実数 *****/
/************************************************************************/
void CopyClear::sort_double_1(
double *pl, // データの左側Ptr
double *pr // データの右側Ptr
){
double *pi; // 内部Ptr: 左
double *pj; // 内部Ptr: 右
double key; // 中央の値
double w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(double) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_double_1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_double_1( pi, pr ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_double_1();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「double」は、倍精度浮動小数型「double型」データを意味
します!
「1」は、降順にソートする事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_double_1();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_double_1()」の【仮引数】
void CopyClear::sort_double_1(
double *pl, // データの左側Ptr
double *pr // データの右側Ptr
){
「double* pl,」は、データ配列左端「l=left省略」
「double* pr」は、データ配列右端「r=right省略」
(D)関数「sort_double_1()」の【アルゴリズム】
){
double *pi; // 内部Ptr: 左
double *pj; // 内部Ptr: 右
double key; // 中央の値
double w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(double) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_double_1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_double_1( pi, pr ); // この間をソート
} //
}
(D-1)ローカル変数
){
double *pi; // 内部Ptr: 左
double *pj; // 内部Ptr: 右
double key; // 中央の値
double w; // 交換用の場所
「double* pi;」は、内部ポインタ(左側用)
「double* pj;」は、内部ポインタ(右側用)
「double key;」は、中央の値(キー比較用)
「double w;」は、データ交換用の場所
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(double) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_double_1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_double_1( pi, pr ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(double)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、
比較用の値越え」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以下に成るまで繰り
返す」、次の内側ループ
「while(key>*pj){pj--;}」は、「右」側の
値が、比較用の値未満」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_double_1(pl,pj);}」で再帰呼び出し
を自分自身「sort_double_1()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_double_1(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が降順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_double_1(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が降順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!
(4-15-134)関数「void sort_double_0_key(
double* pl,double* pr,
short* plx,short* prx){・・・}」
/************************************************************************/
/***** QUIC-SORT:昇順ソート:キー=倍精度、添字=16 *****/
/************************************************************************/
void CopyClear::sort_double_0_key(
double *pl, // KeyDataの左側Ptr
double *pr, // KeyDataの右側Ptr
short *plx, // 添字Data左側Ptr
short *prx // 添字Data右側Ptr
){
double *pi; // 内部KeyPtr: 左
double *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
double key; // 中央の値
double w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(double) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_double_0_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_double_0_key( pi, pr, pix, prx ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_double_0_key();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「double」は、倍精度浮動小数型「double型」データを意味
します!
「0」は、昇順にソートする事を意味します!
「key」は、キー付きを意味し、連動して連動配列も中身の
入れ替えを行う事を意味します!
この関数は、データ配列を昇順≪小さい方から大きい方へ
整列≫にソートする関数でインデックス配列も連動して作成
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_double_0_key();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_double_0_key()」の【仮引数】
void CopyClear::sort_double_0_key(
double *pl, // KeyDataの左側Ptr
double *pr, // KeyDataの右側Ptr
short *plx, // 添字Data左側Ptr
short *prx // 添字Data右側Ptr
){
「double* pl,」は、データ配列左端「l=left省略」
「double* pr」は、データ配列右端「r=right省略」
「short* plx,」は、連動配列配列左端
「short* prx」は、連動配列配列左端
★備考★上記「double* pl,double* pr」をソート対象キー配列
として、ここ「short* plx,short* prx」は、連動して入れ
替えられる配列
(D)関数「sort_double_0_key()」の【アルゴリズム】
){
double *pi; // 内部KeyPtr: 左
double *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
double key; // 中央の値
double w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(double) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_double_0_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_double_0_key( pi, pr, pix, prx ); // この間をソート
} //
}
(D-1)ローカル変数
){
double *pi; // 内部KeyPtr: 左
double *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
double key; // 中央の値
double w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
「double* pi;」は、内部ポインタ(左側用)キー
「double* pj;」は、内部ポインタ(右側用)キー
「short* pix;」は、内部ポインタ(左側用)連動
「short* pjx;」は、内部ポインタ(右側用)連動
「double key;」は、中央の値(キー比較用)
「double w;」は、データ交換用の場所
「short wx;」は、データ交換用の場所連動
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(double) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_double_0_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_double_0_key( pi, pr, pix, prx ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「pix=plx;pjx=prx;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(double)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;pix++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、比較用の値未満
」の間「pi++;pix++;」ポインタを右側に移動を繰り返すと
即ち、「左側がキーの値以上に成るまで繰り返す」、
次の内側ループ
「while(key<*pj){pj--;pjx--;}」は、「右」側の値が、
比較用の値越え」の間「pj--;pjx--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;wx=*pix;
*pix=*pjx;*pjx=wx;pix++;pjx--;
wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして連動配列の入れ替えとして
「wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;」と配列入れ
替えを行い!「do構文」を終えると!
そして「if(pl<pj){sort_double_0_key(pl,pj,plx,pjx);}」
で再帰呼び出しを自分自身「sort_double_0_key()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sort_double_0_key(pl,pj,plx,pjx);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_double_0_key(pi,pr,pix,prx);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!
(4-15-135)関数「void sort_double_1_key(
double* pl,double* pr,
short* plx,short* prx){・・・}」
/************************************************************************/
/***** QUIC-SORT:降順ソート:キー=倍精度、添字1=16 *****/
/************************************************************************/
void CopyClear::sort_double_1_key(
double *pl, // KeyDataの左側Ptr
double *pr, // KeyDataの右側Ptr
short *plx, // 添字Data左側Ptr
short *prx // 添字Data右側Ptr
){
double *pi; // 内部KeyPtr: 左
double *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
double key; // 中央の値
double w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(double) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_double_1_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_double_1_key( pi, pr, pix, prx ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_double_1_key();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「double」は、倍精度浮動小数型「double型」データを意味
します!
「1」は、降順にソートする事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数
「key」は、キー付きを意味し、連動して連動配列も中身の
入れ替えを行う事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数でインデックス配列も連動して作成
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_double_1_key();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_double_1_key()」の【仮引数】
void CopyClear::sort_double_1_key(
double *pl, // KeyDataの左側Ptr
double *pr, // KeyDataの右側Ptr
short *plx, // 添字Data左側Ptr
short *prx // 添字Data右側Ptr
){
「double* pl,」は、データ配列左端「l=left省略」
「double* pr」は、データ配列右端「r=right省略」
「short* plx,」は、連動配列配列左端
「short* prx」は、連動配列配列左端
★備考★上記「double* pl,double* pr」をソート対象キー配列
として、ここ「short* plx,short* prx」は、連動して入れ
替えられる配列
(D)関数「sort_double_1_key()」の【アルゴリズム】
){
double *pi; // 内部KeyPtr: 左
double *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
double key; // 中央の値
double w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(double) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_double_1_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_double_1_key( pi, pr, pix, prx ); // この間をソート
} //
}
(D-1)ローカル変数
){
double *pi; // 内部KeyPtr: 左
double *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
double key; // 中央の値
double w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
「double* pi;」は、内部ポインタ(左側用)キー
「double* pj;」は、内部ポインタ(右側用)キー
「short* pix;」は、内部ポインタ(左側用)連動
「short* pjx;」は、内部ポインタ(右側用)連動
「double key;」は、中央の値(キー比較用)
「double w;」は、データ交換用の場所
「short wx;」は、データ交換用の場所連動
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(double) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_double_1_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_double_1_key( pi, pr, pix, prx ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「pix=plx;pjx=prx;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(double)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;pix++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、比較用の値未満
」の間「pi++;pix++;」ポインタを右側に移動を繰り返すと
即ち、「左側がキーの値以上に成るまで繰り返す」、
次の内側ループ
「while(key>*pj){pj--;pjx--;}」は、「右」側の値が、
比較用の値未満」の間「pj--;pjx--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成るまで
繰り返す」、
そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;wx=*pix;
*pix=*pjx;*pjx=wx;pix++;pjx--;
wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして連動配列の入れ替えとして
「wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;」と配列入れ
替えを行い!「do構文」を終えると!
そして「if(pl<pj){sort_double_1_key(pl,pj,plx,pjx);}」
で再帰呼び出しを自分自身「sort_double_1_key()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sort_double_1_key(pl,pj,plx,pjx);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が降順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_double_1_key(pi,pr,pix,prx);}」で範囲
「piからpr」のポインタの示す左右範囲」が降順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!
(4-15-136)関数「void sort_int64_0(__int64* pl,
__int64* pr){・・・}」
/************************************************************************/
/***** QUIC-SORT:昇順ソート:データ=64Bit整数 *****/
/************************************************************************/
void CopyClear::sort_int64_0(
__int64 *pl, // データの左側Ptr
__int64 *pr // データの右側Ptr
){
__int64 *pi; // 内部Ptr: 左
__int64 *pj; // 内部Ptr: 右
__int64 key; // 中央の値
__int64 w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(__int64) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_int64_0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_int64_0( pi, pr ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_int64_0();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「__int64」は、8バイト整数型「__int64型」データを意味
します!
「0」は、昇順にソートする事を意味します!
この関数は、データ配列を昇順≪小さい方から大きい方へ
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_int64_0();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_int64_0()」の【仮引数】
void CopyClear::sort_int64_0(
__int64 *pl, // データの左側Ptr
__int64 *pr // データの右側Ptr
){
「__int64* pl,」は、データ配列左端「l=left省略」
「__int64* pr」は、データ配列右端「r=right省略」
(D)関数「sort_int64_0()」の【アルゴリズム】
){
__int64 *pi; // 内部Ptr: 左
__int64 *pj; // 内部Ptr: 右
__int64 key; // 中央の値
__int64 w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(__int64) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_int64_0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_int64_0( pi, pr ); // この間をソート
} //
}
(D-1)ローカル変数
){
__int64 *pi; // 内部Ptr: 左
__int64 *pj; // 内部Ptr: 右
__int64 key; // 中央の値
__int64 w; // 交換用の場所
「__int64* pi;」は、内部ポインタ(左側用)
「__int64* pj;」は、内部ポインタ(右側用)
「__int64 key;」は、中央の値(キー比較用)
「__int64 w;」は、データ交換用の場所
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(__int64) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_int64_0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_int64_0( pi, pr ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(__int64)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、
比較用の値未満」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、次の内側ループ
「while(key<*pj){pj--;}」は、「右」側の
値が、比較用の値越え」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_int64_0(pl,pj);}」で再帰呼び出し
を自分自身「sort_int64_0()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_int64_0(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_int64_0(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が昇順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!
(4-15-137)関数「void sort_int64_1(__int64* pl,
__int64* pr){・・・}」
/************************************************************************/
/***** QUIC-SORT:降順ソート:データ=64Bit整数 *****/
/************************************************************************/
void CopyClear::sort_int64_1(
__int64 *pl, // データの左側Ptr
__int64 *pr // データの右側Ptr
){
__int64 *pi; // 内部Ptr: 左
__int64 *pj; // 内部Ptr: 右
__int64 key; // 中央の値
__int64 w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(__int64) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_int64_1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_int64_1( pi, pr ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_int64_1();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「__int64」は、8バイト整数型「__int64型」データを意味
します!
「1」は、降順にソートする事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_int64_1();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_int64_1()」の【仮引数】
void CopyClear::sort_int64_1(
__int64 *pl, // データの左側Ptr
__int64 *pr // データの右側Ptr
){
「__int64* pl,」は、データ配列左端「l=left省略」
「__int64* pr」は、データ配列右端「r=right省略」
(D)関数「sort_int64_1()」の【アルゴリズム】
){
__int64 *pi; // 内部Ptr: 左
__int64 *pj; // 内部Ptr: 右
__int64 key; // 中央の値
__int64 w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(__int64) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_int64_1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_int64_1( pi, pr ); // この間をソート
} //
}
(D-1)ローカル変数
){
__int64 *pi; // 内部Ptr: 左
__int64 *pj; // 内部Ptr: 右
__int64 key; // 中央の値
__int64 w; // 交換用の場所
「__int64* pi;」は、内部ポインタ(左側用)
「__int64* pj;」は、内部ポインタ(右側用)
「__int64 key;」は、中央の値(キー比較用)
「__int64 w;」は、データ交換用の場所
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(__int64) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_int64_1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_int64_1( pi, pr ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(__int64)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、
比較用の値越え」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値に成るまで繰り
返す」、次の内側ループ
「while(key>*pj){pj--;}」は、「右」側の
値が、比較用の値未満」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;}」は、条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sort_int64_1(pl,pj);}」で再帰呼び出し
を自分自身「sort_int64_1()」関数をサブルーチン関数とし
て条件「pl<pj」=「元々の左側が内部の右側と左右関係が
保たれて居る」なら、再帰呼び出し
「sort_int64_1(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が降順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_int64_1(pi,pr);}」で範囲「piからpr」の
ポインタの示す左右範囲」が降順にソート済みと見なして
処理します!★備考★これが、再帰呼び出しを行う事で
実現する「クイックソート」と呼ばれる通常のデータでは
最速と言われているアルゴリズムですコレは、多くの画像
処理以外のプログラミングで使用されて居ますので数学的
帰納法をアルゴリズムに応用した事を理解して下さい!
C言語的には「再帰呼び出し」との文言で平気で多用しま
す!
(4-15-138)関数「void sort_int64_0_key(
__int64* pl,__int64* pr,
short* plx,short* prx){・・・}」
/************************************************************************/
/***** QUIC-SORT:昇順ソート:キー=64Bit整数、添字=16 *****/
/************************************************************************/
void CopyClear::sort_int64_0_key(
__int64 *pl, // KeyDataの左側Ptr
__int64 *pr, // KeyDataの右側Ptr
short *plx, // 添字Data左側Ptr
short *prx // 添字Data右側Ptr
){
__int64 *pi; // 内部KeyPtr: 左
__int64 *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
__int64 key; // 中央の値
__int64 w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(__int64) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_int64_0_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_int64_0_key( pi, pr, pix, prx ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_int64_0_key();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「__int64」は、8バイト整数型「__int64型」データを意味
します!
「0」は、昇順にソートする事を意味します!
「key」は、キー付きを意味し、連動して連動配列も中身の
入れ替えを行う事を意味します!
この関数は、データ配列を昇順≪小さい方から大きい方へ
整列≫にソートする関数でインデックス配列も連動して作成
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_int64_0_key();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_int64_0_key()」の【仮引数】
void CopyClear::sort_int64_0_key(
__int64 *pl, // KeyDataの左側Ptr
__int64 *pr, // KeyDataの右側Ptr
short *plx, // 添字Data左側Ptr
short *prx // 添字Data右側Ptr
){
「__int64* pl,」は、データ配列左端「l=left省略」
「__int64* pr」は、データ配列右端「r=right省略」
「short* plx,」は、連動配列配列左端
「short* prx」は、連動配列配列左端
★備考★上記「__int64* pl,__int64* pr」をソート対象キー配列
として、ここ「short* plx,short* prx」は、連動して入れ
替えられる配列
(D)関数「sort_int64_0_key()」の【アルゴリズム】
){
__int64 *pi; // 内部KeyPtr: 左
__int64 *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
__int64 key; // 中央の値
__int64 w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(__int64) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_int64_0_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_int64_0_key( pi, pr, pix, prx ); // この間をソート
} //
}
(D-1)ローカル変数
){
__int64 *pi; // 内部KeyPtr: 左
__int64 *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
__int64 key; // 中央の値
__int64 w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
「__int64* pi;」は、内部ポインタ(左側用)キー
「__int64* pj;」は、内部ポインタ(右側用)キー
「short* pix;」は、内部ポインタ(左側用)連動
「short* pjx;」は、内部ポインタ(右側用)連動
「__int64 key;」は、中央の値(キー比較用)
「__int64 w;」は、データ交換用の場所
「short wx;」は、データ交換用の場所連動
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(__int64) ) ); // セット
do{ // 以下繰り返し
while( *pi < key ){ // 左側が小さい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key < *pj ){ // 右側が大きい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_int64_0_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_int64_0_key( pi, pr, pix, prx ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「pix=plx;pjx=prx;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(__int64)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;pix++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、比較用の値未満
」の間「pi++;pix++;」ポインタを右側に移動を繰り返すと
即ち、「左側がキーの値以上に成るまで繰り返す」、
次の内側ループ
「while(key<*pj){pj--;pjx--;}」は、「右」側の値が、
比較用の値越え」の間「pj--;pjx--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、
そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;wx=*pix;
*pix=*pjx;*pjx=wx;pix++;pjx--;
wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして連動配列の入れ替えとして
「wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;」と配列入れ
替えを行い!「do構文」を終えると!
そして「if(pl<pj){sort_int64_0_key(pl,pj,plx,pjx);}」
で再帰呼び出しを自分自身「sort_int64_0_key()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sort_int64_0_key(pl,pj,plx,pjx);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_int64_0_key(pi,pr,pix,prx);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!
(4-15-139)関数「void sort_int64_1_key(
__int64* pl,__int64* pr,
short* plx,short* prx){・・・}」
/************************************************************************/
/***** QUIC-SORT:降順ソート:キー=64Bit整数、添字1=16 *****/
/************************************************************************/
void CopyClear::sort_int64_1_key(
__int64 *pl, // KeyDataの左側Ptr
__int64 *pr, // KeyDataの右側Ptr
short *plx, // 添字Data左側Ptr
short *prx // 添字Data右側Ptr
){
__int64 *pi; // 内部KeyPtr: 左
__int64 *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
__int64 key; // 中央の値
__int64 w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(__int64) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_int64_1_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_int64_1_key( pi, pr, pix, prx ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sort_int64_1_key();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
「__int64」は、8バイト整数型「__int64型」データを意味
します!
「1」は、降順にソートする事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数
「key」は、キー付きを意味し、連動して連動配列も中身の
入れ替えを行う事を意味します!
この関数は、データ配列を降順≪大きい方からへ小さい方に
整列≫にソートする関数でインデックス配列も連動して作成
★備考★「_」で区切って居るのは、極初期に作成された
ので区切りに「_」を使用するか、単語先頭「英大文字」と
色々迷って居た時期です!
(B)関数「void sort_int64_1_key();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sort_int64_1_key()」の【仮引数】
void CopyClear::sort_int64_1_key(
__int64 *pl, // KeyDataの左側Ptr
__int64 *pr, // KeyDataの右側Ptr
short *plx, // 添字Data左側Ptr
short *prx // 添字Data右側Ptr
){
「__int64* pl,」は、データ配列左端「l=left省略」
「__int64* pr」は、データ配列右端「r=right省略」
「short* plx,」は、連動配列配列左端
「short* prx」は、連動配列配列左端
★備考★上記「__int64* pl,__int64* pr」をソート対象キー配列
として、ここ「short* plx,short* prx」は、連動して入れ
替えられる配列
(D)関数「sort_int64_1_key()」の【アルゴリズム】
){
__int64 *pi; // 内部KeyPtr: 左
__int64 *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
__int64 key; // 中央の値
__int64 w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(__int64) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_int64_1_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_int64_1_key( pi, pr, pix, prx ); // この間をソート
} //
}
(D-1)ローカル変数
){
__int64 *pi; // 内部KeyPtr: 左
__int64 *pj; // 内部KeyPtr: 右
short *pix; // 内部添字Ptr:左
short *pjx; // 内部添字Ptr:右
__int64 key; // 中央の値
__int64 w; // 交換用の場所:キー
short wx; // 交換用の場所:添字
「__int64* pi;」は、内部ポインタ(左側用)キー
「__int64* pj;」は、内部ポインタ(右側用)キー
「short* pix;」は、内部ポインタ(左側用)連動
「short* pjx;」は、内部ポインタ(右側用)連動
「__int64 key;」は、中央の値(キー比較用)
「__int64 w;」は、データ交換用の場所
「short wx;」は、データ交換用の場所連動
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
pix = plx; // 添字左側をSet
pjx = prx; // 添字右側をSet
key = *( pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(__int64) ) ); // セット
do{ // 以下繰り返し
while( *pi > key ){ // 左側が大きい間
pi++; // 左側を中に進める
pix++; // 添字部も進める
} //
while( key > *pj ){ // 右側が小さい間
pj--; // 右側を中に進める
pjx--; // 添字部も進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
wx = *pix; // 左右の添字データ
*pix = *pjx; // を交換
*pjx = wx; // し
pix++; // 左側を中に進める
pjx--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sort_int64_1_key( pl, pj, plx, pjx ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sort_int64_1_key( pi, pr, pix, prx ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「pix=plx;pjx=prx;」は、ローカルな左側・右側をセット
「key=*(pi+((int)pj-(int)pi)/(2*sizeof(__int64)))」は、
左右の中央の場所(ポインタの中央)の値を取り出す!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;pix++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、比較用の値未満
」の間「pi++;pix++;」ポインタを右側に移動を繰り返すと
即ち、「左側がキーの値以上に成るまで繰り返す」、
次の内側ループ
「while(key>*pj){pj--;pjx--;}」は、「右」側の値が、
比較用の値未満」の間「pj--;pjx--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成る
まで繰り返す」、
そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;
pj--;wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;wx=*pix;
*pix=*pjx;*pjx=wx;pix++;pjx--;
wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして連動配列の入れ替えとして
「wx=*pix;*pix=*pjx;*pjx=wx;pix++;pjx--;」と配列入れ
替えを行い!「do構文」を終えると!
そして「if(pl<pj){sort_int64_1_key(pl,pj,plx,pjx);}」
で再帰呼び出しを自分自身「sort_int64_1_key()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sort_int64_1_key(pl,pj,plx,pjx);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が降順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sort_int64_1_key(pi,pr,pix,prx);}」で範囲
「piからpr」のポインタの示す左右範囲」が降順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!
(4-15-140)関数「void sortTypeCorr0(
TypeCorr* pl,TypeCorr* pr){・・・}」
/************************************************************************/
/***** QUIC-SORT:昇順ソート:データ=TypeCorr *****/
/************************************************************************/
void CopyClear::sortTypeCorr0(
TypeCorr *pl, // データの左側Ptr
TypeCorr *pr // データの右側Ptr
){
TypeCorr *p; // 内部Ptr:中央
TypeCorr *pi; // 内部Ptr: 左
TypeCorr *pj; // 内部Ptr: 右
double key; // 中央の値
TypeCorr w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
p = pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeCorr) ); // セット
key = p->d; // 相関値部を取り出す
do{ // 以下繰り返し
while( pi->d < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < pj->d ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sortTypeCorr0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sortTypeCorr0( pi, pr ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sortTypeCorr0();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
★注意★構造体「TypeCorr」は、相関値関連です!この
データは、相関値の値でソーティングします!
「0」は、データ配列を昇順≪小さい方から大きい方へ整列
≫にソートする関数を意味!
この関数は、相関値の値でデータ配列を昇順≪小さい方から
大きい方へ整列≫にソートする関数
(B)関数「void sortTypeCorr0();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sortTypeCorr0()」の【仮引数】
void CopyClear::sortTypeCorr0(
TypeCorr *pl, // データの左側Ptr
TypeCorr *pr // データの右側Ptr
){
「TypeCorr* pl,」は、データ配列左端「l=left省略」
「TypeCorr* pr」は、データ配列右端「r=right省略」
ここで使用する専用の型「TypeCorr」≪
解説『解説クラスSupport』の「(2-6)
相関値+座標」で解説≫
(D)関数「sortTypeCorr0()」の【アルゴリズム】
){
TypeCorr *p; // 内部Ptr:中央
TypeCorr *pi; // 内部Ptr: 左
TypeCorr *pj; // 内部Ptr: 右
double key; // 中央の値
TypeCorr w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
p = pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeCorr) ); // セット
key = p->d; // 相関値部を取り出す
do{ // 以下繰り返し
while( pi->d < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < pj->d ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sortTypeCorr0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sortTypeCorr0( pi, pr ); // この間をソート
} //
}
(D-1)ローカル変数
){
TypeCorr *p; // 内部Ptr:中央
TypeCorr *pi; // 内部Ptr: 左
TypeCorr *pj; // 内部Ptr: 右
double key; // 中央の値
TypeCorr w; // 交換用の場所
「TypeCorr* p;」は、内部ポインタ(中央用)
「TypeCorr* pi;」は、内部ポインタ(左側用)
「TypeCorr* pj;」は、内部ポインタ(右側用)
「double key;」は、中央の値(キー比較用)
「TypeCorr w;」は、データ交換用の場所
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
p = pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeCorr) ); // セット
key = p->d; // 相関値部を取り出す
do{ // 以下繰り返し
while( pi->d < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < pj->d ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sortTypeCorr0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sortTypeCorr0( pi, pr ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「p=pi+((int)pj-(int)pi)/(2*sizeof(TypeCorr));」は、
ローカルなデータ配列の中央へのポインタをセット
「key=p->d;」は、左右の中央の場所のキー値「p->d」、
詰り相関値を取り出す!★備考★他の関数では中央値への
ポインタを算出せずに直接、キーデータを取り出して居ます
が、「TypeCorr」と正規相関(XY座標と相関値)の
メンバーとして相関値を使用するので理解し易い様に中央
ポインタを先ず作成してから、メンバーの相関値を取り出す
事にしました!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(pi->d<key){pi++;}」は、while構文で
ループ条件「pi->d<key」は、「左側のキーの値が、
比較用の値未満」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以上に成るまで繰り
返す」、次の内側ループ
「while(key<pj->d){pj--;}」は、「右」側のキーの
値が、比較用の値越え」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず、
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sortTypeCorr0(pl,pj);}」で再帰呼び
出しを自分自身「sortTypeCorr0()」関数をサブルーチン
関数として行い!
条件「pl<pj」=「元々の左側が内部の右側と左右関係が保
たれて居る」なら、再帰呼び出し「sortTypeCorr0(pl,pj);」を
行う事で数学の「帰納的定義法」と考えて再帰呼び出しを
行った部分「plからpjのポインタの示す左右範囲」が昇順に
ソート済みと見なして処理する方法です!★備考★これが
再帰呼び出しを行う事で実現する「クイックソート」と呼ば
れる通常のデータでは最速と言われているアルゴリズムです
同じ様に「if(pi<pr){sortTypeCorr0(pi,pr);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順に
ソート済みと見なして処理します!★備考★これが、
再帰呼び出しを行う事で実現する「クイックソート」と呼ば
れる通常のデータでは最速と言われているアルゴリズムです
コレは、多くの画像処理以外のプログラミングで使用されて
居ますので数学的帰納法をアルゴリズムに応用した事を理解
して下さい!C言語的には「再帰呼び出し」との文言で平気
で多用します!
(4-15-141)関数「void sortTypeCorr1(
TypeCorr* pl,TypeCorr* pr){・・・}」
/************************************************************************/
/***** QUIC-SORT:降順ソート:データ=TypeCorr *****/
/************************************************************************/
void CopyClear::sortTypeCorr1(
TypeCorr *pl, // データの左側Ptr
TypeCorr *pr // データの右側Ptr
){
TypeCorr *p; // 内部Ptr:中央
TypeCorr *pi; // 内部Ptr: 左
TypeCorr *pj; // 内部Ptr: 右
double key; // 中央の値
TypeCorr w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
p = pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeCorr) ); // セット
key = p->d; // 相関値部を取り出す
do{ // 以下繰り返し
while( pi->d > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > pj->d ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sortTypeCorr1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sortTypeCorr1( pi, pr ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sortTypeCorr1();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
★注意★構造体「TypeCorr」は、相関値関連です!この
データは、相関値の値でソーティングします!
「1」は、データ配列を相関値の値でデータ配列を降順≪
大きい方から小さい方へ整列≫にソートする関数
(B)関数「void sortTypeCorr1();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sortTypeCorr1()」の【仮引数】
void CopyClear::sortTypeCorr1(
TypeCorr *pl, // データの左側Ptr
TypeCorr *pr // データの右側Ptr
){
「TypeCorr* pl,」は、データ配列左端「l=left省略」
「TypeCorr* pr」は、データ配列右端「r=right省略」
ここで使用する専用の型「TypeCorr」≪
解説『解説クラスSupport』の「(2-6)
相関値+座標」で解説≫
(D)関数「sortTypeCorr1()」の【アルゴリズム】
){
TypeCorr *p; // 内部Ptr:中央
TypeCorr *pi; // 内部Ptr: 左
TypeCorr *pj; // 内部Ptr: 右
double key; // 中央の値
TypeCorr w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
p = pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeCorr) ); // セット
key = p->d; // 相関値部を取り出す
do{ // 以下繰り返し
while( pi->d > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > pj->d ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sortTypeCorr1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sortTypeCorr1( pi, pr ); // この間をソート
} //
}
(D-1)ローカル変数
){
TypeCorr *p; // 内部Ptr:中央
TypeCorr *pi; // 内部Ptr: 左
TypeCorr *pj; // 内部Ptr: 右
double key; // 中央の値
TypeCorr w; // 交換用の場所
「TypeCorr* p;」は、内部ポインタ(中央用)
「TypeCorr* pi;」は、内部ポインタ(左側用)
「TypeCorr* pj;」は、内部ポインタ(右側用)
「double key;」は、中央の値(キー比較用)
「TypeCorr w;」は、データ交換用の場所
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
p = pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeCorr) ); // セット
key = p->d; // 相関値部を取り出す
do{ // 以下繰り返し
while( pi->d > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > pj->d ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sortTypeCorr1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sortTypeCorr1( pi, pr ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「p=pi+((int)pj-(int)pi)/(2*sizeof(TypeCorr));」は、
ローカルなデータ配列の中央へのポインタをセット
「key=p->d;」は、左右の中央の場所のキー値「p->d」、
詰り相関値を取り出す!★備考★他の関数では中央値への
ポインタを算出せずに直接、キーデータを取り出して居ます
が、「TypeCorr」と正規相関(XY座標と相関値)の
メンバーとして相関値を使用するので理解し易い様に中央
ポインタを先ず作成してから、メンバーの相関値を取り出す
事にしました!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(pi->d>key){pi++;}」は、while構文で
ループ条件「pi->d>key」は、「左側のキーの値が、
比較用の値越え」の間「pi++;」ポインタを右側に移動を
繰り返すと、即ち、「左側がキーの値以下に成るまで繰り
返す」、次の内側ループ
「while(key>pj->d){pj--;}」は、「右」側のキーの
値が、比較用の値未満」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成るまで
繰り返す」、そしてif構文
「if(pi>=pj){w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」は、
条件「pi>=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず、
「w=*pi;*pi=*pj;*pj=w;」で左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
そして「if(pl<pj){sortTypeCorr0(pl,pj);}」で再帰呼び
出しを自分自身「sortTypeCorr0()」関数をサブルーチン
関数として行い!
条件「pl<pj」=「元々の左側が内部の右側と左右関係が保
たれて居る」なら、再帰呼び出し「sortTypeCorr0(pl,pj);」
を行う事で数学の「帰納的定義法」と考えて再帰呼び出しを
行った部分「plからpjのポインタの示す左右範囲」が昇順に
ソート済みと見なして処理する方法です!★備考★これが
再帰呼び出しを行う事で実現する「クイックソート」と呼ば
れる通常のデータでは最速と言われているアルゴリズムです
同じ様に「if(pi<pr){sortTypeCorr0(pi,pr);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順に
ソート済みと見なして処理します!★備考★これが、
再帰呼び出しを行う事で実現する「クイックソート」と呼ば
れる通常のデータでは最速と言われているアルゴリズムです
コレは、多くの画像処理以外のプログラミングで使用されて
居ますので数学的帰納法をアルゴリズムに応用した事を理解
して下さい!C言語的には「再帰呼び出し」との文言で平気
で多用します!
(4-15-142)関数「void sortTypeCorrIX0(
TypeCorrIX* pl,
TypeCorrIX* pr,short* plx,
short* prx){・・・}」
/************************************************************************/
/***** QUIC-SORT:昇順ソート:データ=TypeCorrIX *****/
/************************************************************************/
void CopyClear::sortTypeCorrIX0(
TypeCorrIX *pl, // データの左側Ptr
TypeCorrIX *pr // データの右側Ptr
){
TypeCorrIX *p; // 内部Ptr:中央
TypeCorrIX *pi; // 内部Ptr: 左
TypeCorrIX *pj; // 内部Ptr: 右
double key; // 中央の値
TypeCorrIX w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
p = pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeCorrIX) ); // セット
key = p->d; // 相関値部を取り出す
do{ // 以下繰り返し
while( pi->d < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < pj->d ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sortTypeCorrIX0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sortTypeCorrIX0( pi, pr ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sortTypeCorrIX0();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
★注意★構造体「TypeCorrIX」は、相関値関連です!
このデータは、相関値の値でソーティングします!
「0」は、データ配列を昇順≪小さい方から大きい方へ整列
≫にソートする関数を意味!
この関数は、相関値の値でデータ配列を昇順≪小さい方から
大きい方へ整列≫にソートする関数で型「TypeCorrIX」内部
にメンバー変数として連動配列へのインデックス内蔵!
「_0」は、昇順にソートする事を意味します!
(B)関数「void sortTypeCorrIX0();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sortTypeCorrIX0()」の【仮引数】
void CopyClear::sortTypeCorrIX0(
TypeCorrIX *pl, // データの左側Ptr
TypeCorrIX *pr // データの右側Ptr
){
「TypeCorrIX* pl,」は、データ配列左端「l=left省略」
「TypeCorrIX* pr」は、データ配列右端「r=right省略」
ここで使用する専用の型「TypeCorrIX」≪
解説『解説クラスSupport』の「(2-6)
相関値+座標」で解説≫
(D)関数「sortTypeCorrIX0()」の【アルゴリズム】
){
TypeCorrIX *p; // 内部Ptr:中央
TypeCorrIX *pi; // 内部Ptr: 左
TypeCorrIX *pj; // 内部Ptr: 右
double key; // 中央の値
TypeCorrIX w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
p = pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeCorrIX) ); // セット
key = p->d; // 相関値部を取り出す
do{ // 以下繰り返し
while( pi->d < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < pj->d ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sortTypeCorrIX0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sortTypeCorrIX0( pi, pr ); // この間をソート
} //
}
(D-1)ローカル変数
){
TypeCorrIX *p; // 内部Ptr:中央
TypeCorrIX *pi; // 内部Ptr: 左
TypeCorrIX *pj; // 内部Ptr: 右
double key; // 中央の値
TypeCorrIX w; // 交換用の場所
「TypeCorrIX* p;」は、内部ポインタ(中央用)
「TypeCorrIX* pi;」は、内部ポインタ(左側用)
「TypeCorrIX* pj;」は、内部ポインタ(右側用)
「double key;」は、中央の値(キー比較用)
「TypeCorrIX w;」は、データ交換用の場所
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
p = pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeCorrIX) ); // セット
key = p->d; // 相関値部を取り出す
do{ // 以下繰り返し
while( pi->d < key ){ // 左側が小さい間
pi++; // 左側を中に進める
} //
while( key < pj->d ){ // 右側が大きい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sortTypeCorrIX0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sortTypeCorrIX0( pi, pr ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「p=pi+((int)pj-(int)pi)/(2*sizeof(TypeCorrIX));」は、
ローカルなデータ配列の中央へのポインタをセット
「key=p->d;」は、左右の中央の場所のキー値「p->d」、
詰り相関値を取り出す!★備考★他の関数では中央値への
ポインタを算出せずに直接、キーデータを取り出して居ます
が、「TypeCorrIX」と正規相関(XY座標と相関値)の
メンバーとして相関値を使用するので理解し易い様に中央
ポインタを先ず作成してから、メンバーの相関値を取り出す
事にしました!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi<key){pi++;}」は、while構文で
ループ条件「*pi<key」は、「左側の値が、比較用の値未満
」の間「pi++;」ポインタを右側に移動を繰り返すと
即ち、「左側がキーの値以上に成るまで繰り返す」、
次の内側ループ
「while(key<*pj){pj--;}」は、「右」側の値が、
比較用の値越え」の間「pj--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以下に成るまで
繰り返す」、
そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
★備考★連動配列インデックスは「TypeCorrIX型」の
メンバー変数として内蔵されて居るのでアルゴリズム的に
入れ替える処理が無い事に留意!
「do構文」を終えると!
そして「if(pl<pj){sortTypeCorrIX0(pl,pj);}」
で再帰呼び出しを自分自身「sortTypeCorrIX0()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sortTypeCorrIX0(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sortTypeCorrIX0(pi,pr);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!
★★特注「note編集機能不具合」★★
「key=(pi+((int)pj-(int)pi)/(2*sizeof(TypeCorrIX)))」
とコピペでテキストを記載したら、
「key=(pi+((int)pj-(int)pi)/(2sizeof(TypeCorrIX)))」
等と主に「*」が消える事が多々ありますので注意して手作業
で修正して居るが、全て修正出来て無い部分が有る事に留意
して読んで頂きたい!必ず、【<>code】機能で生の
テキストを必ず参考にして下さい!!
(4-15-143)関数「void sortTypeCorrIX1(
TypeCorrIX* pl,
TypeCorrIX* pr,short* plx,
short* prx){・・・}」
/************************************************************************/
/***** QUIC-SORT:降順ソート:データ=TypeCorrIX *****/
/************************************************************************/
void CopyClear::sortTypeCorrIX1(
TypeCorrIX *pl, // データの左側Ptr
TypeCorrIX *pr // データの右側Ptr
){
TypeCorrIX *p; // 内部Ptr:中央
TypeCorrIX *pi; // 内部Ptr: 左
TypeCorrIX *pj; // 内部Ptr: 右
double key; // 中央の値
TypeCorrIX w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
p = pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeCorrIX) ); // セット
key = p->d; // 相関値部を取り出す
do{ // 以下繰り返し
while( pi->d > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > pj->d ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sortTypeCorrIX1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sortTypeCorrIX1( pi, pr ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sortTypeCorrIX1();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
★注意★構造体「TypeCorrIX」は、相関値関連です!
このデータは、相関値の値でソーティングします!
「1」は、データ配列を降順≪大きい方から小さい方へ整列
≫にソートする関数を意味!
この関数は、相関値の値でデータ配列を降順≪大きい方から
小さい方へ整列≫にソートする関数で型「TypeCorrIX」内部
にメンバー変数として連動配列へのインデックス内蔵!
(B)関数「void sortTypeCorrIX1();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sortTypeCorrIX1()」の【仮引数】
void CopyClear::sortTypeCorrIX1(
TypeCorrIX *pl, // データの左側Ptr
TypeCorrIX *pr // データの右側Ptr
){
「TypeCorrIX* pl,」は、データ配列左端「l=left省略」
「TypeCorrIX* pr」は、データ配列右端「r=right省略」
ここで使用する専用の型「TypeCorr」≪
解説『解説クラスSupport』の「(2-6)
相関値+座標」で解説≫
(D)関数「sortTypeCorrIX1()」の【アルゴリズム】
){
TypeCorrIX *p; // 内部Ptr:中央
TypeCorrIX *pi; // 内部Ptr: 左
TypeCorrIX *pj; // 内部Ptr: 右
double key; // 中央の値
TypeCorrIX w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
p = pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeCorrIX) ); // セット
key = p->d; // 相関値部を取り出す
do{ // 以下繰り返し
while( pi->d > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > pj->d ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sortTypeCorrIX1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sortTypeCorrIX1( pi, pr ); // この間をソート
} //
}
(D-1)ローカル変数
){
TypeCorrIX *p; // 内部Ptr:中央
TypeCorrIX *pi; // 内部Ptr: 左
TypeCorrIX *pj; // 内部Ptr: 右
double key; // 中央の値
TypeCorrIX w; // 交換用の場所
「TypeCorrIX* p;」は、内部ポインタ(中央用)
「TypeCorrIX* pi;」は、内部ポインタ(左側用)
「TypeCorrIX* pj;」は、内部ポインタ(右側用)
「double key;」は、中央の値(キー比較用)
「TypeCorrIX w;」は、データ交換用の場所
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
p = pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeCorrIX) ); // セット
key = p->d; // 相関値部を取り出す
do{ // 以下繰り返し
while( pi->d > key ){ // 左側が大きい間
pi++; // 左側を中に進める
} //
while( key > pj->d ){ // 右側が小さい間
pj--; // 右側を中に進める
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sortTypeCorrIX1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sortTypeCorrIX1( pi, pr ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「p=pi+((int)pj-(int)pi)/(2*sizeof(TypeCorrIX));」は、
ローカルなデータ配列の中央へのポインタをセット
「key=p->d;」は、左右の中央の場所のキー値「p->d」、
詰り相関値を取り出す!★備考★他の関数では中央値への
ポインタを算出せずに直接、キーデータを取り出して居ます
が、「TypeCorrIX」と正規相関(XY座標と相関値)の
メンバーとして相関値を使用するので理解し易い様に中央
ポインタを先ず作成してから、メンバーの相関値を取り出す
事にしました!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「while(*pi>key){pi++;pix++;}」は、while構文で
ループ条件「*pi>key」は、「左側の値が、比較用の値越え
」の間「pi++;pix++;」ポインタを右側に移動を繰り返すと
即ち、「左側がキーの値以下に成るまで繰り返す」、
次の内側ループ
「while(key>*pj){pj--;pjx--;}」は、「右」側の値が、
比較用の値未満」の間「pj--;pjx--;」ポインタを左側に
移動を繰り返すと、即ち、「右側がキーの値以上に成るまで
繰り返す」、
そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
★備考★連動配列インデックスは「TypeCorrIX型」の
メンバー変数として内蔵されて居るのでアルゴリズム的に
入れ替える処理が無い事に留意!
「do構文」を終えると!
そして「if(pl<pj){sortTypeCorrIX1(pl,pj);}」
で再帰呼び出しを自分自身「sortTypeCorrIX1()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sortTypeCorrIX1(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sortTypeCorrIX1(pi,pr);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!
(4-15-144)関数「void sortXTypeXY0(TypeXY* pl,
TypeXY* pr){・・・}」
/************************************************************************/
/***** QUIC-SORT:昇順ソート:データ=TypeXYでX座標 *****/
/***** 昇順ソート(X→Y) *****/
/************************************************************************/
void CopyClear::sortXTypeXY0(
TypeXY *pl, // データの左側Ptr
TypeXY *pr // データの右側Ptr
){
TypeXY *p; // 内部Ptr:中央
TypeXY *pi; // 内部Ptr: 左
TypeXY *pj; // 内部Ptr: 右
int keyX; // 中央の値:X
int keyY; // 中央の値:Y
TypeXY w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
p = pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeXY) ); // セット
keyX = p->x; // X座標を取り出す
keyY = p->y; // Y座標を取り出す
do{ // 以下繰り返し
for(;;){ // 以下繰り返し:内側
if( pi->x < keyX ){ // 左側が小さい間:X
pi++; // 左側を中に進める
}else if( pi->x == keyX ){ // X座標同値なら
if( pi->y < keyY ){ // 左側が小さい間:Y
pi++; // 左側を中に進める
}else{ // 大きい場合:Y
break; // 内側Loop終了
} //
}else{ // 大きい場合:X
break; // 内側Loop終了
} //
} //
for(;;){ // 以下繰り返し:内側
if( keyX < pj->x ){ // 右側が大きい間:X
pj--; // 右側を中に進める
}else if( keyX == pj->x ){ // X座標同値なら
if( keyY < pj->y ){ // 右側が大きい間:Y
pj--; // 右側を中に進める
}else{ // 小さい場合:Y
break; // 内側Loop終了
} //
}else{ // 小さい場合:X
break; // 内側Loop終了
} //
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sortXTypeXY0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sortXTypeXY0( pi, pr ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sortXTypeXY0();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
★注意★構造体「TypeXY」は、XY座標関連です!
このデータは、XY座標の値でソーティングします!
「0」は、データ配列を昇順≪小さい方から大きい方へ整列
≫にソートする関数を意味!
この関数は、XY座標の値でデータ配列を昇順≪小さい方
から大きい方へ整列≫にソートする関数です!ここでの座標
比較は、X座標の大小を元に比較し、比較時にX座標が同値
ならば、Y座標の大小を比較します!
(B)関数「void sortXTypeXY0();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sortXTypeXY0()」の【仮引数】
void CopyClear::sortXTypeXY0(
TypeXY *pl, // データの左側Ptr
TypeXY *pr // データの右側Ptr
){
「TypeXY* pl,」は、データ配列左端「l=left省略」
「TypeXY* pr」は、データ配列右端「r=right省略」
ここで使用する専用の型「TypeXY」≪
解説『解説クラスSupport』の(2-1)
座標組用データ構造「座標」で解説≫
(D)関数「sortXTypeXY0()」の【アルゴリズム】
){
TypeXY *p; // 内部Ptr:中央
TypeXY *pi; // 内部Ptr: 左
TypeXY *pj; // 内部Ptr: 右
int keyX; // 中央の値:X
int keyY; // 中央の値:Y
TypeXY w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
p = pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeXY) ); // セット
keyX = p->x; // X座標を取り出す
keyY = p->y; // Y座標を取り出す
do{ // 以下繰り返し
for(;;){ // 以下繰り返し:内側
if( pi->x < keyX ){ // 左側が小さい間:X
pi++; // 左側を中に進める
}else if( pi->x == keyX ){ // X座標同値なら
if( pi->y < keyY ){ // 左側が小さい間:Y
pi++; // 左側を中に進める
}else{ // 大きい場合:Y
break; // 内側Loop終了
} //
}else{ // 大きい場合:X
break; // 内側Loop終了
} //
} //
for(;;){ // 以下繰り返し:内側
if( keyX < pj->x ){ // 右側が大きい間:X
pj--; // 右側を中に進める
}else if( keyX == pj->x ){ // X座標同値なら
if( keyY < pj->y ){ // 右側が大きい間:Y
pj--; // 右側を中に進める
}else{ // 小さい場合:Y
break; // 内側Loop終了
} //
}else{ // 小さい場合:X
break; // 内側Loop終了
} //
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sortXTypeXY0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sortXTypeXY0( pi, pr ); // この間をソート
} //
}
(D-1)ローカル変数
){
TypeXY *p; // 内部Ptr:中央
TypeXY *pi; // 内部Ptr: 左
TypeXY *pj; // 内部Ptr: 右
int keyX; // 中央の値:X
int keyY; // 中央の値:Y
TypeXY w; // 交換用の場所
「TypeXY* p;」は、内部ポインタ(中央用)
「TypeXY* pi;」は、内部ポインタ(左側用)
「TypeXY* pj;」は、内部ポインタ(右側用)
「int keyX;」は、中央の値(キー比較用のX座標)
「int keyY;」は、中央の値(キー比較用のY座標)
「TypeXY w;」は、データ交換用の場所
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
p = pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeXY) ); // セット
keyX = p->x; // X座標を取り出す
keyY = p->y; // Y座標を取り出す
do{ // 以下繰り返し
for(;;){ // 以下繰り返し:内側
if( pi->x < keyX ){ // 左側が小さい間:X
pi++; // 左側を中に進める
}else if( pi->x == keyX ){ // X座標同値なら
if( pi->y < keyY ){ // 左側が小さい間:Y
pi++; // 左側を中に進める
}else{ // 大きい場合:Y
break; // 内側Loop終了
} //
}else{ // 大きい場合:X
break; // 内側Loop終了
} //
} //
for(;;){ // 以下繰り返し:内側
if( keyX < pj->x ){ // 右側が大きい間:X
pj--; // 右側を中に進める
}else if( keyX == pj->x ){ // X座標同値なら
if( keyY < pj->y ){ // 右側が大きい間:Y
pj--; // 右側を中に進める
}else{ // 小さい場合:Y
break; // 内側Loop終了
} //
}else{ // 小さい場合:X
break; // 内側Loop終了
} //
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sortXTypeXY0( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sortXTypeXY0( pi, pr ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「p=pi+((int)pj-(int)pi)/(2*sizeof(TypeXY));」は、
ローカルなデータ配列の中央へのポインタをセット
「keyX=p->x;keyY=p->y;」は、左右の中央の場所の
キー値「p->x」とX座標、「p->y」とY座標、と今回は、
詰りXY座標値を取り出す!★備考★他の関数では中央値
へのポインタを算出せずに直接、キーデータを取り出して
居ますが、「TypeXY」と座標(X座標値Y座標値)のメン
バーとして使用するので理解し易い様に中央ポインタを先ず
作成してから、メンバーの値を取り出す事にしました!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「for(;;){・・無限ループ本体・・}」は、for無限ルー
プ構文「for(;;)」で無限ループ本体で「break;」でループ
から脱出する事でループを構築するが、無限ループ本体は、
先ず、「if(pi->x<keyX){pi++;}」で条件「pi->x<keyX」≪
詰り、左側X座標がキーの値未満≫の間「pi++;」ポインタ
を右側に移動を繰り返す、次に
「else if(pi->x==keyX){if(pi->y<keyY){pi++;}else{
break;}}」と条件「pi->x==keyX」とX座標が同値の時、
「if(pi->y<keyY){pi++;}else{break;}」と、更に条件
「pi->y<keyY」≪詰り、左側Y座標がキーの値未満≫の間
「pi++;」ポインタを右側に移動を繰り返す、そして条件
「pi->y<keyY」が不成立なら「break;」と無限ループ脱出
更に条件「pi->x==keyX」が不成立なら「break;」と無限
ループ脱出、
次の内側ループも「for(;;){・・無限ループ本体・・}」
は、for無限ループ構文「for(;;)」で無限ループ本体で
「break;」でループから脱出する事でループを構築するが、
無限ループ本体は、先ず、「if(keyX<pj->x){pj--;}」で
条件「keyX<pj->x」≪詰り、右側X座標がキーの値未満≫
の間「pj--;」ポインタを左側に移動を繰り返す、次に
「else if(keyX==pj->x){if(keyY<pj->y){pj--;}else{
break;}}」と条件「pi->x==keyX」とX座標が同値の時、
「if(keyY<pj->y){pj--;}else{break;}}」と、更に条件
「keyY<pj->y」≪詰り、右側Y座標がキーの値未満≫の
間「pj--;」ポインタを左側に移動を繰り返す、そして条件
「pi->y<keyY」が不成立なら「break;」と無限ループ脱出
更に条件「keyX==pj->x」が不成立なら「break;」と無限
ループ脱出、★備考★この関数「sortXTypeXY0()」では、
座標の比較をX座標を比較しますが、X座標とキーが同じ
場合は、Y座標で比較する事は理解していますね!
そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
「do構文」を終えると!
そして「if(pl<pj){sortXTypeXY0(pl,pj);}」
で再帰呼び出しを自分自身「sortXTypeXY0()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sortXTypeXY0(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sortXTypeXY0(pi,pr);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!
(4-15-145)関数「void sortXTypeXY1(TypeXY* pl,
TypeXY* pr){・・・}」
/************************************************************************/
/***** QUIC-SORT:降順ソート:データ=TypeXYでX座標 *****/
/***** 降順ソート(X→Y) *****/
/************************************************************************/
void CopyClear::sortXTypeXY1(
TypeXY *pl, // データの左側Ptr
TypeXY *pr // データの右側Ptr
){
TypeXY *p; // 内部Ptr:中央
TypeXY *pi; // 内部Ptr: 左
TypeXY *pj; // 内部Ptr: 右
int keyX; // 中央の値:X
int keyY; // 中央の値:Y
TypeXY w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
p = pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeXY) ); // セット
keyX = p->x; // X座標を取り出す
keyY = p->y; // Y座標を取り出す
do{ // 以下繰り返し
for(;;){ // 以下繰り返し:内側
if( pi->x > keyX ){ // 左側が大きい間:X
pi++; // 左側を中に進める
}else if( pi->x == keyX ){ // X座標同値なら
if( pi->y > keyY ){ // 左側が大きい間:Y
pi++; // 左側を中に進める
}else{ // 小さい場合:Y
break; // 内側Loop終了
} //
}else{ // 小さい場合:X
break; // 内側Loop終了
} //
} //
for(;;){ // 以下繰り返し:内側
if( keyX > pj->x ){ // 右側が小さい間:X
pj--; // 右側を中に進める
}else if( keyX == pj->x ){ // X座標同値なら
if( keyY > pj->y ){ // 右側が小さい間:Y
pj--; // 右側を中に進める
}else{ // 大きい場合:Y
break; // 内側Loop終了
} //
}else{ // 大きい場合:X
break; // 内側Loop終了
} //
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sortXTypeXY1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sortXTypeXY1( pi, pr ); // この間をソート
} //
}
☆備考☆この関数はファイル「CopyClear100.cpp」に存在!
★注意★この関数は「private:属性」ですのでライブラリの
外から使用不能です!
(A)関数「sortXTypeXY1();」の【関数名】
「Sort」は、勿論、英単語「sort」、カタカナ語ソート・
ソーティング、詰り並び替えです!
★注意★構造体「TypeXY」は、XY座標関連です!
このデータは、XY座標の値でソーティングします!
「1」は、データ配列を降順≪大きい方から小さい方へ整列
≫にソートする関数を意味!
この関数は、XY座標の値でデータ配列を降順≪大きい方
から小さい方へ整列≫にソートする関数です!
ここでの座標比較は、X座標の大小を元に比較し、
比較時にX座標が同値ならば、Y座標の大小を比較します!
(B)関数「void sortXTypeXY1();」の【返値】
返値を返さない関数です!
★注意★詰り、実引数の検査を実行時に行いませんので
使用する時は、正しい実引数を記載する必要が有ります!
(C)関数「sortXTypeXY1()」の【仮引数】
void CopyClear::sortXTypeXY1(
TypeXY *pl, // データの左側Ptr
TypeXY *pr // データの右側Ptr
){
「TypeXY* pl,」は、データ配列左端「l=left省略」
「TypeXY* pr」は、データ配列右端「r=right省略」
ここで使用する専用の型「TypeXY」≪
解説『解説クラスSupport』の(2-1)
座標組用データ構造「座標」で解説≫
(D)関数「sortXTypeXY1()」の【アルゴリズム】
){
TypeXY *p; // 内部Ptr:中央
TypeXY *pi; // 内部Ptr: 左
TypeXY *pj; // 内部Ptr: 右
int keyX; // 中央の値:X
int keyY; // 中央の値:Y
TypeXY w; // 交換用の場所
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
p = pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeXY) ); // セット
keyX = p->x; // X座標を取り出す
keyY = p->y; // Y座標を取り出す
do{ // 以下繰り返し
for(;;){ // 以下繰り返し:内側
if( pi->x > keyX ){ // 左側が大きい間:X
pi++; // 左側を中に進める
}else if( pi->x == keyX ){ // X座標同値なら
if( pi->y > keyY ){ // 左側が大きい間:Y
pi++; // 左側を中に進める
}else{ // 小さい場合:Y
break; // 内側Loop終了
} //
}else{ // 小さい場合:X
break; // 内側Loop終了
} //
} //
for(;;){ // 以下繰り返し:内側
if( keyX > pj->x ){ // 右側が小さい間:X
pj--; // 右側を中に進める
}else if( keyX == pj->x ){ // X座標同値なら
if( keyY > pj->y ){ // 右側が小さい間:Y
pj--; // 右側を中に進める
}else{ // 大きい場合:Y
break; // 内側Loop終了
} //
}else{ // 大きい場合:X
break; // 内側Loop終了
} //
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sortXTypeXY1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sortXTypeXY1( pi, pr ); // この間をソート
} //
}
(D-1)ローカル変数
){
TypeXY *p; // 内部Ptr:中央
TypeXY *pi; // 内部Ptr: 左
TypeXY *pj; // 内部Ptr: 右
int keyX; // 中央の値:X
int keyY; // 中央の値:Y
TypeXY w; // 交換用の場所
「TypeXY* p;」は、内部ポインタ(中央用)
「TypeXY* pi;」は、内部ポインタ(左側用)
「TypeXY* pj;」は、内部ポインタ(右側用)
「int keyX;」は、中央の値(キー比較用のX座標)
「int keyY;」は、中央の値(キー比較用のY座標)
「TypeXY w;」は、データ交換用の場所
(D―2)アルゴリズムコード
pi = pl; // KeyDataの左側Set
pj = pr; // KeyDataの右側Set
p = pi + ( (int)pj - (int)pi ) // 右左の中央値を
/ ( 2 * sizeof(TypeXY) ); // セット
keyX = p->x; // X座標を取り出す
keyY = p->y; // Y座標を取り出す
do{ // 以下繰り返し
for(;;){ // 以下繰り返し:内側
if( pi->x > keyX ){ // 左側が大きい間:X
pi++; // 左側を中に進める
}else if( pi->x == keyX ){ // X座標同値なら
if( pi->y > keyY ){ // 左側が大きい間:Y
pi++; // 左側を中に進める
}else{ // 小さい場合:Y
break; // 内側Loop終了
} //
}else{ // 小さい場合:X
break; // 内側Loop終了
} //
} //
for(;;){ // 以下繰り返し:内側
if( keyX > pj->x ){ // 右側が小さい間:X
pj--; // 右側を中に進める
}else if( keyX == pj->x ){ // X座標同値なら
if( keyY > pj->y ){ // 右側が小さい間:Y
pj--; // 右側を中に進める
}else{ // 大きい場合:Y
break; // 内側Loop終了
} //
}else{ // 大きい場合:X
break; // 内側Loop終了
} //
} //
if( pi <= pj ){ // 左 ≦ 右 なら
w = *pi; // 左右のキーデータ
*pi = *pj; // を交換
*pj = w; // し
pi++; // 左側を中に進める
pj--; // 右側を中に進める
} //
}while( pi <= pj ); // 左≦右なら繰返し
if( pl < pj ){ // 外左 < 中右 なら
sortXTypeXY1( pl, pj ); // この間をソート
} //
if( pi < pr ){ // 中左 < 外右 なら
sortXTypeXY1( pi, pr ); // この間をソート
} //
}
「pi=pl;pj=pr;」は、ローカルな左側・右側をセット
「p=pi+((int)pj-(int)pi)/(2*sizeof(TypeXY));」は、
ローカルなデータ配列の中央へのポインタをセット
「keyX=p->x;keyY=p->y;」は、左右の中央の場所の
キー値「p->x」とX座標、「p->y」とY座標、と今回は、
詰りXY座標値を取り出す!★備考★他の関数では中央値
へのポインタを算出せずに直接、キーデータを取り出して
居ますが、「TypeXY」と座標(X座標値Y座標値)のメン
バーとして使用するので理解し易い様に中央ポインタを先ず
作成してから、メンバーの座標値を取り出す事にしました!
二重ループで外側の
do構文「・・外側ループ本体・・}while(pi<=pj);」と
後置ループ条件「pi<=pj」と内部のポインタの左右関係が
保たれている間繰り返す!そして最初の内側のループ
「for(;;){・・無限ループ本体・・}」は、for無限ルー
プ構文「for(;;)」で無限ループ本体で「break;」でループ
から脱出する事でループを構築するが、無限ループ本体は、
先ず、「if(pi->x>keyX){pi++;}」で条件「pi->x>keyX」≪
詰り、左側X座標がキーの値越え≫の間「pi++;」ポインタ
を右側に移動を繰り返す、次に
「else if(pi->x==keyX){if(pi->y>keyY){pi++;}else{
break;}}」と条件「pi->x==keyX」とX座標が同値の時、
「if(pi->y>keyY){pi++;}else{break;}」と、更に条件
「pi->y>keyY」≪詰り、左側Y座標がキーの値越え≫の間
「pi++;」ポインタを右側に移動を繰り返す、そして条件
「pi->y>keyY」が不成立なら「break;」と無限ループ脱出
更に条件「pi->x==keyX」が不成立なら「break;」と無限
ループ脱出、
次の内側ループも「for(;;){・・無限ループ本体・・}」
は、for無限ループ構文「for(;;)」で無限ループ本体で
「break;」でループから脱出する事でループを構築するが、
無限ループ本体は、先ず、「if(keyX<pj->x){pj--;}」で
条件「keyX<pj->x」≪詰り、右側X座標がキーの値未満≫
の間「pj--;」ポインタを左側に移動を繰り返す、次に
「else if(keyX==pj->x){if(keyY<pj->y){pj--;}else{
break;}}」と条件「pi->x==keyX」とX座標が同値の時、
「if(keyY<pj->y){pj--;}else{break;}}」と、更に条件
「keyY<pj->y」≪詰り、右側Y座標がキーの値未満≫の
間「pj--;」ポインタを左側に移動を繰り返す、そして条件
「pi->y>keyY」が不成立なら「break;」と無限ループ脱出
更に条件「keyX==pj->x」が不成立なら「break;」と無限
ループ脱出、★備考★この関数「sortXTypeXY1()」では、
座標の比較をX座標を比較しますが、X座標とキーが同じ
場合は、Y座標で比較する事は理解していますね!
そしてif構文
「if(pi<=pj){w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」は、
条件「pi<=pj」と左右関係が保たれていたら
「w=*pi;*pi=*pj;*pj=w;pi++;pj--;}」で先ず
「w=*pi;*pi=*pj;*pj=w;」でキーデータ左右を入れ替え、
「pi++;pj--;」とローカル左右ポインタを進める!
「do構文」を終えると!
そして「if(pl<pj){sortXTypeXY1(pl,pj);}」
で再帰呼び出しを自分自身「sortXTypeXY1()」関数を
サブルーチン関数として条件「pl<pj」=「元々の左側が
内部の右側と左右関係が保たれて居る」なら、再帰呼び出し
「sortXTypeXY1(pl,pj);」を行う事で数学の
「帰納的定義法」と考えて再帰呼び出しを行った部分
「plからpjのポインタの示す左右範囲」が昇順にソート済
みと見なして処理する方法です!★備考★これが再帰呼び出
しを行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムです同じ様に
「if(pi<pr){sortXTypeXY1(pi,pr);}」で範囲
「piからpr」のポインタの示す左右範囲」が昇順にソート
済みと見なして処理します!★備考★これが、再帰呼び出し
を行う事で実現する「クイックソート」と呼ばれる通常の
データでは最速と言われているアルゴリズムですコレは、
多くの画像処理以外のプログラミングで使用されて居ますの
で数学的帰納法をアルゴリズムに応用した事を理解して下さ
い!C言語的には「再帰呼び出し」との文言で平気で多用し
ます!
★★特注「note編集機能不具合」★★
「p=pi+((int)pj-(int)pi)/(2*sizeof(TypeXY));」と
コピペでテキストを記載したら、
「p=pi+((int)pj-(int)pi)/(2sizeof(TypeXY));」と
等と主に「*」が消える事が多々ありますので注意して手作業
で修正して居るが、全て修正出来て無い部分が有る事に留意
して読んで頂きたい!必ず、【<>code】機能で生の
テキストを必ず参考にして下さい!!
ココまでで区切り≪「private:属性」の関数の並びが、
「sortXTypeXY1()」関数までとソート系「X座標」が終了
したので次から「sortYTypeXY0()」とソート系「Y座標」
関数の説明になるので≫が良いので終わります?!
継続追加は有りません!★備考★
勿論、記載ミスは直して行きますが!
引き続き、
新規解説『解説クラスCopyClear(37)』を
御贔屓下さい!