Сортировка слиянием работает за время O ( n*log(n) ), как в среднем, так и в худшем случае.
Единственным недостатком для сортировки массива является необходимость наличия дополнительной памяти (buf)
равной по размеру исходному массиву (arr). Для сортировки списков дополнительная память не требуется.
template<class T> ArrRef<T> mergeSort123 ( ArrRef<T> & arr, ArrRef<T> & buf ) { const nat n = arr.size(); const nat small_size = sizeof(T) > 8 ? 32 : sizeof(T) > 4 ? 50 : 64; if ( n < small_size ) return insertSort123 ( arr ); nat k = small_size / 2; nat m = n, s = 0; for(;;) { if ( m > k ) { insertSort123 ( ArrRef<T> ( arr, s, k ) ); s += k; m -= k; } else { insertSort123 ( ArrRef<T> ( arr, s, m ) ); break; } } bool e = false; do { T * a, * b; if ( e ) { b = arr(); a = buf(); } else { a = arr(); b = buf(); } nat i1 = 0; for (;;) { T * p1 = a + i1; nat i2 = i1 + k; if ( i2 >= n ) { T * a2 = a + n; while ( p1 < a2 ) { *b++ = *p1++; } break; } T * a2 = a + i2; T * p2 = a2; nat i3 = i2 + k; if ( i3 > n ) i3 = n; T * a3 = a + i3; for (;;) { if ( *p1 <= *p2 ) { *b++ = *p1++; if ( p1 == a2 ) { while ( p2 < a3 ) { *b++ = *p2++; } break; } } else { *b++ = *p2++; if ( p2 == a3 ) { while ( p1 < a2 ) { *b++ = *p1++; } break; } } } i1 = i3; } e = !e; k <<= 1; } while ( k < n ); if ( e ) { for ( nat i = 0; i < n; ++i ) arr[i] = buf[i]; } return arr; } Здесь переменные i1, i2, i3 обозначают соответственно: начало первого фрагмента из пары, начало второго фрагмента и начало следующей пары, если она есть. Аналогично устроен шаблон mergeSort321, который сортирует элементы массивов по убыванию. Описание шаблона классов ArrRef находится здесь.
|