快速排序——每次选取一个基准值,将数组分为小于基准值和大于基准值的两部分,再重复之前的递归操作
对于含有大量重复元素的情况,性能会显著降低,甚至退化成O(n²)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 function  quickSort  (arr )   _quickSort(arr, 0 , arr.length - 1 )      function  _quickSort  (arr, l, r )      if  (l >= r) {       return      }     const  p = _partition(arr, l, r)     _quickSort(arr, l, p - 1 )     _quickSort(arr, p + 1 , r)   }   function  _partition  (arr, l, r )                     const  randomIndex = ~~(Math .random() * (r - l + 1 ) + l)     swap(arr, l, randomIndex)     let  p = arr[l]     let  j = l     for  (let  i = l + 1 ; i <= r; i++) {       if  (arr[i] < p) {         j++         swap(arr, i, j)       }     }     swap(arr, l, j)     return  j   } } 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 function  quickSort2  (arr )   _quickSort(arr, 0 , arr.length - 1 )      function  _quickSort  (arr, l, r )      if  (l >= r) {       return      }     const  p = _partition(arr, l, r)     _quickSort(arr, l, p - 1 )     _quickSort(arr, p + 1 , r)   }   function  _partition  (arr, l, r )                const  randomIndex = ~~(Math .random() * (r - l + 1 ) + l)     swap(arr, l, randomIndex)     let  p = arr[l]     let  i = l + 1 , j = r     while  (true ) {       while  (i <= j && arr[i] < p) i++       while  (i <= j && arr[j] > p) j--       if  (i >= j) break        swap(arr, i, j)       i++       j--     }     swap(arr, l, j)     return  j   } } 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 function  quickSort3  (arr )   _quickSort(arr, 0 , arr.length - 1 )      function  _quickSort  (arr, l, r )      if  (l >= r) {       return      }     const  [lt, gt] = _partition(arr, l, r)     _quickSort(arr, l, lt - 1 )     _quickSort(arr, gt, r)   }   function  _partition  (arr, l, r )                     const  randomIndex = ~~(Math .random() * (r - l + 1 ) + l)     swap(arr, l, randomIndex)     const  p = arr[l]     let  lt = l, i = l + 1 , gt = r + 1      while  (i < gt) {       if  (arr[i] < p) {         lt++         swap(arr, i, lt)         i++       } else  if  (arr[i] > p) {         gt--         swap(arr, i, gt)       } else  {          i++       }     }     swap(arr, lt, l)                    return  [lt, gt]   } } 
归并排序:将原数组对半分割成子数组,然后递归分割子数组,直至不能分割,然后分别排序子数组,再依次合并
稳定 
O(nlogn) 
无法原地排序,需要额外的O(n)空间 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 function  mergeSort  (arr )   _mergeSort(arr, 0 , arr.length - 1 )      function  _mergeSort  (arr, l, r )      if  (l >= r) {       return      }     const  mid = l + ((r - l) >> 1 )     _mergeSort(arr, l, mid)     _mergeSort(arr, mid + 1 , r)     _merge(arr, l, mid, r)   }      function  _merge  (arr, l, mid, r )      const  temp = []     for  (let  i = l; i <= r; i++) {       temp[i] = arr[i]     }     let  i = l, j = mid + 1      for  (let  k = l; k <= r; k++) {       if  (i > mid) {          arr[k] = temp[j]         j++       } else  if  (j > r) {          arr[k] = temp[i]         i++       } else  if  (temp[i] <= temp[j]) {          arr[k] = temp[i]         i++       } else  {          arr[k] = temp[j]         j++       }     }   } } 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 function  mergeSort  (arr )      const  tempArr = new  Array (arr.length)   _mergeSort(arr, 0 , arr.length - 1 )      function  _mergeSort  (arr, l, r )           if  (r - l <= 15 ) {       insertSort(arr, l, r)       return      }     const  mid = l + ((r - l) >> 1 )     _mergeSort(arr, l, mid)     _mergeSort(arr, mid + 1 , r)          if  (arr[mid] > arr[mid + 1 ])       _merge(arr, l, mid, r)   }      function  _merge  (arr, l, mid, r )           for  (let  i = l; i <= r; i++) {       tempArr[i] = arr[i]     }     let  i = l, j = mid + 1      for  (let  k = l; k <= r; k++) {       if  (i > mid) {          arr[k] = tempArr[j]         j++       } else  if  (j > r) {          arr[k] = tempArr[i]         i++       } else  if  (tempArr[i] <= tempArr[j]) {          arr[k] = tempArr[i]         i++       } else  {          arr[k] = tempArr[j]         j++       }     }   }   function  insertSort  (arr, l, r )      for  (let  i = l + 1 ; i <= r; i++) {       const  temp = arr[i]       let  j       for  (j = i; j - 1  >= l && temp < arr[j - 1 ]; j--) {         arr[j] = arr[j - 1 ]       }       arr[j] = temp     }   } } 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 function  mergeSortNR  (arr )   const  tempArr = new  Array (arr.length)      for  (let  size = 1 ; size < arr.length; size = size * 2 ) {          for  (let  i = 0 ; i + size < arr.length; i = i + 2  * size) {        const  l = i,         mid = i + size - 1 ,         r = Math .min(i + 2  * size - 1 , arr.length - 1 )       if  (arr[mid] > arr[mid + 1 ]) {         _merge(arr, l, mid, r)       }     }   }   function  _merge  (arr, l, mid, r )      for  (let  i = l; i <= r; i++) {       tempArr[i] = arr[i]     }     let  i = l, j = mid + 1      for  (let  k = l; k <= r; k++) {       if  (i > mid) {          arr[k] = tempArr[j]         j++       } else  if  (j > r) {          arr[k] = tempArr[i]         i++       } else  if  (tempArr[i] <= tempArr[j]) {          arr[k] = tempArr[i]         i++       } else  {          arr[k] = tempArr[j]         j++       }     }   } } 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 function  mergeSortNR  (arr )   const  tempArr = new  Array (arr.length)      for  (let  i = 0 ; i < arr.length; i = i + 16 ) {     const  l = i,       r = Math .min(i + 15 , arr.length - 1 )     insertSort(arr, l, r)   }      for  (let  size = 16 ; size < arr.length; size = size * 2 ) {          for  (let  i = 0 ; i + size < arr.length; i = i + 2  * size) {        const  l = i,         mid = i + size - 1 ,         r = Math .min(i + 2  * size - 1 , arr.length - 1 )              if  (arr[mid] > arr[mid + 1 ]) {         _merge(arr, l, mid, r)       }     }   }   function  _merge  (arr, l, mid, r )      for  (let  i = l; i <= r; i++) {       tempArr[i] = arr[i]     }     let  i = l, j = mid + 1      for  (let  k = l; k <= r; k++) {       if  (i > mid) {          arr[k] = tempArr[j]         j++       } else  if  (j > r) {          arr[k] = tempArr[i]         i++       } else  if  (tempArr[i] <= tempArr[j]) {          arr[k] = tempArr[i]         i++       } else  {          arr[k] = tempArr[j]         j++       }     }   }   function  insertSort  (arr, l, r )      for  (let  i = l + 1 ; i <= r; i++) {       const  temp = arr[i]       let  j       for  (j = i; j - 1  >= l && temp < arr[j - 1 ]; j--) {         arr[j] = arr[j - 1 ]       }       arr[j] = temp     }   } } 
堆排序:将数组调整成大根堆/小根堆,每次将第一个元素与最后一个未排好序的元素交换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 function  heapSort  (arr )   const  lastParentIndex = ~~((arr.length - 1 ) / 2 )   for  (let  i = lastParentIndex; i >= 0 ; i--) {     _siftDown(arr, i, arr.length)   }   for  (let  i = arr.length - 1 ; i > 0 ; i--) {     swap(arr, 0 , i)     _siftDown(arr, 0 , i)   }   return  arr   function  _siftDown (arr, i, n )      while  (2  * i + 1  < n) {       let  j = 2  * i + 1        if  (j + 1  < n && arr[j + 1 ] > arr[j]) {         j = j + 1        }       if  (arr[i] > arr[j]) {         break        }       swap(arr, i, j)       i = j     }   } } 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 function  swap  (arr, i, j )   const  temp = arr[i]   arr[i] = arr[j]   arr[j] = temp             } function  generateOrderedArray  (n )   const  arr = new  Array (n)   for  (let  i = 0 ; i < n; i++)     arr[i] = i   return  arr } function  generateRandomArray  (n, bound )   const  arr = new  Array (n)   for  (let  i = 0 ; i < n; i++)     arr[i] = ~~(Math .random() * bound)   return  arr } function  generateRandomArrayByStartAndEnd  (n, start, end )   const  arr = new  Array (n)   for  (let  i = 0 ; i < n; i++)     arr[i] = ~~(Math .random() * (end - start + 1 ) + start)   return  arr } function  isSorted  (arr )   for  (let  i = 1 ; i < arr.length; i++)     if  (arr[i - 1 ] > arr[i])       return  false    return  true  } function  testSort  (fn, arr )   const  startTime = Date .now()   fn(arr)   const  endTime = Date .now()   const  spendTime = endTime - startTime   if  (!isSorted(arr)) {     console .log(`${fn.name}  failed!` )     const  debugArr = generateRandomArray(5 , 10 )     console .log(`Before sort: [${debugArr.join(', ' )} ]` )     fn(debugArr)     console .log(`After sort: [${debugArr.join(', ' )} ]` )     return    }   console .log(`${fn.name} : ${arr.length} , time: ${spendTime / 1000 } s` ) } module .exports = {  swap,   generateOrderedArray,   generateRandomArray,   generateRandomArrayByStartAndEnd,   isSorted,   testSort }