把键当作可索引的类别
若每条记录的键可表示为0到R减一之间的整数,可以为每种键准备一个计数槽。扫描输入时按键增加频数,便知道每一类别占多少位置;与比较排序不同,这一步利用了键的表示和范围。
记录除键以外还可能包含姓名、时间或其他内容。若只需要一组整数的排序结果,可以按频数重新列出整数;若要保留原始记录及其关联内容,则还需要把每条记录分配到对应输出位置,不能仅输出键值而丢掉其余数据。
参考:[1]
累计频数确定输出区间
将频数累加后,可以求出每种键之前有多少条记录,得到该键在输出中的起始位置。再次扫描输入,把记录写入相应类别的下一个空位,并推进那个类别的位置;不同键于是落在互不重叠、按键递增的区间。
按输入从前到后分配,同键记录也按相同先后进入输出,形成稳定的计数排序。位置数组常与频数共用存储,因而分配过程中计数内容会改变;后续若还需原频数,应另行保留,不能把已经推进的位置误作最初统计。
参考:[1]
线性界包含键范围
处理n条记录、R个可能键的典型稳定版本,需要O(n+R)时间及O(n+R)额外空间。只有R相对可控时,这个代价才有吸引力;少数记录的键若散布在极大整数范围,直接为每个可能值开槽会浪费大量资源。
这不违反比较排序的下界,因为算法使用了比较之外的键索引信息。字符编码、负数偏移和键到类别的映射,都必须与目标顺序一致;把任意字符串简单当作整数类别,并不能自动得到人类语言的正确排序。