【发布时间】:2014-02-28 20:28:24
【问题描述】:
我正在尝试在 JavaScript 中实现一堆排序算法,但我不明白为什么我的 shell 排序这么慢。它比我的合并排序慢 6 倍,并且只比我的插入排序快一点。我在网上看到了另一种实现,但我更专注于使其清晰易读(因为我有一个新手博客),而且更快的实现对于我的目的来说太简洁了。关于如何保持总体计划但加快进度的任何想法?
var shellSort = function( list ) {
var gapSize = Math.floor( list.length / 2 );
while( gapSize > 0 ) {
_shellInsertionSort( list, gapSize );
gapSize = Math.floor( gapSize / 2 );
}
return list;
};
function _shellInsertionSort( list, gapSize ) {
var temp, i, j;
for( i = gapSize; i < list.length; i += gapSize ) {
j = i;
while( j > 0 && list[ j - gapSize ] > list[j] ) {
temp = list[j];
list[j] = list[ j - gapSize ];
list[ j - gapSize ] = temp;
j -= gapSize;
}
}
};
我的归并排序:
var mergeSort = function( list ) {
if ( list.length <= 1 ) {
return list;
}
var left = [],
right = [],
middle = Math.floor( list.length / 2 ),
i;
for( i = 0; i < middle; i++ ) {
left.push( list[i] );
}
for( ; i < list.length; i++ ) {
right.push( list[i] );
}
left = mergeSort( left );
right = mergeSort( right );
return _merge( left, right );
};
function _merge( left, right ) {
var result = [];
// Should be able to just get rid of arguments in while loop
while( left.length || right.length ) {
if( left.length > 0 && right.length > 0 ) {
if( left[0] <= right[0] ) {
result.push( left.shift() );
} else {
result.push( right.shift() );
}
}
else if( left.length ) {
return result.concat( left );
}
else {
return result.concat( right );
}
}
}
我的测试:
var testSpeed = function( testSize, rounds ) {
var testArrays = [],
algorithms = Array.prototype.slice.call( arguments, 2 ),
results = [],
i, j;
for( i = 0; i < rounds; i++ ) {
testArrays[i] = [];
for( j = 0; j < testSize; j++ ) {
testArrays[i].push( Math.ceil( Math.random() * testSize ));
}
}
for( i = 0; i < algorithms.length; i++ ) {
for( j = 0; j < rounds; j++ ) {
if( !results[i] ) {
results[i] = [];
}
results[i].push( testAlgorithm( algorithms[i], testArrays[j] ));
}
}
return results;
};
var testAlgorithm = function( algorithm, set ) {
var clone = set.slice(),
start = new Date().getTime(),
end;
algorithm( clone );
end = new Date().getTime();
return end - start;
};
【问题讨论】:
-
这可能更适合codereview.stackexchange.com。
-
Shell 排序在您的间隙序列最坏的情况下是二次方的,那么您为什么认为它应该不比归并排序慢?
-
虽然我根本没有彻底检查你的代码(而且 codereview 可能是要求进行代码审查的更好地方),但我相信你使用的间隙序列不是很好;与其他间隙序列不同,它的最坏情况时间复杂度为 O(N^2)。
-
@NiklasB.:这取决于您使用的间隔序列。有关复杂性结果的调查,请参阅 Sedgewick 1996 (citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.101.9061)。
-
@rici 我考虑了间隙序列,这里选择的特别差。但即使有一个好的间隙序列,你也不太可能渐近地击败归并排序
标签: javascript algorithm performance sorting shellsort