
直接访问数组排序是一种利用键作为数组索引的线性时间排序算法。它通过将待排序的完整对象(包含键和值)直接放置到辅助数组中对应键的位置,然后按顺序遍历辅助数组来重构已排序的原始数组。该方法的核心在于利用键的特性实现o(n+u)的效率,但对键的范围和类型有特定要求,适用于键为非负整数且范围不大的场景。
直接访问数组排序原理
直接访问数组排序(Direct Access Array Sort)是一种非比较型排序算法,其核心思想是利用待排序元素的“键”(key)作为辅助数组的索引。这种方法假设所有键都是唯一的非负整数,并且在一个可管理的范围内。通过这种直接映射关系,算法能够以线性时间复杂度完成排序。
理解该算法的关键在于明确它排序的是完整的对象(或称作项,item),而不仅仅是键本身。当一个对象被“排序”时,意味着其在最终序列中的位置是根据其键值来确定的。算法将每个包含键和值的对象放置到一个根据其键值索引的辅助数组中。完成所有对象的放置后,只需顺序遍历辅助数组,即可按照键的自然顺序提取出所有对象,从而实现对原始数组的排序。
算法步骤详解
以下是直接访问数组排序的Python实现示例,我们将逐一解析其工作流程。
def direct_access_sort(A):
"""
使用直接访问数组对列表A进行排序。
假设A中的每个元素都是一个具有'key'属性的对象,
且所有key都是不同的非负整数。
"""
# 1. 确定键的范围(最大键值)
# 遍历所有元素,找到最大的键值,然后u表示辅助数组的大小(0到最大键值)
u = 1 + max([x.key for x in A]) # O(n) 操作,n为A中元素的数量
# 2. 初始化直接访问数组D
# 创建一个大小为u的辅助数组D,所有位置初始为None
D = [None] * u # O(u) 操作,u为键的范围
# 3. 将元素插入到直接访问数组D中
# 遍历原始数组A中的每个元素x,将其放置到D中以x.key为索引的位置
for x in A: # O(n) 操作
D[x.key] = x
# 4. 从D中按序读出元素,重构已排序的A
# 初始化一个计数器i,用于记录A中当前要填充的位置
i = 0
# 遍历从0到u-1的所有可能的键值
for key in range(u): # O(u) 操作
# 如果D[key]不为None,说明该键值对应的位置有存储的元素
if D[key] is not None:
# 将该元素(完整的对象)放回原始数组A的当前位置
A[i] = D[key]
# 移动到A的下一个位置
i += 1示例分析
为了更好地理解上述过程,我们以一个具体的例子进行说明。假设我们有一个包含人名和身高(作为键)的列表,需要按身高排序。
原始输入数组 A:
A = [{key: 160, name: "Alice"}, {key: 150, name: "Bob"}, {key: 200, name: "Charlie"}, {key: 188, name: "David"}]-
确定键的范围 u:
- A 中最大的 key 是 200。
- 因此 u = 1 + 200 = 201。这意味着辅助数组 D 的索引范围是 0 到 200。
-
初始化直接访问数组 D:
- D 将是一个包含 201 个 None 值的数组: D = [None, None, ..., None] (长度为 201)
-
插入元素到 D 中:
- 遍历 A:
- x = {key: 160, name: "Alice"} -> D[160] = {key: 160, name: "Alice"}
- x = {key: 150, name: "Bob"} -> D[150] = {key: 150, name: "Bob"}
- x = {key: 200, name: "Charlie"} -> D[200] = {key: 200, name: "Charlie"}
- x = {key: 188, name: "David"} -> D[188] = {key: 188, name: "David"}
- 此时 D 中只有索引 150, 160, 188, 200 处存储了对象,其余位置仍为 None。
- 遍历 A:
-
从 D 中按序读出元素,重构 A:
- i 初始化为 0。
- 遍历 key 从 0 到 200:
- key = 0, 1, ..., 149: D[key] 均为 None,跳过。
- key = 150: D[150] 是 {key: 150, name: "Bob"}。
- A[0] = {key: 150, name: "Bob"}
- i 变为 1。
- key = 151, ..., 159: D[key] 均为 None,跳过。
- key = 160: D[160] 是 {key: 160, name: "Alice"}。
- A[1] = {key: 160, name: "Alice"}
- i 变为 2。
- key = 161, ..., 187: D[key] 均为 None,跳过。
- key = 188: D[188] 是 {key: 188, name: "David"}。
- A[2] = {key: 188, name: "David"}
- i 变为 3。
- key = 189, ..., 199: D[key] 均为 None,跳过。
- key = 200: D[200] 是 {key: 200, name: "Charlie"}。
- A[3] = {key: 200, name: "Charlie"}
- i 变为 4。
- key = 201, ...: 循环结束。
最终,原始数组 A 被成功排序:
A = [{key: 150, name: "Bob"}, {key: 160, name: "Alice"}, {key: 188, name: "










