常见的排序算法

本文总结下常考的排序算法

快速排序

平均时间复杂度 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
}

参考资料:

[十大经典排序算法](

posted @   EGBDFACE  阅读(43)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示