测试结果截图
每种排序都实现了比较器,可以进行复杂结构对象比较
代码为js实现,运行环境nodejs
/****************************************
* sortTool
* 2015/5/25
****************************************/
/**
* 插入排序
* @param {*Array} arr
* @param {*Number} begin 可选
* @param {*Number} end 可选
* @param {*Function} comparer 可选参数
*/
exports.insertSort = function(arr, comparer, begin, end) {
if(!arr || arr.constructor != Array) {
return;
}
if(!comparer || comparer.constructor != Function) {
comparer = defComparer;
}
if(start == undefined || end == undefined) {
begin = 0;
end = arr.length;
}
var j, temp;
for(var i=1+begin; i<end; ++i) {
temp = arr[i];
j = i-1;
for(; j>=0 && comparer(arr[j], temp) > 0; --j) {
arr[j+1] = arr[j];
}
if(j+1 != i) {
arr[j+1] = temp;
}
}
}
/**
* 冒泡排序
* @param {*Array} arr 待排序数组
* @param {*Function} comparer 可选参数
*/
exports.bubbleSort = function(arr, comparer) {
if(!arr || arr.constructor != Array) {
return;
}
if(!comparer || comparer.constructor != Function) {
comparer = defComparer;
}
for(var i=0; i<arr.length; ++i) {
for(var j=0; j<arr.length-i-1; ++j) {
if(comparer(arr[j], arr[j+1]) > 0) {
swap(arr, j+1, j);
}
}
}
}
/**
* 选择排序
* @param {*Array} arr
* @param {*Function} comparer 可选参数
*/
exports.selectionSort = function(arr, comparer) {
if(!arr || arr.constructor != Array) {
return;
}
if(!comparer || comparer.constructor != Function) {
comparer = defComparer;
}
var minIndex = 0;
for(var i=0; i<arr.length; ++i) {
minIndex = i;
for(var j=i; j<arr.length; ++j) {
if(comparer(arr[j], arr[minIndex]) < 0) {
minIndex = j;
}
}
swap(arr, i, minIndex);
}
}
/**
* 快速排序
* @param {*Array} arr
* @param {*Number} start
* @param {*Number} end
* @param {*Function} comparer 可选参数
*/
exports.quickSort = function(arr, comparer, begin, end){
if(!arr || arr.constructor != Array) {
return;
}
if(!comparer || comparer.constructor != Function) {
comparer = defComparer;
}
if(begin == undefined || end == undefined) {
begin = 0;
end = arr.length - 1;
}
var pivotPosition;
while(begin < end){
pivotPosition = optimalPartition(arr, comparer, begin, end);
if(end - pivotPosition >= pivotPosition - begin){
exports.quickSort(arr, comparer, begin, pivotPosition - 1);
begin = pivotPosition + 1;
}
else{
exports.quickSort(arr, comparer, pivotPosition + 1, end);
end = pivotPosition - 1;
}
}
}
/**
* 归并排序
* @param {Array} arr
* @param {*Function} comparer 可选参数
*/
exports.mergeSort = function(arr, comparer) {
if(!arr || arr.constructor != Array) {
return;
}
if(!comparer || comparer.constructor != Function) {
comparer = defComparer;
}
var tempArr = new Array(arr.length);
sort(arr, comparer, 0, arr.length-1, tempArr);
}
/**
* 希尔排序
* @param {Array} arr
* @param {*Function} comparer 可选参数
*/
exports.shellSort = function(arr, comparer) {
if(!arr || arr.constructor != Array) {
return;
}
if(!comparer || comparer.constructor != Function) {
comparer = defComparer;
}
var group, i = 1, j = 0, temp;
for (group = Math.floor(arr.length/2); group>0; group = Math.floor(group/2)) {
for(i=group; i<arr.length; i+=group) {
temp = arr[i];
j = i-group;
for(; j>=0 && arr[j]>temp; j-=group) {
arr[j+group] = arr[j];
}
if(j+group != i) {
arr[j+group] = temp;
}
}
}
}
/**
* 堆排序
* @param {Array} arr
* @param {*Function} comparer 可选参数
*/
exports.heapSort= function(arr, comparer) {
if(!arr || arr.constructor != Array) {
return;
}
if(!comparer || comparer.constructor != Function) {
comparer = defComparer;
}
//1.构建大顶堆
for(var i=Math.floor(arr.length/2)-1;i>=0;i--){
//从第一个非叶子结点从下至上,从右至左调整结构
adjustHeap(arr, comparer, i, arr.length);
}
//2.调整堆结构+交换堆顶元素与末尾元素
for(var j=arr.length-1;j>0;j--){
swap(arr,0,j);//将堆顶元素与末尾元素进行交换
adjustHeap(arr, comparer, 0, j);//重新对堆进行调整
}
}
/*************************************
* 本地函数
************************************/
/**
* 数组元素交换
* @param {*Array} arr 数组
* @param {*Function} comparer 元素比较器
* @param {*Number} pos1 下标1
* @param {*Number} pos2 下标2
*/
function swap(arr, pos1, pos2) {
if(pos1 == pos2) {
return;
}
var temp = arr[pos1];
arr[pos1] = arr[pos2];
arr[pos2] = temp;
}
/**
* 默认比较器
* @param {*Any} a
* @param {*Any} b
*/
function defComparer(a, b) {
if(a > b) {
return 1;
}
if(a < b) {
return -1;
}
if(a == b) {
return 0;
}
}
/**
* 快速排序 随机化基数优化
* @param {*Array} arr
* @param {*Function} comparer 元素比较器
* @param {*Number} begin
* @param {*Number} end
*/
function optimalPartition(arr, comparer, begin, end){
var pivotPosition = Math.floor(Math.random() * (end - begin + 1) + begin);
var pivot;
var i = begin, j;
pivot = arr[pivotPosition];
swap(arr, pivotPosition, end);
for(j = begin; j < end; j++){
if(comparer(arr[j], pivot) <= 0){
swap(arr, i, j);
i++;
}
}
arr[end] = arr[i];
arr[i] = pivot;
return i;
}
/**
* 归并排序sort
* @param {*Array} arr 待排序的数组
* @param {*Function} comparer 元素比较器
* @param {*Number} left 排序开始的下标
* @param {*Number} right 排序结束的下标
* @param {*Array} tempArr 临时数组
*/
function sort(arr, comparer, left, right, tempArr) {
if(right - left < 1) {
return;
}
var mid = Math.floor((left+right) / 2);
sort(arr, comparer, left, mid, tempArr);
sort(arr, comparer, mid+1, right, tempArr);
merge(arr, comparer, left, mid, mid+1, right, tempArr);
};
/**
* 归并排序merge
* @param {*Array} arr 待排序的数组
* @param {*Function} comparer 元素比较器
* @param {*Number} l1 分支1数组开始下标
* @param {*Number} r1 分支1数组开始下标
* @param {*Number} l2 分支2数组结束下标
* @param {*Number} r2 分支2数组结束下标
* @param {*Array} tempArr 临时数组
*/
function merge(arr, comparer, l1, r1, l2, r2, tempArr) {
var index = 0;
var start = l1;
while(l1 <= r1 && l2 <= r2) {
if(comparer(arr[l1], arr[l2]) <= 0) {
tempArr[index++] = arr[l1++];
} else {
tempArr[index++] = arr[l2++];
}
}
while(l1 <= r1) {
tempArr[index++] = arr[l1++];
}
while(l2 <= r2) {
tempArr[index++] = arr[l2++];
}
for (var i = 0; i < index; ++i) {
arr[start+i] = tempArr[i];
}
}
/**
* 堆排序,堆调整为大顶堆(升序)或小顶堆(降序)
* @param {*Array} arr
* @param {*Function} comparer 元素比较器
* @param {*Number} i
* @param {*Number} length
*/
function adjustHeap(arr, comparer, i, length) {
var temp = arr[i];//先取出当前元素i
for(var k=i*2+1;k<length;k=k*2+1){//从i结点的左子结点开始,也就是2i+1处开始
if(k+1<length && comparer(arr[k], arr[k+1]) < 0){//如果左子结点小于右子结点,k指向右子结点
k++;
}
if(comparer(arr[k], temp) > 0){//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
arr[i] = arr[k];
i = k;
}else{
break;
}
}
arr[i] = temp;//将temp值放到最终的位置
}
//测试开始
//比较器测试
console.log("比较器测试");
function Point(x, y){
this.x = x;
this.y = y;
}
var pointArr = [];
for (var i = 0; i < 10; i++) {
pointArr.push(new Point(Math.round(Math.random()*10), Math.round(Math.random()*10)));
}
exports.mergeSort(pointArr, function(a, b) {
var x = a.x - b.x;
if(x == 0) {
return a.y - b.y;
} else {
return x;
}
});
console.log(pointArr);
//性能测试
console.log("性能测试");
//初始一个N个元素的数组
const N = 40000;
var array1 = new Array(N);
for (var i = 0; i < array1.length; i++) {
array1[i] = Math.round(Math.random() * N);
}
var array2 = array1.slice(0);
var array3 = array1.slice(0);
var array4 = array1.slice(0);
var array5 = array1.slice(0);
var array6 = array1.slice(0);
var array7 = array1.slice(0);
console.log("各排序速度简单比较,都对元素个数为", N, ",且内容相同的数组排序");
//插入排序
var start = process.hrtime(); //获取纳秒级别
exports.insertSort(array1);
var end = process.hrtime(start);
console.log("插入排序耗时:", end[0]+end[1]/1000000000+" 秒");
//冒泡排序
start = process.hrtime();
exports.bubbleSort(array2);
end = process.hrtime(start);
console.log("冒泡排序耗时:", end[0]+end[1]/1000000000+" 秒");
//选择排序
start = process.hrtime();
exports.selectionSort(array3);
end = process.hrtime(start);
console.log("选择排序耗时:", end[0]+end[1]/1000000000+" 秒");
//快速排序
start = process.hrtime();
exports.quickSort(array4);
end = process.hrtime(start);
console.log("快速排序耗时:", end[0]+end[1]/1000000000+" 秒");
//归并排序
start = process.hrtime();
exports.mergeSort(array5);
end = process.hrtime(start);
console.log("归并排序耗时:", end[0]+end[1]/1000000000+" 秒");
//希尔排序
start = process.hrtime();
exports.shellSort(array6);
end = process.hrtime(start);
console.log("希尔排序耗时:", end[0]+end[1]/1000000000+" 秒");
//堆排序
start = process.hrtime();
exports.heapSort(array7);
end = process.hrtime(start);
console.log(" 堆排序耗时:", end[0]+end[1]/1000000000+" 秒");
console.log("over");