算法:基于比较的排序算法

1、冒泡排序:

(1)平均时间复杂度:O(n2)

(2)最好时间复杂度:O(n)

(3)最坏时间复杂度:O(n2)

(5)空间复杂度:O(1)

(5)稳定性:稳定

(6)JavaScript实现:

function bubble ( arr ) {
    var len = arr.length;
    var tmp;
    //  外层循环负责控制排序的趟数
    for(var i = 0; i < len - 1; i++){
       // 内层循环负责进行一趟排序
       for(var j = 0; j < len - 1 - i; j++){
          if(arr[j + 1] < arr[j]){
              tmp = arr[j];
              arr[j] = arr[j + 1];
              arr[j + 1] = tmp;
          };
       };
    };
    return arr;
};

2、选择排序:

(1)平均时间复杂度:O(n2)

(2)最好时间复杂度:O(n2)

(3)最坏时间复杂度:O(n2)

(4)空间复杂度:O(1)

(5)稳定性:不稳定

(6)JavaScript实现:

function select( arr ) {
   var len = arr.length;
   // 外层循环需要进行len - 1趟排序
   for(var i = 0; i < len - 1; i++){
      var index = i;
      var min = arr[i];
      var tmp;
      // 内层循环从未排序的数组元素中比较出最小的一个
      for(var j = i + 1; j < len; j++){
         if(min > arr[j]){
            index = j;
            min = arr[j];
         };
      };
      // 将其放在排序后的数组元素的最后
      tmp = arr[i];
      arr[i] = min;
      arr[index] = tmp;
   };
};

3、插入排序:

(1)平均时间复杂度:O(n2)

(2)最好时间复杂度:O(n)

(3)平均时间复杂度:O(n2)

(4)空间复杂度:O(1)

(5)稳定性:稳定

(6)JavaScript实现:

  遍历数组,遍历到i时,a0,a1...ai-1是已经排好序的,取出ai,从ai-1开始向前和每个比较大小,如果小于,则将此位置元素向后移动,继续先前比较,如果不小于,则放到正在比较的元素之后。可见相等元素比较是,原来靠后的还是拍在后边,所以插入排序是稳定的。

  当待排序的数据基本有序时,插入排序的效率比较高,只需要进行很少的数据移动。

function insert ( arr ) { 
   var len = arr.length;
   var tmp;
   for(var i = 1; i < len; i++){
      // 取出当前的数组元素
      tmp = arr[i];
      for(var j = i - 1; j >= 0; j--){
         if (arr[j] > tmp) {
            arr[j+1] = arr[j];
         } else {
       break;
     };
      };
      // 插入取出的数组元素
      arr[j+1] = tmp;
   };
   return arr;
}

4、希尔排序:

(1)平均时间复杂度:O(nlogn) ~ O(n2)

(2)最好时间复杂度:O(n1.3)

(3)最坏时间复杂度:O(n2)

(4)空间复杂度:O(1)

(5)稳定性:不稳定

(6)JavaScript实现:

// 插入排序
function sort( arr, di ){
   for(var i = di; i < arr.length; i++){
      var guard = arr[i];
      for(var j =i -di; j >= 0 && guard < arr[j]; j -= di){
         arr[j+di] = arr[j];
      };
      arr[j+di] = guard;
   };
   return arr;
}

//  希尔排序,本质上是以不同的步长多次进行插入排序
//  步长的选择对希尔排序的效率有显著影响
function shell ( arr ) {
  var di = parseInt( arr.length / 2 );
  while ( di >= 1) {
      arr = sort( arr, di);
      di = parseInt( di / 2 );
  };
  return arr;
};

5、归并排序:

(1)平均时间复杂度:O(nlogn)

(2)最好时间复杂度:O(nlogn)

(3)最坏时间复杂度:O(nlogn)

(4)空间复杂度:O(n)

(5)稳定性:稳定

(6)JavaScript实现:

// 对被归并的左右两个数组进行归并排序
// 被输入的左右两个数组,都是有序的。
function merge (left, right){
   var l = 0,
         r = 0;
   var result = [];
   // 对左右两个数组的首项,进行比较,较小的推入栈中。
   while(l < left.length && r < right.length){
      if(left[l] < right[r]){
         result.push( left[l] );
         l += 1;
      } else {
         result.push( right[r] );
         r += 1;
      };
   };
   // 经过上面的比较,左右两个数组,必定有一个数组比较完毕,一个没有比较完毕。
   // 但是,在不同情况的递归层,有不同的表现,故而将二者未比较的元素都连接到result中。
   // 由于,左右两个数组在输入前就是有序的,剩余未经比较的数组元素也是有序的,且都大于之前经过比较的数组元素,故而可以将其连接到result。
   // 下方的代码,实质上是将左右数组中,未经比较的数组元素连接到result。
   result = result.concat( left.slice(l) );
   result = result.concat( right.slice(r) );
   return result;
};

function mergeSort ( arr ){
   var len = arr.length;
   // 结束递归
   if(len <= 1){
      return arr;
   };
   // 切割数组,并对切割后的数组进行递归操作
   var middle = Math.floor( len/2 );
   var left = mergeSort( arr.slice(0, middle) );
   var right = mergeSort( arr.slice(middle) );
   // 完成递归后,进行归并
   return merge(left, right);
}

6、快速排序:
简称快排,时间复杂度并不固定,如果在最坏情况下(元素刚好是反向的)速度比较慢,达到 O(n^2)(和选择排序一个效率),但是如果在比较理想的情况下时间复杂度 O(nlogn)。

快排也是一个分治的算法,快排算法每次选择一个元素并且将整个数组以那个元素分为两部分,根据实现算法的不同,元素的选择一般有如下几种:

永远选择第一个元素
永远选择最后一个元素
随机选择元素
取中间值
整个快速排序的核心是分区(partition),分区的目的是传入一个数组和选定的一个元素,把所有小于那个元素的其他元素放在左边,大于的放在右边。

(1)平均时间复杂度:O(nlogn)

(2)最好时间复杂度:O(nlogn)

(3)最坏时间复杂度:O(n2)

(4)空间复杂度:O(logn) ~ O(n)

(5)稳定性:不稳定

(6)JavaScript实现:

function quick ( arr ) {
   var less = [],
         pivotList = [],
         more = [],
         result = [],
         len = arr.length;
   // 结束递归
   if(len <= 1){
       return arr;
   };

   // 与基准对比,将数组划分为小,中,大三组
   var pivot = arr[0];
   for(var i = 0; i <len; i++){
      if(arr[i] < pivot){
         less.push(arr[i]);
      } else if(arr[i] > pivot){
         more.push(arr[i]);
      } else {
         pivotList.push(arr[i]);
      };
   };
   // 递归地对划分出的小、大两个组进行快速排序
   less = quick(less);
   more = quick(more);
   // 将排序好的小,中,大三组连接起来 
   result = result.concat(less, pivotList, more);
   return result;
}

为什么哈希表的时间复杂度是常数阶O(1)

在哈希表中进行添加,删除,查找等操作,性能十分之高,不考虑哈希冲突的情况下,仅需一次定位即 可完成,时间复杂度为O(1),哈希表是如何实现达到惊艳的常数阶O(1)的呢?
我们知道,数据结构的物理存储结构只有两种:顺序存储结构和链式存储结构(像栈,队列,树,图等是从逻辑结构去抽象的,映射到内存中,也这两种物理组织形式),在数组中根据下标查找某个元素,一次定位就可以达到,哈希表利用了这种特性,哈希表的主干就是数组。
比如我们要新增或查找某个元素,我们通过把当前元素的关键字 通过某个函数映射到数组中的某个位置,通过数组下标一次定位就可完成操作。
存储位置 = f(关键字)
其中,这个函数f一般称为哈希函数,这个函数的设计好坏会直接影响到哈希表的优劣。
查找操作同理,先通过哈希函数计算出实际存储地址,然后从数组中对应地址取出即可。
所以,哈希表的时间复杂度就是常数阶O(1)。

在这里插入图片描述
https://blog.csdn.net/donggua3694857/article/details/52432906

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值