7种常见排序的实现及简单性能比较


测试结果截图


每种排序都实现了比较器,可以进行复杂结构对象比较

代码为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");

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值