JavaScript排序算法之归并排序

归并排序的引入

             归并排序的命名来自它的实现原理: 把一系列排好序的子序列合并成一个大的完整有序序列。 从理论上讲, 这个算法很容易实现。 我们需要两个排好序的子数组, 然后通过比较数据大小, 先从最小的数据开始插入, 最后合并得到第三个数组。 然而, 在实际情况中, 归并排序还有一些问题, 当我们用这个算法对一个很大的数据集进行排序时, 我们需要相当大的空间来合并存储两个子数组。 就现在来讲, 内存不那么昂贵, 空间不是问题, 因此值得我们去实现一下归并排序, 比较它和其他排序算法的执行效率。

自底向上的排序方法

      采用非递归或者迭代版本的归并排序是一个自底向上的过程。 这个算法首先将数据集分解为一组只有一个元素的数组。 然后通过创建一组左右子数组将它们慢慢合并起来, 每次合并都保存一部分排好序的数据, 直到最后剩下的这个数组所有的数据都已完美排序。 下图演示了自底向上的归并排序算法如何运行的。

代码测试:

1.所调用的函数:

   function CArray(numElements) {
   this.dataStore = [];
   this.toString = toString;

   this.numElements = numElements;

   this.setData = setData;                 //随机生成一组数
   this.mergeSort=mergeSort;
   this.mergeArrays=mergeArrays;
   for (var i = 0; i < numElements; ++i) {
      this.dataStore[i] = i;
   }
}

function setData() {
   for (var i = 0; i < this.numElements; ++i) {
      this.dataStore[i] = Math.floor(Math.random() *
                          (this.numElements+1));
   }
}

function toString() {
   var retstr = "";
   for (var i = 0; i < this.dataStore.length; ++i) {
      retstr += this.dataStore[i] + " ";
      if (i > 0 && i % 10 == 0) {
         retstr += "\n";
      }
   }
   return retstr;
}

function mergeSort() {
        if (this.dataStore.length < 2) {
        return;
        }
        var step = 1;
        var left, right;
        while (step < this.dataStore.length) {
        left = 0;
        right = step;
        while (right + step <= this.dataStore.length) {
        mergeArrays(this.dataStore, left, left+step, right, right+step);
        left = right + step;
        right = left + step;
        }
        if (right < this.dataStore.length) {
        mergeArrays(this.dataStore, left, left+step, right, this.dataStore.length);
        }
        step *= 2;
    }
}

function mergeArrays(arr,startLeft, stopLeft, startRight, stopRight) {
        var rightArr = new Array(stopRight - startRight + 1);
        var leftArr = new Array(stopLeft - startLeft + 1);
        k = startRight;
        for (var i = 0; i < (rightArr.length-1); ++i) {
        rightArr[i] = arr[k];
        ++k;
        } k
        = startLeft;
        for (var i = 0; i < (leftArr.length-1); ++i) {
        leftArr[i] = arr[k];
        ++k;
        }
        rightArr[rightArr.length-1] = Infinity; // 哨兵值
        leftArr[leftArr.length-1] = Infinity; // 哨兵值
        var m = 0;
        var n = 0;
        for (var k = startLeft; k < stopRight; ++k) {
        if (leftArr[m] <= rightArr[n]) {
        arr[k] = leftArr[m];
        m++;
        }
        else {
        arr[k] = rightArr[n];
        n++;
        }
        }
        alert("left array - ", leftArr[m]);
        alert("right array - ", rightArr[n]);
        }

说明:函数中的关键点就是 step 这个变量, 它用来控制 mergeArrays() 函数生成的leftArr rightArr 这两个子序列的大小。 通过控制子序列的大小, 处理排序是比较高效的, 因为它在对小数组进行排序时不需要花费太多时间。 合并之所以高效, 还有一个原因, 由于未合并的数据已经是排好序的, 将它们合并到一个有序数组的过程非常容易
测试

var nums = new CArray(10);
nums.setData();
alert(nums.toString());
nums.mergeSort();
alert(nums.toString());




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值