常见几种排序之javascript实现
2017-04-24 15:58
375 查看
各种排序方法都可以用JS实现,这里只是写了几种常见的JS实现,包括冒泡,选择,插入,希尔,归并,快排以及堆排序。还有各排序算法的时间复杂度和空间复杂度。
冒泡:
依次比较相邻的两个数,如果不符合排序规则,则调换两个数的位置。这样一遍比较下来,能够保证最大(或最小)的数排在最后一位。
再对最后一位以外的数组,重复前面的过程,直至全部排序完成。
改进:设置一标志性变量pos,用于记录每趟排序中最后一次进行交换的位置。由于pos位置之后的记录均已交换到位,故在进行下一趟排序时只要扫描到pos位置即可。
选择:
选择排序(Selection Sort)与冒泡排序类似,也是依次对相邻的数进行两两比较。不同之处在于,它不是每比较一次就调换位置,而是一轮比较完毕,找到最大值(或最小值)之后,将其放在正确的位置,其他数的位置不变
插入排序:
它将数组分成“已排序”和“未排序”两部分,一开始的时候,“已排序”的部分只有一个元素,然后将它后面一个元素从“未排序”部分插入“已排序”部分,从而“已排序”部分增加一个元素,“未排序”部分减少一个元素。以此类推,完成全部排序。
改进:
希尔排序:
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量=1(<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止
合并排序:
将两个已经排序的数组合并,要比从头开始排序所有元素来得快。因此,可以将数组拆开,分成n个只有一个元素的数组,然后不断地两两合并,直到全部排序完成
快速排序:
先确定一个“支点”(pivot),将所有小于“支点”的值都放在该点的左侧,大于“支点”的值都放在该点的右侧,然后对左右两侧不断重复这个过程,直到所有排序完成
堆排序
/*将待排序的序列构造成一个最大堆,此时序列的最大值为根节点;依次将根节点与待排序序列的最后一个元素交换
再维护从根节点到该元素的前一个节点为最大堆,如此往复,最终得到一个递增序列*/
Algorithm | Average | Best | Worst | extra space | stable |
冒泡排序 | O(N^2) | O(N) | O(N^2) | O(1) | 稳定 |
直接插入排序 | O(N^2) | O(N) | O(N^2) | O(1) | 稳定 |
折半插入排序 | O(NlogN) | O(NlogN) | O(N^2) | O(1) | 稳定 |
简单选择排序 | O(N^2) | O(N^2) | O(N^2) | O(1) | 不稳定 |
快速排序 | O(NlogN) | O(NlogN) | O(N^2) | O(logN)~O(N^2) | 不稳定 |
归并排序 | O(NlogN) | O(NlogN) | O(NlogN) | O(N) | 稳定 |
堆排序 | O(NlogN) | O(NlogN) | O(NlogN) | O(1) | 不稳定 |
依次比较相邻的两个数,如果不符合排序规则,则调换两个数的位置。这样一遍比较下来,能够保证最大(或最小)的数排在最后一位。
再对最后一位以外的数组,重复前面的过程,直至全部排序完成。
function bubbleSort(arr){ var len = arr.length; for(var i = 0;i<len;i++){ for(var j = 0;j<len-1-i;j++){ if(arr[j]>arr[j+1]){ //相邻元素两两比较 var temp = arr[j+1]; //元素交换 arr[j+1] = arr[j]; arr[j]=temp; } } } return arr; }
改进:设置一标志性变量pos,用于记录每趟排序中最后一次进行交换的位置。由于pos位置之后的记录均已交换到位,故在进行下一趟排序时只要扫描到pos位置即可。
function bubbleSort2(arr){ var i=arr.length-1; //初始时,最后位置保持不变 while(i>0){ var pos=0;//每趟开始时,无记录交换 for(var j=0;j<i;j++){ if(arr[j]>arr[j+1]){ pos=j;//记录交换的位置 var tmp=arr[j]; arr[j]=arr[j+1]; arr[j+1]=tmp; } } i=pos;//为下一趟排序作准备 } return arr; }
选择:
选择排序(Selection Sort)与冒泡排序类似,也是依次对相邻的数进行两两比较。不同之处在于,它不是每比较一次就调换位置,而是一轮比较完毕,找到最大值(或最小值)之后,将其放在正确的位置,其他数的位置不变
function selectionSort(arr){ var len=arr.length; var minIndex,temp; for(var i=0;i<len-1;i++){ minIndex=i; for(var j=i+1;j<len;j++){ if(arr[j]<arr[minIndex]){ //寻找最小的数 minIndex=j; //将最小数的索引保存 } } temp=arr[i]; arr[i]=arr[minIndex]; arr[minIndex]=temp; } return arr; }
插入排序:
它将数组分成“已排序”和“未排序”两部分,一开始的时候,“已排序”的部分只有一个元素,然后将它后面一个元素从“未排序”部分插入“已排序”部分,从而“已排序”部分增加一个元素,“未排序”部分减少一个元素。以此类推,完成全部排序。
function insertionSort(array) { for (var i = 1; i < array.length; i++) { var key = array[i]; var j = i - 1; while (j >= 0 && array[j] > key) { array[j + 1] = array[j]; j--; } array[j + 1] = key; } return array; }
改进:
function binaryInsertionSort(array){ for(var i=1;i<array.length;i++){ var key=array[i],left=0,right=i-1; while(left<=right){ var middle=parseInt((left+right)/2); if(key<array[middle]){ right=middle-1; }else{ left=middle+1; } } for(var j=i-1;j>=left;j--){ array[j+1]=array[j]; } array[left]=key; } return array; }
希尔排序:
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量=1(<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止
function shellSort(arr) { var len = arr.length, temp, gap = 1; while(gap < len/5) { //动态定义间隔序列 gap =gap*5 b9fb +1; } for (gap; gap > 0; gap = Math.floor(gap/5)) { for (var i = gap; i < len; i++) { temp = arr[i]; for (var j = i-gap; j >= 0 && arr[j] > temp; j-=gap) { arr[j+gap] = arr[j]; } arr[j+gap] = temp; } } return arr; }
合并排序:
将两个已经排序的数组合并,要比从头开始排序所有元素来得快。因此,可以将数组拆开,分成n个只有一个元素的数组,然后不断地两两合并,直到全部排序完成
function mergeSort(arr){ //采用自上而下的递归方法 var len=arr.length; if(len<2){ return arr; } var middle=Math.floor(len/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&&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; }
快速排序:
先确定一个“支点”(pivot),将所有小于“支点”的值都放在该点的左侧,大于“支点”的值都放在该点的右侧,然后对左右两侧不断重复这个过程,直到所有排序完成
function qSort(arr){ if(arr.length==0){ return []; } var left=[]; var right=[]; var pivot=arr[0]; for(var i=1;i<arr.length;i++){ if(arr[i]<pivot){ left.push(arr[i]); }else{ right.push(arr[i]); } } return qSort(left).concat(pivot,qSort(right)); }
堆排序
/*将待排序的序列构造成一个最大堆,此时序列的最大值为根节点;依次将根节点与待排序序列的最后一个元素交换
再维护从根节点到该元素的前一个节点为最大堆,如此往复,最终得到一个递增序列*/
function heapSort(array){ //建堆 var heapSize=array.length,temp; for(var i=Math.floor(heapSize/2)-1;i>=0;i--){ heapify(array,i,heapSize); } //堆排序 for(var j=heapSize-1;j>=1;j--){ temp=array[0]; array[0]=array[j]; array[j]=temp; heapify(array,0,--heapSize); } return array; } function heapify(arr,x,len){ var l=2*x+1,r=2*x+2,largest=x,temp; if(l<len&&arr[l]>arr[largest]){ largest=l; } if(r<len&&arr[r]>arr[largest]){ largest=r; } if(largest!=x){ temp=arr[x]; arr[x]=arr[largest]; arr[largest]=temp; heapify(arr,largest,len); } }
相关文章推荐
- 数组几种常见排序的javascript实现
- Java实现几种常见排序方法(下)
- Java实现几种常见排序方法(上)
- 【转】Java实现几种常见排序方法
- Java实现几种常见排序方法
- Java实现几种常见排序方法
- Java实现几种常见排序方法(下)
- Java实现几种常见排序方法
- Java实现几种常见排序方法
- Java实现几种常见排序方法
- 几种常见排序算法的JavaScript实现
- Java实现几种常见排序方法(下) .
- Java实现几种常见排序方法
- 几种常见的排序C实现
- Java实现几种常见排序方法
- Java实现几种常见排序方法(下)
- 几种常见排序算法之Java实现(插入排序、希尔排序、冒泡排序、快速排序、选择排序、归并排序)
- Java实现几种常见排序方法
- Java实现几种常见排序方法(上)
- Java实现几种常见排序方法