両変数の値を他の変数で交換しない3つのアルゴリズム

2602 ワード

プログラム言語を学習したり、プログラムを設計したりする時には、2つの変数の値を交換することがよくあります.通常私たちのやり方は、新しい変数を定義し、それによって交換を完了します.コードは以下の通りです
int a,b,t;
a=10; b=15;
t=a; a=b; b=t;
このアルゴリズムは分かりやすく、特に初心者にコンピュータープログラムの特徴を理解するのに適しています.実際のソフトウェア開発において、このアルゴリズムは簡単明瞭で、曖昧さが生じず、プログラマ間のコミュニケーションを容易にし、一般的に変数値を交換する問題にぶつかる場合、このアルゴリズム(以下、標準アルゴリズムという)を採用するべきである.標準アルゴリズムの最大の欠点(欠点とは言えない)は、臨時変数を借りる必要があります.臨時変数を使わずに交換できますか?答えは肯定です.ここでは少なくとも3つのアルゴリズムで実装できます.    1)算術演算    2)ポインタ操作    3)ビット演算    1)算術演算は簡単に言えば、+と−の演算で実現されます.コードは以下の通りです
int a,b;
a=10;b=12;
a=b-a;   //a=2;b=12
b=b-a;   //a=2;b=10
a=b+a;   //a=12;b=10
以上の演算により、aとbの値を交換しました.表面的には簡単に見えますが、特に標準アルゴリズムに慣れてからは容易には思いつきません.このアルゴリズムは標準アルゴリズムと比較して3つの計算のプロセスが多くなりましたが、臨時変数には助けられませんでした.(以下、算術アルゴリズムという.)ポインタ操作は、ポインタの動作を実際に整数演算する.例えば、2つのintポインタが減算されて1つの整数Nが得られ、この整数は、2つのポインタ変数のメモリ内の格納位置がN*sizeof(int)バイトを隔てていることを示している.intポインタと一つの整数を加算します.例えば、「a+10」はaを基本アドレスとし、10*sizeof(int)におけるint変数にオフセットすることを表します.したがって,計算アルゴリズムと同様の演算により,ポインタ変数値の交換を完全に行うことができ,それにより交換変数の目的を達成することができた.すなわち、
int *a,*b;    
a=new int(10);        //     
b=new int(20);        //a=0x00030828,b=0x00030840
a=(int*)(b-a);        //a=0x00000006
b=(int*)(b-int(a));   //b=0x00030828
a=(int*)(b+int(a));   //a=0x00030840
最後の3つの文のうち、1つだけは2つのポインタの間の計算です.他は全部ポインタと整数の計算です.そうでないと計算ミスを招き、システムエラーが深刻になります.以上の演算a、bのアドレスで交換が完了しました.aは元のb方向の値を指しています.bはもとのa方向の値を指します.このアルゴリズムは同様に第3の変数を用いずに値の交換を完了し、算術アルゴリズムと比較すると分かりにくいですが、大きなデータタイプを交換するときに、例えばカスタムの大型構造やクラスのように、演算アルゴリズムよりも速く実行できるという利点があります.交換時のアドレスのため、変数値はメモリ内では移動していません.(以下、アドレスアルゴリズムという)3ビット演算は、異種演算によっても変数の交換が可能です.これは最も不思議なものかもしれません.以下のコードを見てください.
int a=10,b=12;  //a=1010^b=1100;
a=a^b;    //a=0110^b=1100;
b=a^b;    //a=0110^b=1010;
a=a^b;    //a=1100=12;b=1010;
このアルゴリズムは、異形または演算の特徴によって決定され、異形または演算によってデータ中のビットを反転させることができ、他のビットは変更されません.これは、1つの数aと任意の所与の数bとの連続的な異種または2回を意味し、aの値は不変である.a^b^b=aです.a=a^bをb=a^bに代入するとb=a^b^b=aとなります.同じ理屈でa=b^a^a=bを得ることができます.気軽に交換ができます.以上の3つのアルゴリズムは、他の変数の助けを借りずに2つの変数値の交換を行うことができます.比較的に、算術アルゴリズムとビットアルゴリズムは純粋Cでは標準データタイプの交換しかできません.構造体には無力です.また、C++の中でオーバーロード操作が必要であれば、複雑なタイプの交換も可能です.ポインタアルゴリズムは任意のデータ構造の交換を容易に行うことができる.この三つのアルゴリズムを紹介するのは実践に応用するのではなく、技術を探求するために、プログラム設計の魅力を展示するためです.その中から、数学の中のテクニックはプログラム設計にかなりの影響力を持っています.実際のソフトウェア開発から見れば、標準アルゴリズムが一番よく、任意の種類の交換問題を解決できます.