惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
D
DataBreaches.Net
博客园 - 三生石上(FineUI控件)
博客园_首页
T
Tailwind CSS Blog
美团技术团队
Hugging Face - Blog
Hugging Face - Blog
博客园 - 叶小钗
大猫的无限游戏
大猫的无限游戏
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
云风的 BLOG
云风的 BLOG
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 聂微东
S
SegmentFault 最新的问题
小众软件
小众软件
酷 壳 – CoolShell
酷 壳 – CoolShell
N
Netflix TechBlog - Medium
Jina AI
Jina AI
WordPress大学
WordPress大学
U
Unit 42
J
Java Code Geeks
Blog — PlanetScale
Blog — PlanetScale
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
The Cloudflare Blog

Jiajun的技术笔记

你好,2026! TiDB 源码阅读(六):TiDB Coprocessor 源码解析 性能优化的核心思想 TiDB 源码阅读(五):索引 TiDB 源码阅读(四):AST、逻辑计划、物理计划 CockroachDB Serverless Architecture podman 无故退出 Cursor Control-L (CTRL-L) Keyboard Shortcuts in Terminal Replace docker with podman Using xmonad with xfce4 A RC script for freebsd frpc 自己动手写一个k8s controller AI 会取代你的(编程)岗位吗? 自建DERP服务器提升Tailscale连接速度(使用Nginx转发) 自动升级Docker容器 再读《程序员修炼之道-从小工到专家》 让浏览器下载文件 再读《软件随想录》/《黑客与画家》/《软技能》 HTTP 压力测试中的 Coordinated Omission 2的补码 编程语言中的 context 是什么? flutter macOS 构建出错 Flatpak 使用小记 Golang CAS 操作是怎么实现的 PostgreSQL 当MQ来使用 Clash 结合 工作VPN 的网络设计 使用 PostgreSQL 搭建 JuiceFS PostgreSQL 配置优化和日志分析 有GitHub Copilot?那就可以搭建你的ChatGPT4服务 窗口函数的使用(以PG为例)
Golang sort源码阅读
Jiajun Huang · 2020-05-16 · via Jiajun的技术笔记

复习算法

  • 插入排序(insertion sort) 插入排序 可以想象为打牌的时候,我们抓到一张牌之后,从右往左 (或者从左往右)找到合适的位置,然后插入。它的时间复杂度是O(n^2)。

    insertion sort插入排序

  • 希尔排序(shell sort) 希尔排序 是插入排序的一种改进版本,它每次以一定步长进行排序,一直重复 到步长为1为止。

  • 堆排(heapsort) 堆排序 借助了堆这个数据结构的特性,将数据放到堆以后再取出,便有了顺序。

  • 快排(quicksort) 快排 每次选取一个哨兵,然后将比它更小的放左边,比它更大的放右边, 然后递归对左右两侧的子数组进行快排的操作,最终数组便会是一个有序的数组。

看看Go的sort实现

我们来看看Go的sort是咋实现的,首先得让要排序的对象实现这个接口:

// A type, typically a collection, that satisfies sort.Interface can be
// sorted by the routines in this package. The methods require that the
// elements of the collection be enumerated by an integer index.
type Interface interface {
	// Len is the number of elements in the collection.
	Len() int
	// Less reports whether the element with
	// index i should sort before the element with index j.
	Less(i, j int) bool
	// Swap swaps the elements with indexes i and j.
	Swap(i, j int)
}

在这个接口之上,我们才能继续阅读源码,以 sort.Ints 为例:

func Ints(a []int) { Sort(IntSlice(a)) }

func Sort(data Interface) {
	n := data.Len()
	quickSort(data, 0, n, maxDepth(n))
}

看函数名,它是用的快排,但是点进去,你会发现其实它是一个混合排序算法:

func quickSort(data Interface, a, b, maxDepth int) {
	for b-a > 12 { // Use ShellSort for slices <= 12 elements
		if maxDepth == 0 {
			heapSort(data, a, b)
			return
		}
		maxDepth--
		mlo, mhi := doPivot(data, a, b)
		// Avoiding recursion on the larger subproblem guarantees
		// a stack depth of at most lg(b-a).
		if mlo-a < b-mhi {
			quickSort(data, a, mlo, maxDepth)
			a = mhi // i.e., quickSort(data, mhi, b)
		} else {
			quickSort(data, mhi, b, maxDepth)
			b = mlo // i.e., quickSort(data, a, mlo)
		}
	}
	if b-a > 1 {
		// Do ShellSort pass with gap 6
		// It could be written in this simplified form cause b-a <= 12
		for i := a + 6; i < b; i++ {
			if data.Less(i, i-6) {
				data.Swap(i, i-6)
			}
		}
		insertionSort(data, a, b)
	}
}

可以看得出来,在不同的条件下,它会使用不同的算法:

  • 当元素数量小于12时,使用shell sort(插入排序的一种更高效的改进版本)
  • 元素数量大于12且maxDepth不为0时,使用原地快排
  • maxDepth = 0时,转而使用 heap sort

所以可以看出来,Go的sort方法是比较复杂的,它结合了多种排序方法进行排序。

其实其它语言也是一样的,比如Python和Java的排序,就使用了 TimSort,也是一种 混合排序算法。