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