十大排序算法——Typescript

188 阅读1分钟

时间复杂度O(n2)O(n^2)的排序算法

1. 冒泡排序

原理

冒泡排序.gif.gif

代码

function bubbleSort (nums: number[]): number[] {
  if (nums.length < 2) return nums
  for (let i = 0; i < nums.length - 1; i ++) {
    for (let j = 1; j < nums.length - i; j++) {
      if (nums[j - 1] > nums[j]) {
        [nums[j - 1], nums[j]] = [nums[j], nums[j - 1]]
      }
    }
  }
  return nums
}

2. 插入排序

原理

插入排序.gif

代码

function insertSort (nums: number[]): number[] {
  if (nums.length < 2) return nums
  // 默认第一个是排序好的
  for (let i = 1; i < nums.length; i++) {
    const ni: number = nums[i]
    let j: number = i - 1
    while(j >=0 && nums[j] > ni) {
      nums[j + 1] = nums[j]
      j--
    }
    nums[j + 1] = ni
  }
  return nums
}

3. 选择排序

原理

选择排序.gif

代码

function selectSort (nums: number[]): number[] {
  if (nums.length < 2) return nums
  for (let i = 0; i < nums.length - 1; i ++) {
    let maxIndex: number = i
    for (let j = i + 1; j < nums.length; j++) {
      if (nums[maxIndex] > nums[j]) {
        maxIndex = j
      }
    }
    [nums[i], nums[maxIndex]] = [nums[maxIndex], nums[i]]
  }
  return nums
}

时间复杂度O(nlogn)O(nlogn)的排序算法

4. 希尔排序

原理

shell.gif

代码

function shellSort (nums: number[]): number[] {
  if (nums.length < 2) return nums
  for (let step = nums.length >> 1; step > 0; step >>= 1) {
    for (let i = step; i < nums.length; i++) {
      const ni: number = nums[i]
      let j: number = i - step
      while( j >=0 && nums[j] > ni) {
        nums[j + step] = nums[j]
        j -= step
      }
      nums[j + step] = ni
    }
  }
  return nums
}

5. 快速排序

原理

快速排序.gif

代码

function quickSort(nums: number[]): number[] {
  if (nums.length < 2) return nums
  const current: number = nums[0]
  const leftArr: number[] = []
  const rightArr: number[] = []
  for (let i = 1; i < nums.length; i ++) {
    if (nums[i] <= current) {
      leftArr.push(nums[i])
    } else {
      rightArr.push(nums[i])
    }
  }
  return [...quickSort(leftArr), current, ...quickSort(rightArr)]
}

6. 归并排序

原理

归并排序.gif

代码

function merge (leftArr: number[], rightArr: number[]): number[] {
  const result: number[] = new Array(leftArr.length + rightArr.length)
  let index1: number = 0
  let index2: number = 0
  while (index1 < leftArr.length && index2 < rightArr.length) {
    if (leftArr[index1] < rightArr[index2]) {
      result[index1 + index2] = leftArr[index1]
      index1++
    } else {
      result[index1 + index2] = rightArr[index2]
      index2++
    }
  }
  while (index1 < leftArr.length) {
    result[index1 + index2] = leftArr[index1]
    index1++
  }
  while (index2 < rightArr.length) {
    result[index1 + index2] = rightArr[index2]
    index2++
  }
  return result
}
function _mergeSort (nums: number[], start: number, end: number): number[] {
  if (start === end) return [nums[start]]
  const middle: number = Math.floor((end + start) / 2)
  const leftArr: number[] = _mergeSort(nums, start, middle)
  const rightArr: number[] = _mergeSort(nums, middle + 1, end)
  return merge(leftArr, rightArr)
}
function mergeSort (nums: number[]): number[] {
  if (nums.length < 2) return nums
  const result: number[] = _mergeSort(nums, 0, nums.length - 1)
  return result
}

7. 堆排序

原理

堆排序.gif

代码


// 堆排序
function createHeap (nums: number[], i: number, heapsize: number) {
  let largest: number = i
  const leftNode: number = 2 * largest + 1
  const rightNode: number = leftNode + 1
  if (leftNode < heapsize && nums[leftNode] > nums[largest]) {
    largest = leftNode
  }
  if (rightNode < heapsize && nums[rightNode] > nums[largest]) {
    largest = rightNode
  }
  if (i !== largest) {
    [nums[i], nums[largest]] = [nums[largest], nums[i]]
    createHeap(nums, largest, heapsize)
  }
}
function createMaxHeap(nums: number[]){
  for (let i = nums.length >> 1 - 1; i >= 0; i --) {
    createHeap(nums, i, nums.length)
  }
}
function heapSort (nums: number[]) : number[] {
  if (nums.length < 2) return nums
  // 创建最大堆
  createMaxHeap(nums)
  for (let i = nums.length - 1; i >= 0; i--) {
    [nums[0], nums[i]] = [nums[i], nums[0]]
    createHeap(nums, 0, i)
  }
  return nums
}

时间复杂度(O(n))(O(n))的排序算法

8. 计数排序

原理

计数.gif

代码

// 计数排序
function countingSort(nums: number[]): number[] {
  if(nums.length < 2) return nums
  // 找出最大 和 最小值
  let min: number = nums[0]
  let max: number = nums[0]
  for (let i = 1; i < nums.length; i++) {
    if (min > nums[i]) {
      min = nums[i]
    }
    if (max < nums[i]) {
      max = nums[i]
    }
  }
  const range: number = max - min + 1
  const counting: number[] = new Array(range).fill(0) // -9 ~ 9
  for (let i = 0; i < nums.length; i++) {
    counting[nums[i] - min]++
  }
  counting[0]--
  for (let i = 1; i < range; i ++) {
    counting[i] += counting[i - 1]
  }
  const result: number[] = []
  for (let i = nums.length - 1; i >= 0 ; i --) {
    const index: number = nums[i] - min
    result[counting[index]--] = nums[i]
  }
  return result
}

9. 基数排序

原理

基数排序.gif

代码

// 基数排序
function radixSort(nums: number[]): number[] {
  if (nums.length < 2) return nums
  let max: number = nums[0]
  for (let i = 1; i < nums.length; i++) {
    if ( Math.abs(max) < Math.abs(nums[i])) {
      max = nums[i]
    }
  }
  let maxDigitLength: number = 0
  while( max !== 0) {
    maxDigitLength++
    max = parseInt('' + max / 10)
  }
  let dev: number = 1
  let counting: number[] = new Array(19).fill(0)
  for (let i = 0; i < maxDigitLength; i ++) {
    // 跟计数排序一样
    for (let j = 0; j < nums.length; j++) {
      const index: number = parseInt('' + (nums[j] / dev)) % 10 + 9
      counting[index]++
    }

    counting[0]--
    for (let j = 1; j < counting.length; j++) {
      counting[j] += counting[j - 1]
    }
    
    const result: number[] = new Array(nums.length)
    for (let j = nums.length - 1; j >= 0 ; j--) {
      const index: number = parseInt('' + nums[j] / dev) % 10 + 9
      console.log(index)
      result[counting[index]--] = nums[j]
    }
    nums = result.slice(0)
    counting = counting.fill(0)
    dev *= 10
  }
  return nums
}

10. 桶排序

原理

image.png

代码

function bucketSort(nums: number[]): number[] {
  if (nums.length < 2) return nums
  // 创建N个桶
  const bucketAmount: number = 10
  let min: number = nums[0]
  let max: number = nums[0]
  for (let i = 1; i < nums.length; i++) {
    if (min > nums[i]) {
      min = nums[i]
    }
    if (max < nums[i]) {
      max = nums[i]
    }
  }
  const range: number = max - min 
  const gap: number = Math.floor(range / (bucketAmount - 1))
  // 创建桶容器
  const buckets: Array<number[]> = new Array(bucketAmount).fill(0).map(() => {
    return new Array(nums.length).fill(0)
  })
  const bucketLength: number[] = new Array(bucketAmount).fill(0)
  for (let i = 0; i < nums.length; i++) {
    const index: number = Math.floor( ( nums[i] - min) / gap)
    buckets[index][bucketLength[index]++] = nums[i]
  }
  // 对每个桶进行排序
  let index: number = 0
  for (let i = 0; i < bucketAmount; i++) {
    const bucket: number[] = buckets[i].filter(v => v !== 0)
    // 我们随便选择一个排序 —— 插入排序
    buckets[i] = insertSort(bucket)
    index += bucketLength[i]
  }
  // 对数组进行合并
  let result: number[] = []
  for (let i = 0; i < bucketAmount; i++) {
    if (buckets[i].length === 0) continue
    result = [...result, ...buckets[i]]
  }
  return result
}