几种排序算法的比较
排序算法 | 最差时间复杂度 | 平均时间复杂度 | 空间复杂度 | 稳定度 |
---|---|---|---|---|
冒泡排序 | O(n2) | O(n2) | O(1) | 稳定 |
直接插入排序 | O(n2) | O(n2) | O(1) | 稳定 |
归并排序 | O(nlog2n) | O(nlog2n) | O(n) | 稳定 |
简单选择排序 | O(n2) | O(n2) | O(1) | 不稳定 |
希尔排序 | O(n2) | O(n*log2n) | O(1) | 不稳定 |
堆排序 | O(n*logn) | O(n*logn) | O(1) | 不稳定 |
快速排序 | O(n2) | O(n*log2n) | O(logn)~O(n) | 不稳定 |
冒泡排序
最坏时间复杂度:O(n^2)
空间复杂度:O(1)
稳定性:稳定
第一种方法:
原理:对数组进行遍历,相邻元素根据大小进行交换,每次遍历将最小值推至最前方,然后对剩下的值再次进行比较
Array.prototype.sort = function() {
var len = this.length,
i, j, k, tmp;
for(i=0;i<len;i++) {
for(j=len-1;j>i;j--) { //每轮冒泡将最小的数移到前面
if(this[j] < this[j-1]) {
tmp = this[j] ;
this[j] = this[j-1] ;
this[j-1] = tmp ;
}
}
}
}
var array = [5,4,6,7,8] ;
array.sort() ;
console.log(array) ;
第二种方法:
- 比较相邻的前后二个数据,如果前面数据大于后面的数据,就将二个数据交换。
- 这样对数组的第0个数据到N-1个数据进行一次遍历后,最大的一个数据就“沉”到数组第N-1个位置。
- N=N-1,如果N不为0就重复前面二步,否则排序完成。
Array.prototype.sort = function() {
var len = this.length,
i, j, k, tmp;
for(i=0;i<len;i++) {
for(j=1;j<len-i;j++) { //每轮冒泡将最大的数移到后面
if(this[j] < this[j-1]) {
tmp = this[j] ;
this[j] = this[j-1] ;
this[j-1] = tmp ;
}
}
}
}
var array = [5,4,6,7,8] ;
array.sort() ;
console.log(array) ;
优化
如果有100个数的数组,仅前面10个无序,后面90个都已排好序且都大于前面10个数字,那么在第一趟遍历后,最后发生交换的位置必定小于10,且这个位置之后的数据必定已经有序了,记录下这位置,第二次只要从数组头部遍历到这个位置就可以了。
Array.prototype.sort = function() {
var len = this.length,
flag = len, //用于记录最后一次交换的位置
j, k, tmp;
while(flag > 0) {
k = flag ;
flag = 0 ;
for(j=1;j<k;j++) {
if(this[j-1] > this[j]) {
tmp = this[j-1] ;
this[j-1] = this[j] ;
this[j] = tmp ;
flag = j ;
}
}
}
}
var array = [5,4,6,7,8,9,10,11,12,13,14,15,16,17,18,19] ;
array.sort() ;
console.log(array) ;
插入排序
最坏时间复杂度:O(n^2)
平均时间复杂度:O(n^2)
空间复杂度:O(1)
稳定性:稳定
原理:从数组第二个值开始,依次将后续的数值经过比较与前面排序后的序列比较后插入。
方法一:
Array.prototype.sort = function() {
var len = this.length,
i, j, tmp ;
for(i=1;i<len;i++) {
tmp = this[i] ;
j = i - 1 ;
while(j>=0 && this[j] > tmp) {
this[j+1] = this[j] ;
j-- ;
}
this[j+1] = tmp ;
}
}
var array = [5,17,4,16,6,18,12,8,9,11,14,7,15,10,13,19] ;
array.sort() ;
console.log(array) ;
方法二:
Array.prototype.sort = function() {
var len = this.length,
i, j, tmp ;
for(i=1;i<len;i++) {
for(j=i-1;j>=0&&this[j]>this[j+1];j--) {
tmp = this[j] ;
this[j] = this[j+1] ;
this[j+1] = tmp ;
}
}
}
var array = [5,17,4,16,6,18,12,8,9,11,14,7,15,10,13,19] ;
array.sort() ;
console.log(array) ;
归并排序
最坏时间复杂度:O(nlogn)
平均时间复杂度:O(nlogn)
空间复杂度:O(n)
稳定性:稳定
基本思路就是将数组分成二组A,B,如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。
选择排序
最坏时间复杂度:O(n^2)
平均时间复杂度:O(n^2)
空间复杂度:O(1)
稳定性:不稳定
原理:与冒泡排序类似,只不过选择排序不是通过相邻元素交换而将最小值“冒泡”到顶端,而是从数组第一个元素开始,与后面的的元素进行比较,如果后面的元素都比他大,则不需要交换,如果有比其小的,则两个值相互交换。
Array.prototype.sort = function() {
var len = this.length,
i, j, k, tmp ;
for(i=0;i<len;i++) {
k = i ;
for(j=i+1;j<len;j++) {
if(array[j] < array[k]) {
k = j ;
}
}
if(k != i) {
tmp = this[i] ;
this[i] = this[k] ;
this[k] = tmp ;
}
}
}
var array = [5,17,4,16,6,18,12,8,9,11,14,7,15,10,13,19] ;
array.sort() ;
console.log(array) ;
希尔排序
最坏时间复杂度:O(n^2)
平均时间复杂度:O(nlogn)
空间复杂度:O(1)
稳定性:不稳定
基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。
Array.prototype.sort = function() {
var len = this.length,
i, j, tmp, gap ;
for(gap=len/2;gap>0;gap/=2) {
for(i=gap;i<len;i++) {
for(j=i-gap;j>=0&&this[j]>this[j+gap];j-=gap) {
tmp = this[j+gap] ;
this[j+gap] = this[j] ;
this[j] = tmp ;
}
}
}
}
var array = [5,17,4,16,6,18,12,8,9,11,14,7,15,10,13,19] ;
array.sort() ;
console.log(array) ;
堆排序
最坏时间复杂度:O(n*logn)
平均时间复杂度:O(n*logn)
空间复杂度:O(1)
稳定性:不稳定
首先可以看到堆建好之后堆中第0个数据是堆中最小的数据。取出这个数据再执行下堆的删除操作。这样堆中第0个数据又是堆中最小的数据,重复上述步骤直至堆中只有一个数据时就直接取出这个数据。
由于堆也是用数组模拟的,故堆化数组后,第一次将A[0]与A[n - 1]交换,再对A[0…n-2]重新恢复堆。第二次将A[0]与A[n – 2]交换,再对A[0…n - 3]重新恢复堆,重复这样的操作直到A[0]与A[1]交换。由于每次都是将最小的数据并入到后面的有序区间,故操作完成后整个数组就有序了。
注意使用最小堆排序后是递减数组,要得到递增数组,可以使用最大堆。
快速排序
最坏时间复杂度:O(n^2)
平均时间复杂度:O(n*logn)
空间复杂度:O(logn)~O(n)
稳定性:不稳定
该方法的基本思想是:
- 先从数列中取出一个数作为基准数。
- 分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
- 再对左右区间重复第二步,直到各区间只有一个数。
function quicksort(array,left,right) {
if(left < right) {
var i = left,
j = right,
x = array[left] ;
while(i < j) {
while(i<j && array[j]>=x) {
j-- ;
}
if(i<j){
array[i++] = array[j] ;
}
while(i<j && array[i]<x) {
i++;
}
if(i<j) {
array[j--] = array[i] ;
}
}
array[i] = x ;
quicksort(array,left,i-1) ;
quicksort(array,i+1,right) ;
}
}
var array = [72,6,57,88,60,42,83,73,88,85,60] ;
quicksort(array,0,10) ;
console.log(array) ;