Js实现排序算法

1.排序算法都有哪些?

排序算法包括:

  • 冒泡排序 选择排序 插入排序 归并排序 计数排序 基数排序 希尔排序 堆排序 桶排序 快速排序

2.冒泡排序

  • 思路:假设有n个数据要进行比较,采用冒泡排序,每一个大循环比较交换得到最大的一个数(位于倒数,可以说这个最大的数不用在下一个大循环中再参与比较了),要进行大循环的次数是n次,而一个大循环中,需要比较交换的次数是n-进行大循环的次数,但是考虑到数组中是从下标0开始存数的,可以将内循环的次数改成从0到n-进行大循环的次数-1。
  • 冒泡排序时间复杂度O(N^2)。
  • 代码:
//交换两数
     ArrayList.prototype.swap=function(m,n){
         var temp=this.array[m];
          this.array[m]=this.array[n];
          this.array[n]=temp;
     }

     //冒泡排序,外层循环是大交换的轮次(有几个数据,就做几轮大循环),内循环是在一个大循环中交换的次数
     ArrayList.prototype.bubble=function(){
         var length=this.array.length;
         for(var i=1;i<=length;i++){
            for(var j=0;j<=length-1-i;j++){
                 if(this.array[j]>this.array[j+1]){
                     this.swap(j,j+1);
                 }
            }
         }
     }

3.选择排序

  • 思路:选定第一个索引位置,然后和后面的元素依次作比较,如果后面的更小,则交换,经过一轮之后,第一个位置的元素就是最小的,然后选择第二个索引位置,和后面的元素作比较,一轮之后,就确定第二小了…经过n轮后,排序完成。外层循环做的事是确定索引位置,索引的位置可以取[0,n-,2],内层循环做的事是取索引之后的元素与索引位置的元素作比较,所以可以取得范围是[索引值+1,n-1],因为是存于数组当中的,所以第一个元素的索引值为0,最后一个元素的索引值为n-1,倒数第二的元素的索引值为n-2.
  • 选择排序时间复杂度O(N^2)。 通常情况下,选择排序在执行效率上比冒泡高,因为两者的比较次数差不多,但是交换次数,选择排序更少(n-1次)。
  • 代码:
//选择排序
     ArrayList.prototype.select=function(){
         var length=this.array.length;
         for(var i=0;i<=length-2;i++){
             for(var j=i+1;j<=length-1;j++){
                 if(this.array[i]>this.array[j]){
                     this.swap(i,j);
                 }
             }
         }
     }

4.插入排序

  • 思路:插入排序的核心是局部有序。它的基本思想是将一个记录插入到已经排好序的有序表中,从而形成一个新的记录数增 1 的有序表。在其实现过程使用双层循环,外层循环是除了第一个元素之外的所有元素(我们把外层循环叫做记号表,范围是[1,n-1]),内层循环(是一个有序表,范围是[0,当前记号的索引-1]),我们从记号表中取一个记号和有序表中的元素比较,如果当前记号更小,则把记号插入到有序表中比记号稍微大的元素的位置上,然后删除记号表中的这个记号;如果记号比有序表中任意元素都大,则不插入。
  • 插入排序的平均时间复杂度也是 O(n^2), 空间复杂度为常数阶O(1),插入排序中,当待排序数组是有序时,是最优的情况,只需当前数跟前一个数比较一下就可以了,这时一共需要比较 N-1 次,时间复杂度为O(N)。最坏的情况是待排序数组是逆序的,此时需要比较次数最多,最坏的情况是 O(n^2)。
  • 代码:
  //插入排序
     ArrayList.prototype.insertSort=function(){
         var length=this.array.length;
         for(var i=1;i<=length-1;i++){
             for(var j=0;j<=i-1;j++){
                 if(this.array[i]<this.array[j]){`在这里插入代码片`
                    this.array.splice(j,0,this.array[i]);
                    this.array.splice(i+1,1);
                    break;
                 }
                 else{
                     continue;
                 }
                 
             }
         }
     }

5.希尔排序

  • 思路:它通过比较相距一定间隔的元素来进行,各趟比较所用的距离随着算法的进行而减小,直到只比较相邻元素的最后一趟排序为止。
  • 希尔排序时间复杂度是 O(n^(1.3-2)),空间复杂度为常数阶 O(1)。 希尔排序没有时间复杂度为 O(n(logn))的快速排序算法快 ,因此对中等大小规模表现良好,但对规模非常大的数据排序不是最优选择,总之比一般 O(n^2 ) 复杂度的算法快得多。
  • 代码:
//希尔排序
     ArrayList.prototype.shell=function(){
         var length=this.array.length;
         var gap=Math.floor(length/2);
         while(gap>=1){
             for(var i=gap;i<=length-1;i++){
                 var temp=this.array[i];
                 var j=i;
                 while(this.array[j-gap]>temp&&j>gap-1){
                        this.array[j]=this.array[j-gap];
                        j-=gap;
                     }
                     this.array[j]=temp;
                 }
                 gap=Math.floor(gap/2);
             }
         } 

6.双路快速排序

  • 思路:快速排序就是给基准数据找到正确位置。首先,我们把数组第一个数当做基准数据用temp存起来,让left在索引为0的地方,让right在索引为n-1的地方,从后面开始,如果array[right]>temp,right就减减,否则就让array[left]=array[right],接着轮到前面了,如果array[left]<temp,left++,否则,array[right]=array[left],这里一直做循环(循环条件是left<right),之后等到循环结束left=right时,让array[left]=temp,说明找到了放基准数据的正确位置,然后返回这个位置,让[left,返回位置-1]再找基准数据,放基准数据;让[返回位置+1,right]再找基准数据,放基准数据.
  • 快速排序是一种比较快速的排序算法,它的平均运行时间是 O(nlogn),之所以特别快是由于非常精练和高度优化的内部循环,最坏的情形性能为O(n^2)。像归并一样,快速排序也是一种分治的递归算法。从空间性能上看,快速排序只需要一个元素的辅助空间,但快速排序需要一个栈空间来实现递归,空间复杂度也为O(logn)。
  • 代码:
//双路快速排序
     ArrayList.prototype.quick=function(left,right){
         if(left<right){
            var p=this.position(left,right);
            this.quick(left,p-1);
            this.quick(p+1,right);
         }
     }

     ArrayList.prototype.position=function(left,right){
        var temp=this.array[left];
         while(left<right){
             while(this.array[right]>temp&&left<right){
                 right--;
             }
             this.array[left]=this.array[right];
             while(this.array[left]<=temp&&left<right){
                 left++;
             }
            this.array[right]=this.array[left];
         }
          this.array[left]=temp;
         return left;
     }

7.归并排序

  • 思路:该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
  • 归并排序的时间复杂度为 O(nlogn)。归并排序时需要和待排序记录个数相等的存储空间,所以空间复杂度为 O(n)。
  • 代码:
function merge(left, right) {
  let result = new Array();
  let i = 0, j = 0
  while(i < left.length && j < right.length) {
    if (left[i] <= right[j]) {
      result.push(left[i++])
    } else {
      result.push(right[j++])
    }
  }
  if (i < left.length) {
    result.push(...left.slice(i))
  } else {
    result.push(...right.slice(j))
  }
  return result
}

function mergeSort(array) {
  if (array.length < 2) {
    return array
  }
  let m = Math.floor(array.length / 2)
  var left = mergeSort(array.slice(0, m))
  var right = mergeSort(array.slice(m))
  return merge(left, right)
} 

var array=[66,68,12,87,100,5,566,23];
console.log(mergeSort(array))

最后,附上这些排序的完整代码

//创建封装类
 function ArrayList(){
     //属性
     this.array=[];

     //方法

     //将数据插入到数组中
     ArrayList.prototype.insert=function(data){
         this.array.push(data);
     }
     //toString方法
     ArrayList.prototype.toString=function(){
         return this.array.join(' ');
     }

     //交换两数
     ArrayList.prototype.swap=function(m,n){
         var temp=this.array[m];
          this.array[m]=this.array[n];
          this.array[n]=temp;
     }

     //冒泡排序,外层循环是大交换的轮次(有几个数据,就做几轮大循环),内循环是在一个大循环中交换的次数
     ArrayList.prototype.bubble=function(){
         var length=this.array.length;
         for(var i=1;i<=length;i++){
            for(var j=0;j<=length-1-i;j++){
                 if(this.array[j]>this.array[j+1]){
                     this.swap(j,j+1);
                 }
            }
         }
     }

     //选择排序
     ArrayList.prototype.select=function(){
         var length=this.array.length;
         for(var i=0;i<=length-2;i++){
             for(var j=i+1;j<=length-1;j++){
                 if(this.array[i]>this.array[j]){
                     this.swap(i,j);
                 }
             }
         }
     }


     //插入排序
     ArrayList.prototype.insertSort=function(){
         var length=this.array.length;
         for(var i=1;i<=length-1;i++){
             for(var j=0;j<=i-1;j++){
                 if(this.array[i]<this.array[j]){
                    this.array.splice(j,0,this.array[i]);
                    this.array.splice(i+1,1);
                    break;
                 }
                 else{
                     continue;
                 }
                 
             }
         }
     }

     //希尔排序
     ArrayList.prototype.shell=function(){
         var length=this.array.length;
         var gap=Math.floor(length/2);
         while(gap>=1){
             for(var i=gap;i<=length-1;i++){
                 var temp=this.array[i];
                 var j=i;
                 while(this.array[j-gap]>temp&&j>gap-1){
                        this.array[j]=this.array[j-gap];
                        j-=gap;
                     }
                     this.array[j]=temp;
                 }
                 gap=Math.floor(gap/2);
             }
         } 
     //双路快速排序
     ArrayList.prototype.quick=function(left,right){
         if(left<right){
            var p=this.position(left,right);
            this.quick(left,p-1);
            this.quick(p+1,right);
         }
     }

     ArrayList.prototype.position=function(left,right){
        var temp=this.array[left];
         while(left<right){
             while(this.array[right]>temp&&left<right){
                 right--;
             }
             this.array[left]=this.array[right];
             while(this.array[left]<=temp&&left<right){
                 left++;
             }
            this.array[right]=this.array[left];
         }
          this.array[left]=temp;
         return left;
     }

    
 }

 //测试
 var array=new ArrayList();
 array.insert(66);
 array.insert(88);
 array.insert(12);
 array.insert(87);
 array.insert(100);
 array.insert(5);
 array.insert(566);
 array.insert(23);
 console.log(array.toString());//66 88 12 87 100 5 566 23
 array.bubble();
 console.log("冒泡排序后:"+array.toString());//冒泡排序后:5 12 23 66 87 88 100 566
array.select();
console.log("选择排序:"+array.toString());//选择排序:5 12 23 66 87 88 100 566
 array.insertSort();
 console.log('插入排序:'+array.toString());//插入排序:5 12 23 66 87 88 100 566
array.shell();
console.log('希尔排序'+array.toString());//希尔排序5 12 23 66 87 88 100 566
array.quick(0,7);
console.log("快速排序:"+array.toString());//快速排序:5 12 23 66 87 88 100 566
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值