javascript 实现的常见几种排序方式

1 插入排序

//插入排序
/*用数组构造一个排序二叉树,再将排序二叉树中序遍历出来,是一个排序数组*/
 function ary2Bst(ary){
  return ary.reduce((root,it)=>{
    return insert2BEST(root,it)//it 数组各项
  },null)//一开始是没有根节点的,创建了一棵树
 }//把val 插入bst中并返回树根 遍历ary这个数组 创建一个树 把数组的各项放进去
   function insert2BEST(root,val/*数组项*/){//一个二叉树    
  if(!root){//没有根节点的时候创建一个节点,假设已经有一棵树了
    return {//如果这个节点没数
      val:val,
      left:null,
      right:null,
    }
  }   /*当这个节点有值得时候*/
    if(val <=  root.val){//判断是左侧树还是右侧
      root.left=insert2BEST(root.left,val)//有值就返回,没有就返回一个空节点,等于创建了一个左节点
    }
    if(val > root.val){
      root.right=insert2BEST(root.right,val)
    }
    return root
  }
res = []
midOrderTraverse(root,it=>{res.push(it)})
中序遍历
function midOrderTraverse(root,res=[]){
    if(root){
        midOrderTraverse(root.left,res)
        res.push(root.val)
        midOrderTraverse(root.right,res)
    }
    return res
}

2 冒泡排序

function buddleSort(ary){
  var l=ary.length
  var swaped // 判断这个调换位置的函数是否还在继续 不继续就跳出循环
  for(var i = 1;i<l;i++){//等于 i= 0 i<l-1 因为做对比只做l-1次 对比次数
    for(var j =0 ;j<l-i;j++){//每一次对比结束后,缩小一次循环次数
      if(ary[j]>ary[j+1]){//当前一位大于后一位 换位
        swaped=true       // 当前一项大于后一项,开始交换位置
        swap (ary,j,j+1)
      }
    }
    if(!swaped){
      break //跳出循环
    }
  }
  return ary
}
P

3 选则排序

/*选择排序,设一个最小的值,反复比较,最小的排在前,第二小在第二位....*/
function selectSort(ary){
  var l=ary.length;
  var minPos//设最小值的下标为i
  for(i=0;i<l-1;i++){
    minPos=i//第一个指针,到l-1项就够了
    for(j=i+1;j<l;j++){//下一项 对比 故=i+1
      if(ary[j]<ary[minPos]){//比最小的还小,设为最小
        minPos = j
      }
    }
    swap(ary,i,minPos)
  }
  return ary
}

4 块排

/*高级解法 快排*/
/*start,end是数组下标,先随机选取一个数字放在数组最后一位作为参考数字,拟定两个下标 i=start-1,j=start,j是用来相比的,i是用来替换的,当遇见比pivo小的数字,i+1,就用j去替换i+1后的位置,最后分成两个数组,递归这个函数*/
function quickSort(ary,comparator=(a,b)=>a-b){//避免内部参数修改
  return Partition(ary,comparator)
}

function Partition(ary,comparator,start=0,end=ary.length-1,){
  if(start>=end){//条件
    return 
  }
var pivotIndex=Math.floor(Math.random()*(end-start+1)+start)//随机得到一个数字下标
var pivo = ary[pivotIndex]//得到数组中的随机数字
swap(ary,pivotIndex,end)//把这个随机数字放在数组最后
for(i=start-1,j=start;j<end;j++){//两个下标,i,j 画图可知
  if(comparator(ary[j],pivo)<0){//当数组项小于随机数,放在左边
    i++//满足条件 i前进
    swap(ary,i,j)//换数字
  }                     
}  //i+1(最中间的值 左边<右边>) 全部比较结束后,换回去       
swap(ary,i+1/*最后的比较值下标*/,end)
  Partition(ary,comparator,start,i)//递归
  Partition(ary,comparator,i+2,end)//递归
  return ary
}

//快排暴力解法
function quickSort2(ary){
  if(ary.length<2){
    return ary.slice()
  }
 var post=ary[Math.floor(Math.random()*ary.length)]//找到一个随机数
  var left=[]
  var mid=[]
  var right=[]
  for(i=0;i<ary.length;i++){
    var val =ary[i]
    if(val<post){
      left.push(val)//比这个数小放左边
    }
    if(val==post){
      mid.push(val)
    }//相等放中间
    if(val>post){
      right.push(val)
    }//大的放右边
  }
  return quickSort2(left).concat(mid,quickSort2(right))
} //递归之后把相等小数组(相等数组 中间项)大数组 合并在一起

5 归并排序

/*归并排序*/
 function mergeSort(ary){
   if(ary.length<2){
     return ary.slice()
   }//结束条件
   var mid=Math.floor(ary.length/2)/*中心点*/
   var left=mergeSort(ary.slice(0,mid))//递归left 
   var right=mergeSort(ary.slice(mid))//递归right
   var res=[]//数组接纳
   while(left.length&&right.length){//
     if(left[0]<=right[0]){//数字小
       res.push(left.shift())//抛出这个数 新数组接纳
     }else{
       res.push(right.shift())
     }
   }
    res.push(...left,...right)//哪个数组还有数 就接哪个数组
   return res
  }
  ```
  ### 6 堆排序(最麻烦最日狗)
  ```js
// 堆排序
function heapSort(ary) {
  heapify(ary)//先把这个数组变成一个堆(仍然是一个数组)
  for(var i = ary.length - 1; i>=1; i--) {//只需遍历到第二项,第一项自然最小
    swap(ary, 0, i)//把堆的第一个位置和最后一项换位(因为堆的头结点是最大的数//即新数组的第一个元素)
    reheap(ary, 0, i - 1)/*交换后得到一个新数组*/
  }//新数组去掉最后的最大值,重新构成一个堆,继续操作
  return ary
}
//把一个数组调整成一个堆
function heapify(ary) {//是从后往前的 倒着调
  for(var i = ary.length - 1; i >= 0; i--) {
    reheap(ary, i)//每一个元素都是一个堆 
  } //逐个成堆
  return ary
}
//把堆顶在top位置的一个可能不是堆
//但左右子树都是堆的树调整成堆
//end指明了数组中end及之前的元素是属于堆的
//构造堆的过程
function reheap(ary, topIndex, endIndex = ary.length - 1) {
  if (topIndex > endIndex) {//将每一个元素构造成堆
    return //当根节点下标算出不在左右范围内,超出下标范围,就没有
  }//也就是说没有子节点了 

  var largestIndex = topIndex//设最大值的下标是根结点
  var leftIndex = topIndex * 2 + 1//左节点下标
  var rightIndex = topIndex * 2 + 2//右节点下标
    /*左指数在范围内*/
  if (leftIndex <= endIndex && ary[leftIndex] > ary[largestIndex]) {
    largestIndex = leftIndex//如果左边节点大于根节点,则交换下标
  }//此时的最大值的下标是头结点,以后会有不同的节点
    /*右指数在范围内*/ 
  if (rightIndex <= endIndex && ary[rightIndex] > ary[largestIndex]) {
    largestIndex = rightIndex
  }//同左//也有可能存在左节点大于根节点小于右节点,所以最后的最大值是右节点,之前的最大值是左节点
  //最大值的下标不等于头结点的下标时,说明头结点并不是最大值,换值
  if (largestIndex != topIndex) {
    swap(ary, largestIndex, topIndex)//把最大值放在根节点位置上
    reheap(ary, largestIndex, endIndex)
  }//将topindex下标上的元素换在了largestindex位置,不确定是否还是一个堆,继续构造堆
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值