常见的排序算法
本文总结下常考的排序算法
快速排序
平均时间复杂度 O(nlogn),最坏时间复杂度:在未引入随机选取中间值,最坏的情况是已排序,而且每次划分都是划分成两个分别包含 n-1 个元素和 0 个元素的子问题,时间复杂度为O(n2)
空间复杂度:O(nlogn)
不稳定排序:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。
function QuickSort (arr) {
function _swap (arr, indexO, indexT) {
var temp = arr[indexO]
arr[indexO] = arr[indexT]
arr[indexT] = temp
}
function _partition (arr, start, end) {
var x = arr[end]
var small = start-1
for (var i=start; i<end; i++) {
if (arr[i] < x) {
++small
_swap(arr, small, i)
}
}
_swap(arr, small+1, end)
return small+1
}
function _randomQuickSort (arr, start, end) {
var round = Math.floor(Math.random()*(end-start+1)+start)
_swap(arr, round, end)
return _partition(arr, start, end)
}
function _quickSort (arr, start, end) {
if (start < end) {
var q = _randomQuickSort(arr, start, end)
_quickSort(arr, start, q-1)
_quickSort(arr, q+1, end)
}
}
_quickSort(arr, 0, arr.length-1)
}
链表的快排:
function QuickSortList (list) {
function _swap (p1, p2) {
var temp = p1.value
p1.value = p2.value
p2.value = temp
}
function _partition (pHead, pEnd) {
var x = pHead.value
// 注意这里用到了三个指针,因为每次都是与头结点进行比较大小
var pSlow = pHead, pFast = pHead.next, pTemp = pHead
while (pFast !== null && pFast !== pEnd.next) {
if (pFast.value < x) {
pTemp = pSlow
pSlow = pSlow.next
_swap(pSlow, pFast)
}
pFast = pFast.next
}
_swap(pSlow, pHead)
return pTemp
}
function _quickSort (pHead, pEnd) {
if (pHead !== pEnd) {
var p = _partition (pHead, pEnd)
_quickSort (pHead, p)
_quickSort (p.next, pEnd)
}
}
var head = list, end = list
while (end && end.next !== null) end = end.next // 使用前检测,可能为空链表
_quickSort(head, end)
return list
}
归并排序
时间复杂度 O(nlogn)
空间复杂度 O(n)
稳定排序
function mergeSort (arr) {
function _mergeTwoSortedArrs (arr1, arr2) {
// 这里返回一个新数组便于后续操作
var res = []
while (arr1.length > 0 && arr2.length > 0) {
if (arr1[0] > arr2[0]) {
res.push(arr2.shift())
} else {
res.push(arr1.shift())
}
}
if (arr1.length > 0) {
res.push(...arr1)
}
if (arr2.length > 0) {
res.push(...arr2)
}
return res
}
function _mergeRecursive (arr) {
if (arr.length < 2) return arr
var mid = Math.floor(arr.length/2)
var leftArr = arr.slice(0,mid)
var rightArr = arr.slice(mid)
return _mergeTwoSortedArrs(_mergeRecursive(leftArr), _mergeRecursive(rightArr))
}
return _mergeRecursive(arr)
}
堆排序
升序:构建大顶堆;降序:构建小顶堆
不稳定排序
时间复杂度: O(nlogn)
空间复杂度: O(1)
function heapSort (arr) {
function _swap (arr, i, j) {
var temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}
function _buildMaxHeap (arr) {
for (var i=Math.floor(arr.length/2); i>=0; i--) {
_heapAdjust(arr, i, arr.length)
}
}
function _heapAdjust (arr, i, length) {
var left = 2*i+1, right = 2*i+2, largest = i
if (left < length && arr[left] > arr[largest]) {
largest = left
}
if (right < length && arr[right] > arr[largest]) {
largest = right
}
if (largest !== i) {
_swap(arr, largest, i)
_heapAdjust(arr, largest, length)
}
}
function _sort (arr) {
_buildMaxHeap(arr)
var length = arr.length
for(var i=length-1; i>0; i--) {
_swap(arr, 0, i)
length--
_heapAdjust(arr, 0, length)
}
}
_sort(arr)
}
冒泡排序
稳定排序
链表冒泡排序
function bubbleSortList (list) {
if (!list) return list
for (let pNode1 = list; pNode1.next !== null; pNode1 = pNode1.next) {
let flag = true
for (let pNode2 = list; pNode2.next !== null; pNode2 = pNode2.next) {
if (pNode2.value > pNode2.next.value) {
flag = false
var temp = pNode2.value
pNode2.value = pNode2.next.value
pNode2.next.value = temp
}
}
if (flag) return list
}
return list
}
参考资料:
[十大经典排序算法](
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了