全网精简版js数据结构——排序

冒泡排序

    function  BubbleSort(){
    const{length}=array
       for(let i=0;iarr[j+1]){
          swap(arr,j,j+1)
          }
        }
       }
       console.log(arry);
    }
    function swap(arry, a, b) {
        const temp = arry[a]
        arry[a] = arry[b]
        arry[b] = temp
//或者用 [arry[b],arry[a]]=[arry[a],arry[b]]//es6中数组解构

      }

    var arr= [1,2,3,4,5]

选择排序

记录并不断更改索引值,找到最小的数后替换

假设数组为 [5, 3, 8, 4, 2]

  • 第一轮外部循环(i = 0):
    • 内部循环找到最小元素 2 在索引 4,交换后数组变为 [2, 3, 8, 4, 5]
  • 第二轮外部循环(i = 1):
    • 内部循环找到最小元素 3 在索引 1(未移动),数组保持不变。
  • 第三轮外部循环(i = 2):
    • 内部循环找到最小元素 4 在索引 3,交换后数组变为 [2, 3, 4, 8, 5]
  • 第四轮外部循环(i = 3):
    • 内部循环找到最小元素 5 在索引 4,交换后数组变为 [2, 3, 4, 5, 8]

排序完成,最终数组为 [2, 3, 4, 5, 8]

插入排序

记录索引对于元素的值,就是把大的数往后面覆盖,最后肯定右两个重复的大数,直接把当前的temp覆盖到排在前面的大数就行

function insertSort(){
  const {length}=arr
  let temp
  for(let i=1;i0&&arr[j-1]>temp){
        arr[j]=arr[j-1]
        j--
    }
    arr[j]=temp
  }
  console.log(arr);
} 
insertSort=[5, 4, 3, 3, 1]

具体用实例说明

  1. 第一轮循环(i = 1)

    • temp = arr[1] = 4
    • j = 1
    • 比较 arr[j-1] (5) 和 temp (4),因为 5 > 4,所以进入 while 循环。
    • 将 arr[j-1] (5) 后移一位,数组变为 [5, 5, 3, 3, 1]
    • j--,现在 j = 0
    • while 循环结束,因为 j = 0
    • 将 temp (4) 插入到 arr[j],数组变为 [4, 5, 3, 3, 1]
  2. 第二轮循环(i = 2)

    • temp = arr[2] = 3
    • j = 2
    • 比较 arr[j-1] (5) 和 temp (3),因为 5 > 3,所以进入 while 循环。
    • 将 arr[j-1] (5) 后移一位,数组变为 [4, 5, 5, 3, 1]
    • j--,现在 j = 1
    • 比较 arr[j-1] (4) 和 temp (3),因为 4 > 3,所以继续 while 循环。
    • 将 arr[j-1] (4) 后移一位,数组变为 [4, 4, 5, 3, 1]
    • j--,现在 j = 0
    • while 循环结束,因为 j = 0
    • 将 temp (3) 插入到 arr[j],数组变为 [3, 4, 5, 3, 1]
  3. 第三轮循环(i = 3)

    • temp = arr[3] = 3
    • j = 3
    • 比较 arr[j-1] (5) 和 temp (3),因为 5 > 3,所以进入 while 循环。
    • 将 arr[j-1] (5) 后移一位,数组变为 [3, 4, 5, 5, 1]
    • j--,现在 j = 2
    • 比较 arr[j-1] (4) 和 temp (3),因为 4 > 3,所以继续 while 循环。
    • 将 arr[j-1] (4) 后移一位,数组变为 [3, 4, 4, 5, 1]
    • j--,现在 j = 1
    • 比较 arr[j-1] (3) 和 temp (3),因为 3 == 3,所以 while 循环结束。
    • 将 temp (3) 插入到 arr[j],数组变为 [3, 3, 4, 5, 1]
  4. 第四轮循环(i = 4)

    • temp = arr[4] = 1
    • j = 4
    • 比较 arr[j-1] (5) 和 temp (1),因为 5 > 1,所以进入 while 循环。
    • 将 arr[j-1] (5) 后移一位,数组变为 [3, 3, 4, 5, 5]
    • j--,现在 j = 3
    • 比较 arr[j-1] (4) 和 temp (1),因为 4 > 1,所以继续 while 循环。
    • 将 arr[j-1] (4) 后移一位,数组变为 [3, 3, 4, 4, 5]
    • j--,现在 j = 2
    • 比较 arr[j-1] (3) 和 temp (1),因为 3 > 1,所以继续 while 循环。
    • 将 arr[j-1] (3) 后移一位,数组变为 [3, 3, 3, 4, 5]
    • j--,现在 j = 1
    • 比较 arr[j-1] (3) 和 temp (1),因为 3 > 1,所以继续 while 循环。
    • 将 arr[j-1] (3) 后移一位,数组变为 [3, 3, 3, 4, 5]
    • j--,现在 j = 0
    • while 循环结束,因为 j = 0
    • 将 temp (1) 插入到 arr[j],数组变为 [1, 3, 3, 4, 5]

归并排序

火狐浏览器的sort就是基于这种排序,chrome用到快速排序

    function mergeSort(array){
    if(array.length>1){
   const {length}=array 
    const middle=Math.floor(length/2)
    const left=mergeSort(array.slice(0,middle))
    const right=mergeSort(array.slice(middle,length))
    array=merge(left,right)
    }
        }
        function merge(left,right){
          let i=0;
          let j=0;
    const result=[]
    while(i

用具体例子解释一下执行过程

  1. 第一次调用 mergeSort

    • 数组长度大于 1,继续执行。
    • middle 是 2。
    • left 是 [5, 4]right 是 [3, 2, 1]
    • 递归调用 mergeSort 对 left 和 right 进行排序。
    1. merge中执行过程
    2. 第一轮比较
      1. left[i] (4) 与 right[j] (1) 比较,因为 1 < 4,所以将 1 添加到 result 中。
      2. j 增加 1,现在 j = 1
    3. 第二轮比较
      1. left[i] (4) 与 right[j] (2) 比较,因为 2 < 4,所以将 2 添加到 result 中。
      2. j 增加 1,现在 j = 2
    4. 第三轮比较
      1. left[i] (4) 与 right[j] (3) 比较,因为 3 < 4,所以将 3 添加到 result 中。
      2. j 增加 1,现在 j = 3
    5. 第四轮比较
      1. left[i] (4) 与 right[j] (不存在) 比较,因为 right 数组已经没有更多元素,所以将 left 数组剩余的元素 [4, 5] 添加到 result 中。

快速排序

以一个元素为基准(可以是middle,0,length-1)把比它小的放一堆,比它大的放一堆,在以第一堆的元素中挑一个基准,比它大的挑一堆,比它小的调一堆,分到最后把这几堆和一起。

    function quickStore(){
      const {length}=arr
      if(length<2){
        return arr
      }
      let base=arr[0]
      let minArr=arr.slice(1).filter(item=>item>=base)
      let maxArr=arr.slick(1).filter(item=>item

计数排序

但是会占据空间

找到最大值

const maxValue = findMax(arr)
// const maxValue = Math.max(...arr)
  • 调用 findMax 函数来找到数组中的最大值。
  • findMax 函数遍历数组,比较每个元素,找到最大值。

:初始化计数数组

const counts = new Array(maxValue + 1)
  • 创建一个长度为 maxValue + 1 的数组 counts,用于存储每个元素的出现次数。
  • 由于最大值是 9,所以 counts 的长度为 10。

    : 计数每个元素的出现次数

  • 例如遍历到数组中数字5出现2次,就把counts计数数组的下标为5的位置计为1,再白能力一遍还有就++计为2。所以count数组中索引值为5的地方数值为2,意思是5出现了两次。

  • arr.forEach(item => {
      if(!counts[item]){
        counts[item] = 0
      }
      counts[item]++
    })

    构建新的排序数组

    let newarr = []
    let sortIndex = 0
    counts.forEach((item, index) => {
      while(item > 0){
        newarr[sortIndex++] = index
        item--
      }
    })
    
  • 初始化一个新的空数组 newarr
  • 遍历 counts 数组,根据计数构建新的排序数组。
  • 对于 counts 中的每个非零元素,将其索引(即原数组中的元素值)添加到 newarr 中相应次数。例如:遍历到5前面数字都没有出现就不会进入while循环,知道索引值index为5时,就将newarr 中sortIndex=0索引值为0的位置计为index5,sortIndex++变为1,迎接下一个元素,counts 数组中索引值5的item减一也就是减少出现次数后再遍历是否还出现,如果还有就把count下标1的位置再计为5.出现次数减一。
  • 完整代码
  •     var arr=[5,7,5,4,9,1]
        function countSort(arr){
          if(arr.length<2){
            return arr
          }
          const maxValue=findMax(arr)
          // const maxValue=Math.max(...arr)也可以用js内置方法
          const counts=new Array(maxValue+1)
          arr.forEach(item => {
            if(!counts[item]){
              counts[item]=0
            }
            counts[item]++
          })
          let newarr=[]
          let sortIndex=0
          counts.forEach((item,index)=>{
            while(item>0){
              newarr[sortIndex++]=index
              item--
            }
          })
    
        }
        countSort(arr)
        function findMax(arr){
          let max=arr[0]
          for(let i=0;imax){
              maax=arr[i]
            }
          }
          return newarr
        }
    

    桶排序

  • 数据稀疏桶会少,数据庞大桶多
        function bucketSort(arr, bucketSize=3){
          if(arr.length<2){
            return arr
          }
          //创建几个小桶
          const buckets=createBucket(arr,buckdetSize)
    //小桶排序(插入算法)合并concat
    return sortBucket(buckets)
        }
        function createBucket(arr,buckdetSize){
    //找最大值和最小值
    let minValue=Math.min(...arr)
    let maxValue=Math.max(...arr)
    //桶数量
    const bucetCount=Math.floor((maxValue-minValue)/ buckdetSize)+1//+1是为了如果最大值正好等于某个桶的边界值,
    // 那么按照简单的除法计算,最大值可能会被分配到超出桶的范围之外。
          // //创建桶子
          // const buckets = []
          // for (let i = 0; i < bucketCount; i++) {
          //   buckets[i] = []
          // }
          // ES6
          const buckets=[...Array(bucetCount)].map(()=>[])
          //判断每个元素应该进哪个桶子
          for (let i = 0; i < arr.length; i++) {
            const index = Marh.floor((arr[i] - minValue) / bucketSize)
            buckets[index].push(arr[i])
          }
     return  buckets
        }
        function sortBucket(){
          const sortArr=[]
          for(let i=0;i 0 && arr[j - 1] > temp) {
                arr[j] = arr[j - 1]
                j--
              }
              arr[j] = temp
            }
            console.log(arr);
          } 
    
        bucketSort([5,4,3,2,6,1,7,10,9,8])
    

    缺点是如果最大数为100,中间会创造很多无效桶

  • 基数排序

  • 填补了计数排序和桶排序的缺点

  • 给定桶子的数量。一般是10,将数组里的数字先按照个位排序,再按十位,再百位~

  • 再掌握这个思想

  •     //Math.floor(x/diveder)%base
        //divider*=base
    

    以35举例:x是35,diveder事先定义为1,base为10

  • 得到十位35/1=35%10=5,得到个位35/10=3%10=3

  •     let maxVal=Math.max(...arr)
        while(divider<=maxVal){
          //构建二维数组
          const buckets = [...Array(10)].map(() => [])
          for (let val of arr) {
            buckets[Math.floor(val / divider) % base].push(val)
    //把取得个位数,十位数百位数推到bukets中
          }
          arr = [].concat(...buckets)
          divider *= base
        }
    

    去最大值作为循环结束的条件

  • 用array和map的方法创建10个空数组。遍历arr中元素,用Math方法取出个十百位数,推到buckets中,如:bucket[3]=3

          arr = [].concat(...buckets)
          divider *= base
    

    表示将arr数组中所有个位数取出来排好后,用concat连成数组,再排新数组中每个元素的十位数,divider*10后变成10.....

  • 完整代码

  •     const arr=[35,2,26,2,5,8,34,1,56,99,33]
        function radixSort(arr){
        const  base=10
        let divider=1
        //Math.floor(x/diveder)%base//得到十位35/1=35%10=5,得到个位35/10=3%10=3
        //divider*=base
        let maxVal=Math.max(...arr)
        while(divider<=maxVal){
          //构建二维数组
          const buckets = [...Array(10)].map(() => [])
          for (let val of arr) {
            buckets[Math.floor(val / divider) % base].push(val)//把取得个位数,十位数百位数推到bukets中
          }
          arr = [].concat(...buckets)
          divider *= base
        }
        return arr
      }
    

你可能感兴趣的:(数据结构js,javascript,数据结构,前端)