美文网首页
【手撕代码7】排序算法,查找

【手撕代码7】排序算法,查找

作者: 一包 | 来源:发表于2019-04-03 17:03 被阅读0次
  • 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。

  • 不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。

  • 时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。

  • 空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。

交换(使用解构赋值)

arr1=[1,2];
arr2=[2,3];
[arr1,arr2]=[arr2,arr1];
console.log(arr1);//2,3

检查是否为数组,交换位置

function checkArr(arr){
  return Array.isArray(arr);
}
function swap(arr,left,right){
  [arr[left],arr[right]]=[arr[right],arr[left]];
}

冒泡排序

  • 冒泡排序的原理如下,从第一个元素开始,把当前元素和下一个索引元素进行比较。如果当前元素大,那么就交换位置,重复操作直到比较到最后一个元素,那么此时最后一个元素就是该数组中最大的数。下一轮重复以上操作,但是此时最后一个元素已经是最大数了,所以不需要再比较最后一个元素,只需要比较到 length - 2 的位置。
function bubble(arr){
  if(!checkArr(arr)){
    console.log("not arr");
  }
  for(let i=0;i<arr.length-1;i++){
    //写在第一个for循环里,是为了,每轮比较初始化bool变量变为true。
    let flag=true;
    for(let j=0;j<arr.length-1-i;j++){//每一轮都会比较出一个最大值,然后后一轮没有必要再比较了,所以没比较一轮,就少比较一次
      if(arr[j]>arr[j+1]){
        swap(arr,j,j+1);
        flag=false
      } 
    }
    if(flag){//,如果本轮比较没有任何元素相互交换位置,那么说明已经比较完成,可以跳出循环
    break;
    }
  }
  return arr;
}
var arr=[2,1,5,6,3];
console.log(bubble(arr));
  • 该算法的操作次数是一个等差数列 n + (n - 1) + (n - 2) + 1 ,去掉常数项以后得出时间复杂度是 O(n * n)

选择排序

  • 选择排序的原理如下。遍历数组,设置最小值的索引为 0,如果取出的值比当前最小值小,就替换最小值索引,遍历完成后,将第一个元素和最小值索引上的值交换。如上操作后,第一个元素就是数组中的最小值,下次遍历就可以从索引 1 开始重复上述操作。
function select(arr){
  if(!checkArr(arr)){
    console.log("not arr");
  }
  for(let i=0;i<arr.length-1;i++){
      let minindex=i;
    for(j=i+1;j<arr.length;j++){
      minindex=arr[j]<arr[minindex]?j:minindex;
      }
    swap(arr,i,minindex);
    
  }
  return arr;
}
var arr=[2,1,5,6,3];
console.log(select(arr));

快排

var quickSort = function(arr) {

  if (arr.length <= 1) { return arr; }

  var pivotIndex = Math.floor(arr.length / 2);

  var pivot = arr.splice(pivotIndex, 1)[0];

  var left = [];

  var right = [];

  for (var i = 0; i < arr.length; i++){

    if (arr[i] < pivot) {

      left.push(arr[i]);

    } else {

      right.push(arr[i]);

    }

  }

  return quickSort(left).concat([pivot], quickSort(right));

};

归并排序

  • 归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
function mergeSort(arr){
  //设置终止的条件
  if(arr.length<2){
    return arr;
  }
  //设置中间值
  var middle=Math.floor(arr.length/2);
  var left=arr.slice(0,middle);
  var right=arr.slice(middle);
  if(left=="undefined"&&right=="undefined"){
    return false;
  }
  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;
}

// 测试数据
var nums=[6,10,1,9,4,8,2,7,3,5];
console.log(mergeSort(nums));
image

二分查找

  • 二分查找,折半查找(有序数组中查找特定元素)
  • 首先,从有序数组的中间的元素开始搜索,如果该元素正好是目标元素(即要查找的元素),则搜索过程结束,否则进行下一步。
  • 如果目标元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半区域查找,然后重复第一步的操作。
    //如果某一步数组为空,则表示找不到目标元素
//二分查找,折半查找(有序数组中查找特定元素)
//首先,从有序数组的中间的元素开始搜索,如果该元素正好是目标元素(即要查找的元素),则搜索过程结束,否则进行下一步。
//如果目标元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半区域查找,然后重复第一步的操作。
//如果某一步数组为空,则表示找不到目标元素。
function binSearch(arr,data){
  var low=0;
  var high=arr.length-1;
   while(low<=high){
     var middle=Math.floor((low+high)/2);
     if(arr[middle]<data){
       low=middle+1;
     }else if(arr[middle>data]){
       high=middle-1;
     }else{
       return middle;
     }
   }
  return -1;
}
var arr=[3,6,9,10,70];
console.log(binSearch(arr, 10))

相关文章

网友评论

      本文标题:【手撕代码7】排序算法,查找

      本文链接:https://www.haomeiwen.com/subject/ffwzbqtx.html