您的位置:首页 > Web前端 > JavaScript

JavaScript排序算法之归并排序

2016-03-27 15:48 645 查看
归并排序的引入


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



自底向上的排序方法

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

代码测试:

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
) {

arr[k] = leftArr[m];

m++;

}

else {

arr[k] = rightArr
;

n++;

}

}

alert("left array - ", leftArr[m]);

alert("right array - ", rightArr
);

}

说明:函数中的关键点就是

step
这个变量, 它用来控制
mergeArrays()
函数生成的leftArr


rightArr
这两个子序列的大小。 通过控制子序列的大小, 处理排序是比较高效的, 因为它在对小数组进行排序时不需要花费太多时间。 合并之所以高效, 还有一个原因,
由于未合并的数据已经是排好序的, 将它们合并到一个有序数组的过程非常容易

测试

var
nums = new CArray(10);

nums.setData();

alert(nums.toString());

nums.mergeSort();

alert(nums.toString());
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: