排序算法及其js实现(二)

希尔插入排序:

其思想是:将记录按下标的一定增量分组,对每组使用直接插入排序算法排序;减少增量,并重复上述步骤,直到增量序列走完。随着增量逐渐减少,每组包含的数字越来越多,当增量减至1时,整个序列恰被分成一组。

我们称{n/2,(n/2)/2...1}为增量序列,希尔排序的增量序列的选择与证明是个数学难题,以上增量序列是比较常用的,也是希尔建议的增量,称为希尔增量,但其实这个增量序列不是最优的。

Javascript代码:

function shellSort(arr){
	var len=arr.length;
//遍历希尔增量序列
	for(var fraction=Math.floor(len/2);fraction>0;fraction=Math.floor(fraction/2)){
//直接处理每个增量对应划分下的数组,而不是单独处理
		for(var i=fraction;i<len;i++){
//直接插入法的代码,将当前元素插入到前面的有序序列中
			for(var j=i-fraction;j>=0&&arr[j]>arr[j+fraction];j-=fraction){
				[arr[j],arr[j+fraction]]=[arr[j+fraction],arr[j]];
			}
		}
	}
	console.log(arr);
}

希尔排序的平均时间复杂度为O(n3/2)。由于其以一定的增量来划分数组,因此,其交换过程并不是相邻的元素,故此排序算法不稳定。

归并排序:

 

其思想是:将原序列拆分成多个子序列,使每个子序列有序,再使子序列段间有序(治)。采用经典的分治策略。

图片的来源https://www.cnblogs.com/chengxiao/p/6194356.html

Javascript实现:

function mergeSort(arr){ //(分)将原数组逐渐拆分,返回的是合并(治)
    var len = arr.length;
    if (len < 2) {
        return arr;
    }
    var middle = Math.floor(len/2);
    var left = arr.slice(0, middle);
    var right = arr.slice(middle); 
//传到merge中的已经是分别有序的两个数组 
return merge(mergeSort(left), mergeSort(right));
}
/*合并过程中考虑三种情况分别对应while和两个if,其一是左右两个数组中都有数值,其二、三是当中有一个没有值*/
function merge(left, right) {
    var result = [];
while (left.length>0 && right.length>0) {
//将两个数组中的值挨个的按照大小放入到新数组中
        if (left[0] <= right[0]) {
            result.push(left.shift());
        } else {
            result.push(right.shift());
        }
    }
    if (left.length)
        result=result.concat(left);
    if (right.length)
        result=result.concat(right);
    return result;
}

归并排序的最好,最坏,平均时间复杂度均为O(nlogn),但其代价是需要额外的内存空间。其交换最深处也是相邻之间的操作,因此是稳定的排序算法。

快速排序:

其思想是: .在待排序的元素任取一个元素作为基准; 将待排序的元素进行分区,比基准元素大的元素放在它的右边,比其小的放在它的左边;对左右两个分区重复以上步骤直到所有元素都是有序的。是不稳定的排序方式,平均时间复杂度是O(nlgn)。

Javascript代码:

方法一:
function quickSort(arr, left, right) {
  if (left == undefined && right == undefined) {
    left = 0;
    right = arr.length - 1;
  }
  var left_index = left; //最左边的值的索引
  var right_index = right; //最右边的值的索引
  var key = 0;
  if (left_index < right_index) {
    //至少有两个待排序的元素
    key = arr[left_index]; //将最左边的值设置为基准值
    while (left_index != right_index) {
      //从左右两边交替扫描,直到left=right
      while (left_index < right_index && arr[right_index] >= key) right_index--; //从右往左扫描,找到第一个比基准元素小的元素
      arr[left_index] = arr[right_index];
      while (left_index < right_index && arr[left_index] <= key) left_index++; //从左往右扫描,找到第一个比基准元素大的元素
      arr[right_index] = arr[left_index];
    }
    arr[right_index] = key; //基准元素落在当前的空位上
    quickSort(arr, left, left_index - 1); //对基准元素左边的元素进行递归排序
    quickSort(arr, right_index + 1, right); //对基准元素右边的进行递归排序
  }
}
var arr = [12, 15, 46, 78, 15, 0, 1, 485, 54, 1, 12];
quickSort(arr);
console.log(arr);
方法二:
function partition(arr, left, right) {
  let mid = left - 1;
  for (let i = left; i < right; i++) {
    if (arr[i] < arr[right]) {
      mid++;
      if (mid !== i) {
        [arr[mid], arr[i]] = [arr[i], arr[mid]];
      }
    }
  }
  mid++;
  [arr[mid], arr[right]] = [arr[right], arr[mid]];
  return mid;
}

function fastSort(arr, left, right) {
  let key = partition(arr, left, right);
  if (key > left) fastSort(arr, left, key - 1);
  if (key < right) fastSort(arr, key + 1, right);
}

arr = [12, 45, 78, 4, 15, 54, 10, 48, 4];
// fastSort(arr, 0, arr.length - 1);
// console.log(arr);


堆排序:

其思想是:将待排序序列构造成一个大顶堆(一般升序采用大顶堆,降序采用小顶堆),此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值