STLソース分析のrotateアルゴリズム
12224 ワード
前言
义齿
forward_iterator_tagバージョン
注意: firstは前段部分のポインタ である. iは後段部分のポインタ を示す.
交換全体の時間的複雑度はO(n)であり、空間的なオーバーヘッドはない.
bidirectional_iterator_tagバージョン
random_access_iterator_tagバージョン
最大公因子減少時間複雑度を採用
まとめ
本節では、
stl_algo.h
ファイルには多くのアルゴリズムが実装されているが、ここではSTL分析でいくつかの関数を選択して分析するが、他のアルゴリズムは興味を持って自分で見ることができ、本節ではstl_algo.h
ファイルのrotate
アルゴリズムを分析する.このアルゴリズムが実現する機能は[first,middle],[midddle,last]の2つの区間の要素を交換することである.义齿
template <class ForwardIterator>
inline void rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last)
{
if (first == middle || middle == last) return;
// : first, middle, last
__rotate(first, middle, last, distance_type(first), iterator_category(first));
}
forward_iterator_tagバージョン
注意:
template <class ForwardIterator, class Distance>
void __rotate(ForwardIterator first, ForwardIterator middle,
ForwardIterator last, Distance*, forward_iterator_tag)
{
// ,
for (ForwardIterator i = middle; ;) {
// middle , ,
iter_swap(first, i);
++first;
++i;
//
if (first == middle) {
//
if (i == last) return;
// middle , first = old_middle
middle = i;
}
//
else if (i == last)
// i , middle
i = middle;
}
}
交換全体の時間的複雑度はO(n)であり、空間的なオーバーヘッドはない.
bidirectional_iterator_tagバージョン
template <class BidirectionalIterator, class Distance>
void __rotate(BidirectionalIterator first, BidirectionalIterator middle,
BidirectionalIterator last, Distance*,
bidirectional_iterator_tag) {
reverse(first, middle);
reverse(middle, last);
reverse(first, last);
}
random_access_iterator_tagバージョン
最大公因子減少時間複雑度を採用
template <class RandomAccessIterator, class Distance>
void __rotate(RandomAccessIterator first, RandomAccessIterator middle,
RandomAccessIterator last, Distance*,
random_access_iterator_tag) {
Distance n = __gcd(last - first, middle - first);
while (n--)
__rotate_cycle(first, last, first + n, middle - first, value_type(first));
}
template <class RandomAccessIterator, class Distance, class T>
void __rotate_cycle(RandomAccessIterator first, RandomAccessIterator last,
RandomAccessIterator initial, Distance shift, T*) {
T value = *initial;
RandomAccessIterator ptr1 = initial;
RandomAccessIterator ptr2 = ptr1 + shift;
while (ptr2 != initial) {
*ptr1 = *ptr2;
ptr1 = ptr2;
if (last - ptr2 > shift)
ptr2 += shift;
else
ptr2 = first + (shift - (last - ptr2));
}
*ptr1 = value;
}
//
template <class EuclideanRingElement>
EuclideanRingElement __gcd(EuclideanRingElement m, EuclideanRingElement n)
{
while (n != 0) {
EuclideanRingElement t = m % n;
m = n;
n = t;
}
return m;
}
まとめ
本節では、
rotate
の2つのセグメントの要素を交換することを分析し、全体的な実現は難しくないが、異なる反復器タイプが最適な関数を選択して実現することを考慮し、最大の効率向上の問題を考慮する必要がある.次の節では、stl_algo.h
の他の基本的なアルゴリズムを分析し続けます.