javascript写各种排序算法

在知乎上看到这个题目,就自己写了一下,在这里附上链接,里面有各种排序的动态图,非常形象直观,有助于新手对排序算法理解,链接:常见排序算法之JavaScript实现
首先各种排序算法都会用到的交换函数:

function swap(Array,a,b){
	var temp;
	temp=Array[a];
	Array[a]=Array[b];
	Array[b]=temp;
}

冒泡排序:

function bubbleSort(array){
	var len=array.length;
	var i,j;
	var temp;
	//注意只用执行n-1次排序,因为第n次排序,最小的那个数已经归位了
	for(i=0;i<len-1;i++){
		for(j=0;j<len-i-1;j++){
			if(array[j]>array[j+1]){
				swap(array,j,j+1);
			}
		}
	}
	return array;
}

冒泡排序有两层循环,时间复杂度大概是o(n*n),而且移动次数很多,每次循环都要移动o(n)的次数,感觉还是很伤的,数比较少的时候用比较好。

选择排序:

function selectionSort(array){
	var len=array.length;
	var i,j;
	var min;//记录最小的那个下标
	for(i=0;i<len-1;i++){
		min=i;
		for(j=i+1;j<len;j++){
			if(array[j]<array[min])
				min=j;
		}
		swap(array,i,min);
	}
	return array;
}

有两处和知乎不同,1、我的是len-1层循环,知乎上是len层,我应该是对的,因为最后一个数已经是最大了。2、知乎里写了这个判断,我当时写的时候没想到,加上:

if(i!=min){
	swap(array,i,min);
}

选择排序相比冒泡排序节省了不少移动的次数,每次循环只移动了一次,但也是两层循环,每次循环要从头到尾比较一下,时间复杂度也是O(n*n)

插入排序:

function insertionSort(array){
  var len=array.length;
  var i,j,k;
  for(i=1;i<len;i++){
    if(array[i]<array[0])
        backward(array,0,i);
    for(j=i-1;j>0;j--){
      if(array[i]<array[j]&&array[i]>array[j-1])
        backward(array,j,i);
    }
  }
  return array;
}
function backward(Array,a,b){
	var i;
	var temp=Array[b];
	for(i=b;i>a;i--)
		Array[i]=Array[i-1];
	Array[a]=temp;
}

知乎上的代码比我的简短,区别:1、我增加了一个判断,如果插入的元素比第一个小就直接移动,不用一个一个比较了。2、我写了一个backward()函数移动元素,知乎上的是比较一次移动一次,那个代码逻辑比较清晰,但是我这个效率上面应该会好一点,毕竟不用多次读写。
插入排序的移动次数和冒泡排序差不多,时间复杂度应该也是O(n*n)

归并排序:
已经不想多说什么,这个排序我想了最久,代码:

function merge(array,i){
  var newArray=new Array();
	for(var j=0;j<=array.length;j=j+i){         newArray=newArray.concat(insertionSort(array.slice(j,j+i)));
  }
  return newArray;
}
function mergeSort(array){
   var i=2;
    while(i<=array.length){
      var result=merge(array,i);
      i=i*2;
    }
    if(i>array.length)
      for(var j=0;j<array.length;j++){
        insertionSort(array);
      }
    return array;
}

用slice()方法取得数组的一部分,需要注意的是该方法并不会改变数组,而是返回一个新的子数组,splice()方法会对原数组进行操作。
知乎上的方法比较好,分成左右两个数组,然后再进行递归,我一开始也想用这个方法,后来在分界上搞不定,发现知乎的做法也没有拘泥于分界,比如是这样[1,44,5]->[1],[44,5]而我总想[1,44],[5],其实不用拘泥于这个,做出来就行。然后在两个数组进行合并的时候,知乎是用了两个指针,分别指向两个数组,边比较边移动,我是直接调用了前面写的插入排序。总的来说被知乎写法完爆。。

快速排序:
算法功底差,想的脑仁疼,代码如下:

function fastSort(array,a,b){
	var i,j,p;
	p=a;
	j=p+1;
	for(i=j;i<=b;i++){
		if(array[i]<array[p]){
			if(i!=j)
				swap(array,i,j);
			j++;	
		}
	}
	swap(array,p,j-1);
	if(a<j-1)
		fastSort(array,a,j-1);
	if(j<b)
		fastSort(array,j,b);
	return array;
}

和知乎上代码差别挺大的,我是取第一个数为基准值,然后在原数组上进行的操作,知乎上面是取中间为基准值,然后建两个数组,left和right,比基准小的放在left,比基准大的放在right,然后把left和基准和right连接起来,为什么感觉别人的代码逻辑都很清楚。。。
备注:concat()方法用于连接两个或者多个数组,用法为arrayA.concat(arrayB,arrayC,…)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值