排序算法
- 一、归并排序
- 二、归并排序的应用
一、归并排序
原理(由小到大排序):
建立在归并操作上的一种有效的排序算法。该算法采用分治法。
算法描述
- 将待排序序列分为左边和右边,目的就是使左边和右边成为已排好的两个序列。最后将两个序列合并即可。
- 采用分治法,将左边的待排序列进一步分为左边和右边,操作同上。
- 至到每一个数字成一个待排序序列,此时,由下而上进行合并,最后得到一个有序序列。
重点 - 进行合并操作的时候,先声明一个合并空间。
- 对两个已排序序列的起始位置开始比较,较小的元素放入合并空间,指针向后移动到下一个待比较元素。
- 至到其中一个序列到达列尾,此时,将剩下的元素复制至合并序列的列尾。
代码如下:
function mergeSort(arr){
let len = arr.length;
if(len < 2) return arr;
let mid = Math.floor(len / 2);
let left = arr.slice(0,mid);
let right = arr.slice(mid);
return merge(mergeSort(left),mergeSort(right));
}
function merge(left,right){
let result = []
while(left.length > 0 && right.length >0){
if(left[0] <= right[0]){
result.push(left.shift());
}else{
result.push(right.shift());
}
}
while(left.length)
result.push(left.shift())
while(right.length)
result.push(right.shift())
return result;
}
var arr = [3,5,7,1,4,56,12,78,25,0,9,8,42,37];
var res = mergeSort(arr);
console.log(arr, res)
二、归并排序的应用
数组中的逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。最后要求输出一个数组中的逆序对的总数P。
待排序序列分治示意图
逆序对与归并排序
逆序对是归并排序进行合并操作时进行。
合并过程为:
- 先声明一个合并空间,大小为两个待排序序列的长度和。
- 对两个已排序序列的起始位置开始比较,较小的元素放入合并空间,指针向后移动到下一个待比较元素。
- 至到其中一个序列到达列尾,此时,将剩下的元素复制至合并序列的列尾。
逆序对的计算为:
- 若右边当前元素小于左边当前元素,那么从当前指针指向的左边的元素起,至到左边元素最后的元素,右边当前元素都是最小的,所以存在的逆序对为,从当前左边元素至列尾的元素的长度。
- 例如:left(7)>right(5),则存在一个逆序对,left(6)>right(4),则共存在两个逆序对。
- 继续进行比较left(5,7)>right(4,6),比较left第一个元素与right第一个元素,left>right,left的长度为2,所以目前存在4个逆序对。
- 继续比较left(5,7)>right(6),比较left第一个元素与right第一个元素,left<right,逆序对数不变。
- 继续比较left(7)>right(6),比较left第一个元素与right第一个元素,left>right,left的长度为1,所以目前存在5个逆序对。最终也为5个逆序对。
代码如下:
function InversePairs(data)
{
let sum = 0;
let res = sort(data);
sum = sum % 1000000007;
return sum;
function sort(data){
if(data.length < 2) return data;
let mid = data.length / 2;
let left = data.slice(0,mid);
let right = data.slice(mid);
return merge(sort(left),sort(right));
}
function merge(left,right){
let result = [];
while(left.length > 0 && right.length > 0){
if(left[0]>right[0]){
sum = sum + left.length;
result.push(right.shift());
}else{
result.push(left.shift())
}
}
while(left.length) result.push(left.shift());
while(right.length) result.push(right.shift());
return result;
}
}