ジェネリック
魯迅
様々な機能におけるアルゴリズムのC ++標準ライブラリには、強力な適用性を持っています。一例のためのstd::sort
機能、すなわち、それはできstd::vector
素子の一種であり、することが可能であるstd::deque
配列の要素のために、それはまた、正常に動作することができ、要素を並べ替えます。一方、std::sort
関数はまた、照合を指定するための関数ポインタ(述部)を受け入れることができます。この記事では、標準ライブラリのシミュレートされますstd::sort
、機能をその同じインタフェースのソート関数を書きます。
ここではマージソート方法をされて仕分け、主なアイデアは、長い方ソート順にソート2の短い配列にあります。一般に、配列は、二つの短いシーケンスがソート機能をマージ必要とする、無秩序です。シーケンスは一つだけの要素であるならば、それは、再帰端を注文する必要があります。図は、可動は、以下を示し:(可動図をインターネットから)
以下を参照してくださいstd::sort
インターフェイス機能。std::sort
関数は、返却値をもたない(又は戻りvoid
、開始位置とデフォルトシーケンスの末尾位置、ならびに照合を指定するオプションのパラメータを示す2回の反復子の受信機)<
比較のために。
だから我々は、ソート機能インタフェースのように長くなることがあります。
template<typename RandIter>
void merge_sort
(
RandIter iterBeg, RandIter iterEnd, //开始与尾后迭代器
TYPE comp = ...//排序规则
)
どこの説明を次のコードの最初の行RandIter
のような適切な型に関数呼び出しを置き換えますクラス名、int*
、std::vector<int>::iterator
などが挙げられます。comp
バイナリ述語されると、RandIter
決定され、comp
型がそれに沿って決定されます。そのようなRandIter
ことはstd::deque<int>::iterator
、コアメンバーがデータであるint
タイプ、述語であるbool (*comp) (int a, int b)
、すなわち、二つの収容int
変数を返すbool
関数型へのポインタ。しかし、異なるイテレータ型のさまざまな、どのようにするかを決定するにはTYPE
?
標準ライブラリ・イテレータクラス注文容器の様々な、パッケージ有するvalue_type
配列内の要素を指すの種類を説明するために、このような二重の記憶素子としてstd::vector
イテレータであるvalue_type
ことstd::vector<double>::iterator::value_type
ファクトdouble
タイプ。したがって、comp
タイプがTYPE
書き込むことができますtypename RandIter::value_type
。
しかし、通常の配列のために、2回の反復子がポインタで渡されたが、ないポインタ型value_type
の!だから、言葉は配列を扱うことができない書き込み。
最初の文書ではtype_traits
、標準ライブラリは、型変換機能の多くを提供します。タイプに対してint*
、どの基準溶液の種類int
。より一般的なタイプのためにT
、場合同じタイプ、それを使用することができるで型を得ること。U*
T
type_traits
std::remove_pointer<T>::type
U
同じことはromove_pointer
、ポインタを操作し、コンテナの順序のために何もできません。
C ++も提供しauto
、decltype
キーが推論を入力します。インタフェースの機能は、使用することはできませんauto
で。そこで、我々は落ちる願っていますdecltype
上。
必要なのは、ある*iterBeg
タイプが、decltype
間接参照は、参照型となりますので、我々はまだ標準ライブラリのヘッダファイルのヘルプが必要なtype_traits
の一つremove_reference
、自然への参照を削除する機能を。次のようにこのように、インターフェース機能です。
template<typename RandIter>
void merge_sort
(
RandIter iterBeg, RandIter iterEnd, //开始与尾后迭代器
bool (*comp)(typename std::remove_reference<decltype(*iterBeg)>::type, typename std::remove_reference<decltype(*iterBeg)>::type) = ...//排序规则
)
タイプ名が解決され、以下のデフォルトのパラメータです。ここでは、ラムダ式を渡しますcomp
。
bool (*comp)(...) = [](typename std::remove_reference<decltype(*iterBeg)>::type a, typename std::remove_reference<decltype(*iterBeg)>::type b){return a < b;}
私は、全体のインターフェースがこれです書き出します:
template<typename RandIter>
void merge_sort
(
RandIter iterBeg, RandIter iterEnd, //开始与尾后迭代器
bool (*comp)(typename std::remove_reference<decltype(*iterBeg)>::type,
typename std::remove_reference<decltype(*iterBeg)>::type) = []
(typename std::remove_reference<decltype(*iterBeg)>::type a,
typename std::remove_reference<decltype(*iterBeg)>::type b) ->bool
{return a < b; }
)
参照が行われたとき、私は達成するために、デフォルトパラメータの代わりにヘビーデューティーを使用してそれを見つけ、Visual Studioのバージョンの採用を実装するために、前にこの機能を書いて、そのインターフェースは、クールなたくさんのことのようです。
template<typename RandIter>
void merge_sort//这里使用 '<' 来排序
(
RandIter iterBeg, RandIter iterEnd //开始与尾后迭代器
);
template<typename RandIter, typename Pred>
void merge_sort//这里使用 comp 来排序
(
RandIter iterBeg, RandIter iterEnd, //开始与尾后迭代器
Pred comp//排序规则
);
ここでは、スキップすることができ、テーマ、とはほとんどの機能の一部が、あります。
template<typename RandIter>
void merge_sort
(
RandIter iterBeg, RandIter iterEnd, //开始与尾后迭代器
bool (*comp)(typename std::remove_reference<decltype(*iterBeg)>::type,
typename std::remove_reference<decltype(*iterBeg)>::type) = []
(typename std::remove_reference<decltype(*iterBeg)>::type a,
typename std::remove_reference<decltype(*iterBeg)>::type b) ->bool
{return a < b; }
)
{
//递归终止条件为子序列只有一个元素,一个元素一定是有序的
//第二个判断条件是为了防止输入空序列
if (iterBeg + 1 == iterEnd || iterBeg == iterEnd)
return;
RandIter iterMid = iterBeg + (iterEnd - iterBeg) / 2;//指向序列中间位置
merge_sort(iterBeg, iterMid, comp);//递归
merge_sort(iterMid, iterEnd, comp);//只有子序列有序才进行合并
std::vector<std::remove_reference<decltype(*iterBeg)>::type>temp;//用来存储合并的有序序列
temp.reserve(iterEnd - iterBeg);//保留空间用于存诸元素,防止空间扩张带来的额外花销
auto it1 = iterBeg, it2 = iterMid;//分别指向两个子序列的开始位置
while (it1 != iterMid || it2 != iterEnd)//还有元素没处理
{
if (it1 == iterMid)//序列1的元素已放完
temp.emplace_back(*it2++);//只能放序列2的元素,后加的优先级高于解引用 (解引用与前加同级)
else if (it2 == iterEnd)
temp.emplace_back(*it1++);
else
temp.emplace_back(comp(*it1, *it2) ? *it1++ : *it2++);//按谓词规定的顺序放入
}
//将排好序的序列复制到原序列中的位置
typename std::vector<std::remove_reference<decltype(*iterBeg)>::type>::iterator itTemp = temp.begin();//第一个typename说明iterator是一个类型名
for (RandIter it2 = iterBeg; it2 != iterEnd; ++itTemp, ++it2)
* it2 = *itTemp;
}
その場には、本明細書中で使用される、ソート操作をマージすることはできませんvector
一時的なデータを格納します。
完成