📜  归并排序中哨兵的用途是什么 (1)

📅  最后修改于: 2023-12-03 15:25:35.873000             🧑  作者: Mango

归并排序中哨兵的用途是什么

在归并排序中,哨兵是一个预置在待排序序列两端的特殊元素。它们的值有助于简化归并过程中的代码实现,提高执行效率,防止越界访问等。

常见哨兵类型

常见的哨兵类型有以下几种:

  • 小哨兵:将待排序序列中的最小值预置到左端。
  • 大哨兵:将待排序序列中的最大值预置到右端。
  • 双哨兵:将待排序序列中的最小值和最大值分别预置到左右两端。
哨兵的用途
  1. 防止越界访问

在归并排序中,每次将两个有序子序列进行合并,需要先确定它们的边界位置。如果没有哨兵,那么就需要在代码中加入一系列的边界判断,使得实现逻辑很不直观,并且容易造成下标越界等错误。而哨兵的作用就在于预置确定的特殊值,使得归并时不必做边界的检查。

  1. 提高执行效率

排序算法的效率常常受限于常数时间。在归并排序的实现中,加入哨兵的好处之一就是可以避免在一些循环中进行比较、交换等操作。以左端的小哨兵为例,当找到第一个右区间元素小于等于左端哨兵的位置时,就可以退出循环,而无需再循环一遍来判断右区间是否已经全部处理完毕。

哨兵的实现

对于数组类型,我们可以在数组两端分别加上哨兵。需要注意的是,添加哨兵会增加数组的长度,因此在分配内存空间时需要多加考虑。下面是一个以小哨兵为例的归并排序实现:

def merge_sort(arr, left, right):
    if left == right:
        return
    mid = (left + right) // 2
    merge_sort(arr, left, mid)
    merge_sort(arr, mid+1, right)
    if arr[mid] <= arr[mid+1]:
        return
    merge(arr, left, mid, right)

def merge(arr, left, mid, right):
    aux = arr.copy()
    i = left
    j = mid + 1
    for k in range(left, right+1):
        if i > mid:
            arr[k] = aux[j]
            j += 1
        elif j > right:
            arr[k] = aux[i]
            i += 1
        elif aux[j] < aux[i]:
            arr[k] = aux[j]
            j += 1
        else:
            arr[k] = aux[i]
            i += 1

n = 10
arr = list(range(n))
random.shuffle(arr)

arr = [float('-inf')] + arr + [float('inf')] # 小哨兵
# arr = [-1] * n + arr + [float('inf')] # 大哨兵

print(f"Before: {arr}")
merge_sort(arr, 1, len(arr)-2)
print(f"After: {arr}")

以上代码中,通过在原数组两端加上小哨兵,可以避免在merge()函数中进行边界判断,提高了代码的可读性和执行效率。