排序算法是基础算法,虽然关键在于算法的思想而不是语言,但还是决定借助算法可视化工具结合自己常用的语言实现一下

1.冒泡排序

基本思路:依次比较两两相邻的两个数,前面数比后面数小,不变。前面数比后面数大,交换顺序。一轮下来,最后的一个数是最大的数。

                  外循环每增加一次,内循环减少一次。

图形展示:

function bubbleSort(arr){
  for (var i = 0; i < arr.length; i++) {
    for (var j = 0; j< arr.length-i-1; j++) {
      if(arr[j]>arr[j+1]){
        var temp=arr[j];
        arr[j]=arr[j+1];
        arr[j+1]=temp;
      }
    }  
  }
  return arr;
}

 

2.选择排序

基本思路:循环数组,找出最小的值,和第一个交换位置;然后在剩下的数中,找出第二小的数,放在第二个;依次类推。

图形展示:

function selectSort(arr){
  for( var i=0;i<arr.length-1;i++){
    var min=i;
    for(var j=i+1;j<arr.length;j++){
      if(arr[j]<arr[min]){
        min=j;
      }
      if(i!=min){
        var temp=arr[i];
        arr[i]=arr[min];
        arr[min]=temp;
      }
    }
  }
  return arr;
}

 

3.插入排序

基本思路:把数组分为[已排序]和[未排序]两部分,第一个数为[已排序],其余为[未排序];

                     从[未排序]中抽出一个数,和[已排序]部分比较,插入到合适位置。

图形展示:

function insert(arr){
  for(var i=0;i<arr.length;i++){
   var value=arr[i];   //i表示未排序部分的当前位置,value表示当前比较的元素
   for(var j=i-1;j>=0&&value<arr[j];j--){  //j表示已排序部分的当前位置
      arr[j+1]=arr[j];
   }
   arr[j+1]=value;
  }
return arr; 
}

4、合并排序

基本思路:不断的将数组对半分,只到每个数组只有一个元素;

                 将分出来的部分重新合并,合并的时候按顺序排列。

图形展示:

方法一

function mergeSort(arr){
  if(arr.length<2){
    return arr;
  }
  var middle=Math.floor(arr.length/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>0 && right.length>0){
    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());
  // }
  if(left.length){
    result=result.concat(left);
  }
  if(right.length){
    result=result.concat(right)
  }
  return result;
}

方法二

function mergeSort(arr){
    //只有一个数的时候退出递归
    if(arr.length<2){
        return arr;
    }
    //递归
    var middle=Math.floor(arr.length/2),
        left=arr.slice(0,middle),
        right=arr.slice(middle);
    
    return merge(mergeSort(left),mergeSort(right))    
}

//将两个数组合并;合并的时候按从小到大的顺序 
function merge(left,right){
    var left_index=0,
    right_index=0,
    result=[];
    while(left_index<left.length&&right_index<right.length){
        if(left[left_index]<right[right_index]){
            result.push(left[left_index++]);
        }else{
            result.push(right[right_index++]);
        }
    }
    return result.concat(left.slice(left_index),right.slice(right_index));

5.快速排序

基本思路:以一个数为基准,比基准小的数放到左边,比基准大的值放右边;递归进行,不能再分后退出递归

图形展示:

方法一:以中间值为基准,这种方法创建了两个新数组,暂用空间

function quickSort(arr){
    if(arr.length<2){
        return arr;
    }
    var base=Math.floor(arr.length/2);
    var pirot=arr.splice(base,1)[0];    //基准值
    var left=[],
    right=[];
    
    for(var i=0;i<arr.length;i++){
        if(arr[i]<pirot){
            left.push(arr[i]);
        }else{
            right.push(arr[i]);
        }
    }
    // 递归,把数组合并在一起把数组合并在一起
    return quickSort(left).concat([pirot],quickSort(right));
}

方法二,以第一个值为基准,先向从右往左,找比它小的值;再从左向右找比它大的值

var quickSort = function(arr, head, tail) {
  if (head > tail) {
      return;
    }
    var i=head;
    var j=tail;
    var Pivot=arr[i]; /**< 选取基准值 */
    while (i<j) {
        //使用j,从序列最右端开始扫描,直到遇到比基准值小的数
        while ((i<j) && (Pivot <= arr[j])) {
          j--;
        }
        //交换位置
        if (i<j) {
          arr[i++]=arr[j];
        }

        //使用i,从序列最左端开始扫描,直到遇到比基准值大的数
        while ( (i<j) && (Pivot >=arr[i]) ) {
          i++;
        }
        //交换位置
        if (i<j) {
          arr[j--]=arr[i];
        }
    }
  
    //最后填入基准值放入合适的位置
    arr[j]=Pivot;
    //对基准值两边序列进行排序的递归调用
    quickSort(arr, head, i-1);
    quickSort(arr, i+1, tail);
    return arr;
}