排序算法

发布于 2022-08-28 11:58:09 字数 168 浏览 14 评论 0

给定数组arr[n],其中n=10000,0<arr[i]<9999,-1<i<10000.
已知数组中的值时乱序的,且其值均匀分布在0-9999 区间,只有少量数值重复
请用js代码写一个函数,以最快的方式完成对该数组的升序排序,要求算法时间复杂度必须小于O(NLOG2N).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

云淡月浅 2022-09-04 11:58:09

数据是均匀分布的,用桶排序挺合适,时间复杂度也必定小于NlogN。
对于N个待排数据,M个桶,桶排序平均时间复杂度为:O(N+N(logN/M)).
桶数越多,速度越快,但空间代价也越大。

具体算法就不写了。

//=======补充代码======

function insertSort(array) {
  var i = 1,
    j, temp, key, len = array.length;
  for (; i < len; i++) {
    temp = j = i;
    key = array[j];
    while (--j > -1) {
      if (array[j] > key) {
        array[j + 1] = array[j];
      } else {
        break;
      }
    }
    array[j + 1] = key;
  }
}
//**迭代快排**
function qs(arr){
    var stack = [];
    stack.push([0,arr.length-1]);
    var l,r,axis,o;
    while(stack.length){
        o = stack.pop();
        l = o[0],r = o[1];
        if( l >= r )
            continue;
        axis = once(arr,l,r);
        stack.push([l,axis-1]);
        stack.push([axis+1,r]);
    }

    function once(arr,l,r){
        var axisAtLeft = true, //left right sign, default left;
            temp;
        swap(arr,l, (r+l)/2 >> 0);  //以中值为轴值
        while(l<r){
            if( axisAtLeft ){
                if( arr[l] > arr[r] ){
                    swap(arr,l++,r);
                    axisAtLeft = false;
                }else  r--;
            }
            else{
                if( arr[l] > arr[r] ){
                    swap(arr,l,r--);
                    axisAtLeft = true;
                }else  l++;
            }
        }
        return l;
    }

    function swap(arr,l,r){
        var temp = arr[l];
        arr[l] = arr[r];
        arr[r] = temp;
    }
    return arr;
}

function createArr(min, max, p ) {
    var arr = [];
    var c = max - min;
    var probability = p || 0.001; //不均匀分布的概率0.1%

    //打乱顺序
    var indexArr = [];
    for (var i = 0; i < c; i++) indexArr[i] = i;
    indexArr.sort(function(a, b) {
        return Math.random() > 0.5 ? 1 : -1;
    });

    for (var i = 0; i < c; i++) {
        if (Math.random() > probability) { //不均匀分布的概率0.1%
            arr.push( indexArr[i] + Math.random() );
        } else {
            arr.push( Math.random() * (c-1) );
        }
    }
    return arr;
}

function bucketSort(arr, min, max) {
    var N = arr.length,
        bucks = [],
        M = Math.floor(Math.sqrt(N)),  //桶的个数设为Math.sqrt(N),如N=10000,则桶数为100
        dis = (max - min) / M;

    //初始化桶
    for (var i = 0; i < M; i++) bucks[i] = [];

    //数据入桶
    for (var j = 0; j < N; j++) 
        bucks[ Math.floor((arr[j] - min) / dis) ].push(arr[j]);

    //各个桶的数据排序
    for (var i = 0; i < M; i++)
         insertSort(bucks[i]);

    //合并各个桶的数据
    var firstBucket = bucks[0];
    for (var i = 1; i < M; i++){
        var bucket_i = bucks[i];
        for(var j=0;j<bucket_i.length;j++){
            firstBucket.push(bucket_i[j]);
        }
    }

    return firstBucket
}

var min = 0,
    max = 10000,
    arr = createArr(min, max)

//桶排序
var d1 = new Date();
var narr = bucketSort(arr, min, max);
console.log(new Date() - d1);


var arr2 = createArr(min, max)
//快排
var d2 = new Date();
qs(arr2);
console.log(new Date() - d2);

在firefox中测试,10000条数据,桶排序快一倍以上。

人事已非 2022-09-04 11:58:09

采用一个类似于位图的结构来解决这个问题。首先,你的数据量不大,而且像你说的重复数目也不多,这里看作常数。可以声明一个10000字节大小的数组count[10000],初始化为全0。扫描一遍你的待排序的数据,针对每一个值i,递增其对应的位置的数组值count[i]。扫描完毕后,再从头扫描一遍a[10000],对于i,输出a[i]次即可。这样时间复杂度为O(n),
我js不怎么懂。勉强给你写个函数

function mySort(arr, length) {
    var count = new Array(length);
    for (var i = 0; i != length; i++) {
        count[i] = 0;
    }
    for (var i = 0; i != length; i++) {
        count[arr[i]]++;
    }
var index = 0;
    for (var i = 0; i != length; i++) {
        for (var j = 0; j < count[i]; j++) {
            arr[index ++] = i;
        }
    }
//alert(count); 
}
// An example
var arr = new Array(10);
arr[0] = 1;
arr[1] = 2;
arr[2] = 1;
arr[3] = 0;
arr[4] = 9;
arr[5] = 8;
arr[6] = 6;
arr[7] = 2;
arr[8] = 3;
arr[9] = 6;

mySort(arr, 10);

alert(arr);
梦亿 2022-09-04 11:58:09

楼主请认真自己做作业,都说了复杂度小 NlogN 了,肯定不是排序了,而是某种比较讨巧的作法。

有人赞,我就写代码

甜心小果奶 2022-09-04 11:58:09

数据很小,不要求空间复杂度的话直接桶排。

var a = new Array;
for(var i=1;i<=10000;i++){
    a[arr[i]]++;
}
//排序完成,可以输出了
for(var i=1;i<=10000;i++){
    for(var j=1;j<=a[i];j++){
        alert(i);
    } 
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文