曾经有段时间研究过排序算法,可惜记不住,虽然看懂,但都忘了。

冰冻三尺,非一日之寒;士别三日,不足刮目相看!
2011-01-28 22:37
2011-01-28 23:18


2011-01-29 09:15

2011-01-29 09:27

2011-01-29 10:25
程序代码:#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
优化的归并排序
2011-01-29 10:50
2011-01-29 11:01
程序代码:
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) );
}
}
2011-01-29 11:49

2011-01-29 12:07
2011-01-29 12:21