曾经有段时间研究过排序算法,可惜记不住,虽然看懂,但都忘了。
冰冻三尺,非一日之寒;士别三日,不足刮目相看!
#include <vector> #include <math.h> using namespace std; template <class Comparable> void mergeImproved( vector<Comparable> &a ) { int size = a.size(); vector<Comparable> b( size ); // 唯一的临时数组 int maxLayer = 1; for ( int items = 2; items < size; items *= 2, ++maxLayer ); // for each layer, perform merge sort. for ( int curLayer = 0, items = 0; curLayer < maxLayer; ++curLayer ) { items = int( pow( double( 2 ), double( curLayer ) ) );//功能:pow(x,y)返回x的y次幂 // decide which array of a and b is input or output vector<Comparable> &in = ( curLayer % 2 == 0 ) ? a : b; vector<Comparable> &out = ( curLayer % 2 == 0 ) ? b : a; // for each left and right sub arrays on the block for ( int index = 0; index < size; index += ( 2 * items ) ) { // fix the left array's first and last indices int first1 = index; int last1 = ( first1 + items - 1 < size - 1 ) ? first1 + items - 1 : size - 1; // fix the right array's first and last indices int first2 = ( last1 < size - 1 ) ? last1 + 1 : size;///////////////////////(size-1) int last2 = (first2 + items - 1 < size - 1 ) ? first2 + items - 1 : size - 1; // now merge them in one block int outIx = first1; for ( ; first1 <= last1 && first2 <= last2; ++outIx ) out[outIx] = ( in[first1] < in[first2] ) ? in[first1++] : in[first2++]; for ( ; first1 <= last1; ++first1, ++outIx ) out[outIx] = in[first1]; for ( ; first2 <= last2; ++first2, ++outIx ) out[outIx] = in[first2]; } } // in case the sort items are in the temporary array if ( maxLayer % 2 == 1 ) a = b; // copy them back to the original优化的归并排序
template<typename _Tp, typename _Alloc> void list<_Tp, _Alloc>:: merge(list& __x) // 前三行是C++里的模版定义,不用管。这个函数用来把 x 的元素归并到当前链表里。 { // 归并之后 x 会变成一个空表。也就是说是挪进当前链表里来。 // _GLIBCXX_RESOLVE_LIB_DEFECTS // 300. list::merge() specification incomplete if (this != &__x) // 只有在 x 不是当前表时,函数才起作用。用于防止类似 merge(a, a) 这样的情况。 { _M_check_equal_allocators(__x); // 由于要挪进当前表。 // 因此两个前提是两个表用要用相同的内存分配器. iterator __first1 = begin(); iterator __last1 = end(); iterator __first2 = __x.begin(); iterator __last2 = __x.end(); while (__first1 != __last1 && __first2 != __last2) if (*__first2 < *__first1) { iterator __next = __first2; _M_transfer(__first1, __first2, ++__next); // transfer(a, b, c) 的意思是: 把指针 b, c 之间的内容(逻辑上它们要指向同一个序列的前后元素)剪切到 a 的后面。 __first2 = __next; } else ++__first1; if (__first2 != __last2) _M_transfer(__last1, __first2, __last2); } } template<typename _Tp, typename _Alloc> void list<_Tp, _Alloc>:: sort() // 这个是排序。 { // Do nothing if the list has length 0 or 1. if (this->_M_impl._M_node._M_next != &this->_M_impl._M_node && this->_M_impl._M_node._M_next->_M_next != &this->_M_impl._M_node) { // list 是带头结点的双向循环链表。因此在头结点的后面是头结点(这种情况是空表)或者头结点后面的后面是头结点(这时只有一个元素)的时候,不进行排序。 list __carry; // carry 用来临时持有一个链表,以和tmp中的某一个进行归并。 list __tmp[64]; // tmp[n] 用来持有一个长度为 2^n 次方个元素的链表。就是 tmp[0] 只能持有一个元素。tmp[1] 持有两个。 list * __fill = &__tmp[0]; // 用来记录用到的tmp的最大下标的链表。大于 fill 的tmp[n] 均是空表。初始化到0上。 list * __counter; // 顾名思义就是计数器,用于下面的循环。 do // 在当前表不空前,不停地往 tmp 里按大小归并当前的链表。 { __carry.splice(__carry.begin(), *this, begin()); for(__counter = &__tmp[0]; __counter != __fill && !__counter->empty(); ++__counter) { __counter->merge(__carry); __carry.swap(*__counter); } __carry.swap(*__counter); if (__counter == __fill) ++__fill; } while ( !empty() ); // 然后把 tmp 里所有长度的表都归并到 fill-1 这个表里。这个过程不再受tmp[n]的长度限制。 for (__counter = &__tmp[1]; __counter != __fill; ++__counter) __counter->merge(*(__counter - 1)); // 最后把 fill-1 换回当前链表。 swap( *(__fill - 1) ); } }