排序算法

  • 一、归并排序
  • 二、归并排序的应用



一、归并排序

原理(由小到大排序):
建立在归并操作上的一种有效的排序算法。该算法采用分治法。
算法描述

  • 将待排序序列分为左边和右边,目的就是使左边和右边成为已排好的两个序列。最后将两个序列合并即可。
  • 采用分治法,将左边的待排序列进一步分为左边和右边,操作同上。
  • 至到每一个数字成一个待排序序列,此时,由下而上进行合并,最后得到一个有序序列。
    重点
  • 进行合并操作的时候,先声明一个合并空间。
  • 对两个已排序序列的起始位置开始比较,较小的元素放入合并空间,指针向后移动到下一个待比较元素。
  • 至到其中一个序列到达列尾,此时,将剩下的元素复制至合并序列的列尾。

代码如下:

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。

待排序序列分治示意图

javascript 排序工具 javascript排序算法_javascript 排序工具


逆序对与归并排序

逆序对是归并排序进行合并操作时进行。

合并过程为:

  • 先声明一个合并空间,大小为两个待排序序列的长度和。
  • 对两个已排序序列的起始位置开始比较,较小的元素放入合并空间,指针向后移动到下一个待比较元素。
  • 至到其中一个序列到达列尾,此时,将剩下的元素复制至合并序列的列尾。

逆序对的计算为:

  • 若右边当前元素小于左边当前元素,那么从当前指针指向的左边的元素起,至到左边元素最后的元素,右边当前元素都是最小的,所以存在的逆序对为,从当前左边元素至列尾的元素的长度。
  • 例如: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;
    }
}