常见几种排序之javascript实现

各种排序方法都可以用JS实现,这里只是写了几种常见的JS实现,包括冒泡,选择,插入,希尔,归并,快排以及堆排序。还有各排序算法的时间复杂度和空间复杂度。

AlgorithmAverageBestWorstextra spacestable
冒泡排序O(N^2)O(N)O(N^2)O(1)稳定
直接插入排序O(N^2)O(N)O(N^2)O(1)稳定
折半插入排序O(NlogN)O(NlogN)O(N^2)O(1)稳定
简单选择排序O(N^2)O(N^2)O(N^2)O(1)不稳定
快速排序O(NlogN)O(NlogN)O(N^2)O(logN)~O(N^2)不稳定
归并排序O(NlogN)O(NlogN)O(NlogN)O(N)稳定
堆排序O(NlogN)O(NlogN)O(NlogN)O(1)不稳定


冒泡:

依次比较相邻的两个数,如果不符合排序规则,则调换两个数的位置。这样一遍比较下来,能够保证最大(或最小)的数排在最后一位。

再对最后一位以外的数组,重复前面的过程,直至全部排序完成。

function bubbleSort(arr){
	var len = arr.length;
	for(var i = 0;i<len;i++){
		for(var j = 0;j<len-1-i;j++){
			if(arr[j]>arr[j+1]){  //相邻元素两两比较
				var temp = arr[j+1];  //元素交换
				arr[j+1] = arr[j];
				arr[j]=temp;
			}
		}
	}
	return arr;
}

改进:设置一标志性变量pos,用于记录每趟排序中最后一次进行交换的位置。由于pos位置之后的记录均已交换到位,故在进行下一趟排序时只要扫描到pos位置即可。

function bubbleSort2(arr){
	var i=arr.length-1;  //初始时,最后位置保持不变
	while(i>0){
		var pos=0;//每趟开始时,无记录交换
		for(var j=0;j<i;j++){
			if(arr[j]>arr[j+1]){
				pos=j;//记录交换的位置
				var tmp=arr[j];
				arr[j]=arr[j+1];
				arr[j+1]=tmp;
			}
		}
		i=pos;//为下一趟排序作准备
	}
	return arr;
}

选择:

选择排序(Selection Sort)与冒泡排序类似,也是依次对相邻的数进行两两比较。不同之处在于,它不是每比较一次就调换位置,而是一轮比较完毕,找到最大值(或最小值)之后,将其放在正确的位置,其他数的位置不变 


function selectionSort(arr){
	var len=arr.length;
	var minIndex,temp;
	for(var i=0;i<len-1;i++){
		minIndex=i;
		for(var j=i+1;j<len;j++){
			if(arr[j]<arr[minIndex]){       //寻找最小的数
				minIndex=j;                //将最小数的索引保存
			}
		}
		temp=arr[i];
		arr[i]=arr[minIndex];
		arr[minIndex]=temp;
	}
	return arr;
}

插入排序:

它将数组分成“已排序”和“未排序”两部分,一开始的时候,“已排序”的部分只有一个元素,然后将它后面一个元素从“未排序”部分插入“已排序”部分,从而“已排序”部分增加一个元素,“未排序”部分减少一个元素。以此类推,完成全部排序。


function insertionSort(array) {
	for (var i = 1; i < array.length; i++) {
		var key = array[i];
		var j = i - 1;
		while (j >= 0 && array[j] > key) {
			array[j + 1] = array[j];
			j--;
		}
		array[j + 1] = key;
	}
	return array;
}

改进:

function binaryInsertionSort(array){
	for(var i=1;i<array.length;i++){
		var key=array[i],left=0,right=i-1;
		while(left<=right){
			var middle=parseInt((left+right)/2);
			if(key<array[middle]){
				right=middle-1;
			}else{
				left=middle+1;
			}
		}
		for(var j=i-1;j>=left;j--){
			array[j+1]=array[j];
		}
		array[left]=key;
	}
	return array;
}

 

 


 

 

希尔排序:

先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量=1(<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止


function shellSort(arr) {
	var len = arr.length,
		temp,
		gap = 1;
	while(gap < len/5) {          //动态定义间隔序列
		gap =gap*5+1;
	}
	for (gap; gap > 0; gap = Math.floor(gap/5)) {
		for (var i = gap; i < len; i++) {
			temp = arr[i];
			for (var j = i-gap; j >= 0 && arr[j] > temp; j-=gap) {
				arr[j+gap] = arr[j];
			}
			arr[j+gap] = temp;
		}
	}
	return arr;
}

合并排序:

将两个已经排序的数组合并,要比从头开始排序所有元素来得快。因此,可以将数组拆开,分成n个只有一个元素的数组,然后不断地两两合并,直到全部排序完成


function mergeSort(arr){  //采用自上而下的递归方法
    var len=arr.length;
    if(len<2){
        return arr;
    }
    var middle=Math.floor(len/2),
        left=arr.slice(0,middle),
        right=arr.slice(middle);
    return merge(mergeSort(left),mergeSort(right));
}
function merge(left,right)
{
    var result=[];
    while(left.length&&right.length){
        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;
}

快速排序:

先确定一个“支点”(pivot),将所有小于“支点”的值都放在该点的左侧,大于“支点”的值都放在该点的右侧,然后对左右两侧不断重复这个过程,直到所有排序完成


function qSort(arr){
	if(arr.length==0){
		return [];
	}
	var left=[];
	var right=[];
	var pivot=arr[0];
	for(var i=1;i<arr.length;i++){
		if(arr[i]<pivot){
			left.push(arr[i]);
		}else{
			right.push(arr[i]);
		}
	}
	return qSort(left).concat(pivot,qSort(right));
} 

堆排序

/*将待排序的序列构造成一个最大堆,此时序列的最大值为根节点;依次将根节点与待排序序列的最后一个元素交换

再维护从根节点到该元素的前一个节点为最大堆,如此往复,最终得到一个递增序列*/

function heapSort(array){
        //建堆
        var heapSize=array.length,temp;
        for(var i=Math.floor(heapSize/2)-1;i>=0;i--){
            heapify(array,i,heapSize);
        }
        //堆排序
        for(var j=heapSize-1;j>=1;j--){
            temp=array[0];
            array[0]=array[j];
            array[j]=temp;
            heapify(array,0,--heapSize);
        }
        return array;
}
function heapify(arr,x,len){
        var l=2*x+1,r=2*x+2,largest=x,temp;
        if(l<len&&arr[l]>arr[largest]){
            largest=l;
        }
        if(r<len&&arr[r]>arr[largest]){
            largest=r;
        }
        if(largest!=x){
            temp=arr[x];
            arr[x]=arr[largest];
            arr[largest]=temp;
            heapify(arr,largest,len);
        }
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

关注我获取更多前端资源和经验分享

感谢大佬们阅读,希望大家头发浓密,睡眠良好,情绪稳定,早日实现财富自由~

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值