js实现十种排序算法

来源:互联网 发布:淘宝欧缇丽旗舰店真假 编辑:程序博客网 时间:2024/06/03 10:02
排序算法平均情况最好情况最坏情况空间复杂度稳定性冒泡排序O(n2)O(n)O(n2)O(1)稳定快速排序O(nlog2n)O(nlog2n)O(n2)O(log2n)~O(n)不稳定直接插入排序O(n2)O(n)O(n2)O(1)稳定希尔排序O(nlog2n)~O(n2)O(n1.3)O(n2)O(1)不稳定简单选择排序O(n2)O(n2)O(n2)O(1)不稳定堆排序O(nlog2n)O(nlog2n)O(nlog2n)O(1)不稳定归并排序O(nlog2n)O(nlog2n)O(nlog2n)O(n)稳定基数排序O(d(n+m))O(d(n+m))O(d(n+m))O(m)稳定

①当待排序记录个数n较大,关键码分布较随机,且对稳定性不作要求,采用快速排序。
②当待排序记录个数n较大,内存空间允许,且要求排序稳定,采用归并排序。
③当待排序记录个数n较大,关键码分布可能出现正序或者逆序的情况,且对稳定性不作要求,采用堆排序或者归并排序
④当待排序记录个数n较大,而只是找出最小的前几个记录,采用堆排序或简单选择排序。
⑤当待排序记录个数n较小,记录已基本有序,且要求稳定时,采用直接插入排序。
⑥当待排序记录个数n较小,记录所含数据项较多,所占存储空间较大时,采用简单选择排序
⑦快速排序和归并排序在待排序记录个数n值较小时的性能不如直接插入排序。


1.冒泡排序

function BubbleSort(a){  let exchange = a.length-1;  while (exchange!=0) {    let bound = exchange;    exchange = 0;    for (let j=0;j<bound;j++) {      if (a[j]>a[j+1]) {        let temp = a[j];        a[j] = a[j+1];        a[j+1] = temp;        exchange = j;      }    }  }  return a;}

冒泡排序(属于交换排序):
时间复杂度 平均情况:O(n^2) 最好情况:O(n) 最坏情况:O(n^2)
空间复杂度 O(1)
稳定
基本思想:两两比较相邻数值,如果反序则交换位置。


2.快速排序

function Partition(arr,first,end){  let i =first;  let j =end;  while(i<j){    while(i<j && arr[i]<=arr[j])j--;//右侧扫描    if (i<j) {      let temp = arr[i];      arr[i] = arr[j];      arr[j] = temp;      i++;    }    while (i<j && arr[i]<=arr[j])i++;//左侧扫描    if(i<j) {      let temp = arr[i];      arr[i] = arr[j];      arr[j] = temp;      j--;    }  }  return i;}function QuickSort(a,first,end){  if(first<end) {    let pivot = Partition(a,first,end);    QuickSort(a,first,pivot-1);    QuickSort(a,pivot+1,end);  }  return a;}

快速排序(属于交换排序),
时间复杂度
平均情况:O(nlog2n)
最好情况:O(nlog2n)
最坏情况:O(n2)
空间复杂度 O(log2n)~O(n)
不稳定
基本思想:首先选一个轴值(pivot,即比较的基准),将待排序记录分成独立的两部分,左侧记录的关键码均小于等于轴值,右侧记录的关键码均大于等于关键码。然后分别对这两部分重复上述过程,知道整个序列有序。快排是对冒泡的改良,属于交换排序


3.直接插入排序

function InsertSort(a){  for (let i = 1; i < a.length; i++) {    let temp = a[i];    for (j=i-1;a[j]>temp;j--) {      a[j+1] = a[j];    }    a[j+1] = temp;  }  return a;}

直接插入排序
时间复杂度
平均情况:O(n2)
最好情况:O(n)
最坏情况:O(n2)
空间复杂度 O(1)
稳定
基本思想:依次将待排序中的每一个记录插入到一个已排好序的序列中,直到全部记录都排好序。


4.希尔排序

function ShellSort(a){  for(let d=parseInt(a.length/2);d>0;d=parseInt(d/2))    {        for(let i=d;i<a.length;i++)        {            let temp=a[i];let j;            for(j=i-d;j>=0 && temp<a[j];j=j-d)            {                a[j+d]=a[j];            }            a[j+d]=temp;        }    }  return a;}

希尔排序
时间复杂度
平均情况:O(nlog2n)~O(n2)
最好情况:O(n1.3)
最坏情况:O(n2)
空间复杂度 O(1)
不稳定
基本思想:对直接插入排序的改良。先将整个待排序记录序列分割成若干个子序列,在子序列内分别进行直接插入排序待到整个序列基本有序时,再对全体记录进行一次直接插入排序

注意:出现除法运算,注意使用parseInt将其转化为整数,否则会出错


5.简单选择排序

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

简单选择排序
时间复杂度
平均情况:O(nlog2n)~O(n2)
最好情况:O(n^1.3)
最坏情况:O(n^2)
空间复杂度 O(1)
不稳定
基本思想:第i趟排序在待排序序列 r[i]~r[n](1<=i<=n-1)中选取关键码最小的记录,并和第i个记录交换作为有序序列的第i个记录。


6.堆排序

function Sift(r,k,m){  var i=k;  var j=2*i;  while (j<=m) {    if (j<m && r[j]<r[j+1]) j++;    if (r[i]>r[j]) break;    else {      var temp = r[i];      r[i] = r[j];      r[j] = temp;      i = j;      j = 2*i;    }  }}function HeapSort(a){  var n = a.length;  var arr = new Array(n);  for (var i = 0,j=1; i < n; i++,j++) {    arr[j] = a[i];  }  for (var i = n/2; i >= 1; i--) {    Sift(arr,i,n);  }  for (var i = 1; i < n; i++) {    var temp = arr[1];    arr[1] = arr[n-i+1];    arr[n-i+1] = temp;    Sift(arr,1,n-i);  }  for (var i = 0; i < n; i++) {    a[i] = arr[i+1];  }  return a;}

堆排序
时间复杂度 平均情况:O(nlog2n) 最好情况:O(nlog2n) 最坏情况:O(nlog2n) —— 2为log的下标。
空间复杂度 O(1)
不稳定
基本思想:简单选择排序的改进法。首先将待排序的记录序列构造成一个堆,此时,选出来堆中所有的记录的最大者即堆顶记录。
然后再将堆顶记录移走,并将剩余的记录再调整成堆,这样又找出了次大的记录。以此类推,知道堆中只有一个记录为止。


7.归并排序的非递归实现

function Merge(r,r1,s,m,t){  var i=s,j=m+1,k=s;  while (i<=m && j<=t) {    if (r[i]<=r[j])r1[k++]=r[i++];    else r1[k++]=r[j++];  }  if (i<=m) {    while(i<=m)r1[k++]=r[i++];  }  else {    while (j<=t) r1[k++]=r[j++];  }}function MergePass(r,r1,n,h){  var i = 0;  while (i<=n-2*h+1) {    Merge(r,r1,i,i+h-1,i+2*h-1);    i+=2*h;  }  if (i<n-h+1) Merge(r,r1,i,i+h-1,n);  else {    for (var k = i; k <= n; k++){      r1[k] = r[k];    }  }}function MergeSort1(r){  var len = r.length;  var sr = new Array(len);  for(var i=0;i<len;i++)    {        sr[i]=r[i];    }    var h=1;    while(h<len)    {        MergePass(sr,r,len-1,h);        h=2 * h;        MergePass(r,sr,len-1,h);        h=2 * h;    }  return r;}

归并排序非递归算法
时间复杂度 平均情况:O(nlog2n) 最好情况:O(nlog2n) 最坏情况:O(nlog2n) —— 2为log的下标。
空间复杂度 O(n)
稳定
基本思想:将若干个有序序列进行两两归并,直至所有待排序记录都在一个有序序列为止。


8.归并排序的递归实现

function Merge(r,r1,s,m,t){  var i=s,j=m+1,k=s;  while (i<=m && j<=t) {    if (r[i]<=r[j])r1[k++]=r[i++];    else r1[k++]=r[j++];  }  if (i<=m) {    while(i<=m)r1[k++]=r[i++];  }  else {    while (j<=t) r1[k++]=r[j++];  }}function MergeSort(r,r1,s,t){    var m;    if(s==t) r1[s]=r[s];    else    {      m= parseInt((s+t)/2);        MergeSort(r,r1,s,m);        MergeSort(r,r1,m+1,t);        Merge(r1,r,s,m,t);    }}function MergeSort2(r){  var n = r.length;  var sr = new Array(n);    MergeSort(r,sr,0,n-1);  return r;}

归并排序的递归算法
时间复杂度 平均情况:O(nlog2n) 最好情况:O(nlog2n) 最坏情况:O(nlog2n) —— 2为log的下标。
空间复杂度 O(n)
稳定
基本思想:将若干个有序序列进行两两归并,直至所有待排序记录都在一个有序序列为止。


9.折半插入排序

function HalfSort(r){  for (var i = 1; i < r.length; i++){    var low = 0;    var high = i - 1;    var insertNote = r[i];    while (low <= high){      var mid = parseInt((low + high) / 2);      if (r[i] > r[mid]) low = mid+1;      else high = mid-1;    }    for ( var j=i; j > low; j--) {      r[j] = r[j - 1];    }    r[low] = insertNote;  }  return r;}

折半插入排序
时间复杂度 平均情况:O(n^2) 最好情况:O(n^2) 最坏情况:O(n^2)
空间复杂度 O(1)
稳定
基本思想:借助折半查找的思想进行折半排序

原创粉丝点击