es6实现冒泡排序,选择排序,插入排序,归并排序,快速排序,桶排序

class ArrayList {
  constructor() {
    this.array = []
  }
  insert (...item) {
    this.array.push(...item)
  }
  toString () {
    return this.array.join()
  }
  // 冒泡排序: 比较两个相邻的项,如果第一个大于第二个则交换他们的位置,元素项向上移动至正确的顺序,就好像气泡往上冒一样
  // 排序小型数组时,此算法比选择排序和冒泡排序性能要好 算法复杂度O(n^2)
  bubbleSort () {
    let i, j, len = this.array.length
    for (i = 0; i < len; i++) {
      for (j = i; j < len; j++) {
        if (this.array[i] > this.array[j]) {
          [this.array[i], this.array[j]] = [this.array[j], this.array[i]]
        }
      }
    }
  }
  // 选择排序:大概思路是找到最小的放在第一位,找到第二小的放在第二位,以此类推 算法复杂度O(n^2)
  selectionSort () {
    let i, j, minIndex, len = this.array.length
    for (i = 0; i < len; i++) {
      minIndex = i
      for (j = i; j < len; j++) {
        if (this.array[j] < this.array[minIndex]) {
          minIndex = j
        }
      }
      if (minIndex !== i) {
        [this.array[i], this.array[minIndex]] = [this.array[minIndex], this.array[i]]
      }
    }
  }
  // 插入排序:每次排一个数组项,假设数组的第一项已经排序,接着,把第二项与第一项进行对比,第二项是该插入到第一项之前还是之后,第三项是该插入到第一项之前还是第一项之后还是第三项
  insertionSort () {
    let i, j, temp, len = this.array.length
    for (i = 1; i < len; i++) {
      temp = this.array[i]
      j = i
      while (j > 0 && temp < this.array[j -1]) { // 判定一下temp如果小于前面的项
        this.array[j]  = this.array[j - 1] // 则把所有大于temp的项整体往后移动一位
        j--
      }
      this.array[j] = temp // 把temp放在往后移动0到多个项后的空缺位置
    }
  }
  // 归并排序:Mozilla Firefox 使用归并排序作为Array.prototype.sort的实现,而chrome使用快速排序的一个变体实现的,前面三种算法性能不好,但归并排序性能不错 算法复杂度O(nlog^n)
  // 归并排序是一种分治算法。本质上就是把一个原始数组切分成较小的数组,直到每个小数组只有一个位置,接着把小数组归并成较大的数组,在归并过程中也会完成排序,直到最后只有一个排序完毕的大数组
  mergeSort () {
    function mergeSortRec(array) {
      let len = array.length
      if (len === 1) {
        return array
      }
      let mid = len >> 1,
        left = array.slice(0, mid),
        right = array.slice(mid, len)
      return merge(mergeSortRec(left), mergeSortRec(right))
    }
    // 归并
    function merge(left, right) {
      let arr = [], il = 0, ir = 0
      while (left.length > il && right.length > ir) {
        if (left[il] < right[ir]) {
          arr.push(left[il])
          il++
        } else {
          arr.push(right[ir])
          ir++
        }
      }
      while (left.length > il) {
        arr.push(left[il])
        il++
      }
      while (right.length > ir) {
        arr.push(right[ir])
        ir++
      }
      return arr
    }
    this.array = mergeSortRec(this.array)
  }
  // 快速排序 算法复杂度O(nlog^n) 通常性能比其他的算法复杂度为O(nlog^n)的性能要好,快速排序也使用分治的方法,将原始数组分为较小的数组(但它并没有像归并一样把数组分割开)
  // 1) 首先,在数组中选择一个中间项作为主元
  // 2) 创建两个指针,左边的只想数组第一个项,右边的指向最后一个项,移动左指针,直到找到一个比主元大的项,接着,移动右边的指针,直到找到一个比主元小的项,然后交换它们。重复这个过程,直到
  // 左侧的指针超过了右侧的指针。这个使比主元小的都在左侧,比主元大的都在右侧。这一步叫划分操作
  // 3) 接着,算法对划分后的小数组(较主元小的值组成的的小数组, 以及较主元大的值组成的小数组)重复之前的两个步骤,直到排序完成
  quickSort () {
    function quick(array, left ,right) {
      if (array.length > 1) {
        let index = partition(array, left ,right)
        if (left < index -1) {
          quick(array, left, index -1)
        }
        if (index < right) {
          quick(array, index, right)
        }
      }
    }
    function partition(array, left, right) {
      let mid = array[left + right >> 1] // 注意主元的位置可能会变动,先记录主元的值
      while (left <= right) {
        while (array[left] < mid) {
          left++
        }
        while (array[right] > mid) {
          right--
        }
        if (left <= right) {
          [array[left], array[right]] = [array[right], array[left]]
          left++
          right--
        }
      }
      return left
    }
    quick(this.array, 0, this.array.length - 1)
  }
  //堆排序:堆排序把数组当中二叉树来排序而得名。
  // 1)索引0是树的根节点;2)除根节点为,任意节点N的父节点是N/2;3)节点L的左子节点是2*L;4)节点R的右子节点为2*R + 1
  // 本质上就是先构建二叉树,然后把跟节点与最后一个进行交换,然后对剩下对元素进行二叉树构建,进行交换,直到剩下最后一个
  heapSort () {
    function heapify(array, heapSize, i) {
      let left = i * 2,
        right = i * 2 + 1,
        largest = i
      if (left < heapSize && array[largest] < array[left]) {
        largest = left
      }
      if (right < heapSize && array[largest] < array[right]) {
        largest = right
      }
      if (i !== largest) {
        [array[i], array[largest]] = [array[largest], array[i]]
        heapify(array, heapSize, largest)
      }
    }
    function buildHeap(array) {
      let heapSize = array.length, i
      for (i = heapSize >> 1; i--;) {
        heapify(array, heapSize, i) //通过倒叙的方式把最大值放在第一位
        console.log(array)
      }
    }
    let heapSize = this.array.length
    buildHeap(this.array)
    while (heapSize > 1) {
      heapSize--
      [this.array[0], this.array[heapSize]] = [this.array[heapSize], this.array[0]]
      heapify(this.array, heapSize, 0) // 在上一次中,只交换来一个,所以只排一次就可以成为二叉树
    }
  }
  // 分布式排序:原始数据会分发到多个中间结构(桶),再合起来放回原始数组,最著名的分布式排序算法有计数排序,桶排序,基数排序,三种算法非常类似.
}
let arrayList = new ArrayList
arrayList.insert(3, 5, 1, 6, 4, 7, 2)
arrayList.heapSort()
console.log(arrayList.toString())
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值