Merge Sort. $O(1),O(N\log N) $

本文介绍了一种高效的排序算法——归并排序,详细解释了其原理和实现过程,并提供了Python代码示例。归并排序是一种稳定的排序算法,时间复杂度为$O(nlogn)$,空间复杂度为$O(1)$。

归并排序

Tips:
1. a = b + c*2**k
2. b =  a % c =   a & (k-1)
3. c =  a // 2**k = a >> k
For example:
1.  643 = 3 + 20*2**5
2.  3 = 643 % 32 = 643 & 31
3.  20 = 643 // 32 = 643 >> 5
import math
from typing import List


def getPower2(n: int):
    """Returns a power of two size for the given target n.
    max is 2**32
    Tips:
        keep moving to the right to make all the bits 1
        From JDK1.8 HashTable.
    """
    if n < 2:
        raise Exception("the number must be greater than 1.")
    n -= 1
    n |= n >> 1
    n |= n >> 2
    n |= n >> 4
    n |= n >> 8
    n |= n >> 16
    return (n+1, int(math.log2(n+1)))


def merge_sort(arr: List[int]):
    """Divide and conquer algorithm.
    Complexity:
        Time: $O(n\logn)$
        Space: $O(1)$
        Stable: yes
    Example:
    >>> raw_data = [0, 10, 15, 9, 3, 13, 21, 6, 8, 10]
    >>> merge_sort(raw_data)
    [0, 3, 6, 8, 9, 10, 10, 13, 15, 21]
    >>> raw_data
    [0, 10, 15, 9, 3, 13, 21, 6, 8, 10]
    """
    # Copy arr, don't change raw data.
    arr = arr[:]
    max_num, power = getPower2(max(arr)+1)

    def merge(left, mid, right):
        """Once merge
        """
        i, j, k = left, mid + 1, left
        while i <= mid and j <= right:
            # Compare
            a = arr[i] & (max_num - 1)
            b = arr[j] & (max_num-1)
            if a < b:
                arr[k] = arr[k] + a * max_num
                i += 1
            else:
                arr[k] = arr[k] + b * max_num
                j += 1
            k += 1
        # Checking if any elements was left
        while i <= mid:
            arr[k] = arr[k] + (arr[i] & (max_num - 1)) * max_num
            i += 1
            k += 1
        while j <= right:
            arr[k] = arr[k] + (arr[j] & (max_num - 1)) * max_num
            j += 1
            k += 1
        # Restore
        for i in range(left, right + 1):
            arr[i] >>= power

    def merge_sort_rec(left, right):
        # recurse return point.
        if left >= right:
            return
        mid = (left + right) >> 1
        # Divide
        merge_sort_rec(left, mid)
        merge_sort_rec(mid+1, right)
        merge(left, mid, right)

    merge_sort_rec(0, len(arr) - 1)
    return arr


if __name__ == "__main__":
    import doctest
    doctest.testmod(verbose=True)

<think> 我们正在寻找在Delphi中实现时间复杂度为O(n log n)的操作的例子。常见的O(n log n)算法包括快速排序、归并排序、堆排序等。由于用户提到了“操作”,我们可以展示一个排序算法的实现,因为排序是常见的O(n log n)操作。 在Delphi中,我们可以实现归并排序(Merge Sort)作为例子,因为它的最坏时间复杂度也是O(n log n),且稳定。 我们将编写一个归并排序的Delphi实现。 归并排序的基本思想是分治法:将数组分成两半,分别对两半进行排序,然后将两个有序数组合并成一个有序数组。 注意:我们将使用递归实现,也可以使用迭代实现(自底向上)以避免递归栈开销,但这里为了清晰使用递归。 我们将实现两个函数: 1. 主函数:MergeSort,负责调用递归排序过程。 2. 合并函数:Merge,负责合并两个有序数组。 另外,用户提供的引用[1]是一个Python监控进程创建的代码片段,与Delphi和排序算法无关,因此我们忽略它,专注于用户当前的需求。 步骤: 1. 定义MergeSort过程,参数为待排序的数组(动态数组)以及数组的左右索引(左闭右闭区间)。 2. 当子数组长度大于1时,找到中点,递归排序左半部分和右半部分,然后合并。 3. 合并过程需要临时数组,将两个有序数组合并为一个有序数组。 我们假设数组中的元素是整数,但可以很容易地改为泛型以支持更多类型。 由于用户要求时间复杂度为O(n log n),归并排序满足这个要求。 代码实现如下: </think> 在 Delphi 中实现时间复杂度为 $O(n \log n)$ 的操作,通常涉及使用高效的排序或搜索算法。以下是几种常见实现方法及代码示例: ### 1. 归并排序 (典型 $O(n \log n)$ 算法) ```pascal procedure MergeSort(var A: array of Integer; Low, High: Integer); var Mid, i, j, k: Integer; Temp: array of Integer; begin if Low < High then begin Mid := (Low + High) div 2; MergeSort(A, Low, Mid); // 递归排序左半部 MergeSort(A, Mid + 1, High); // 递归排序右半部 // 合并有序数组 SetLength(Temp, High - Low + 1); i := Low; j := Mid + 1; k := 0; while (i <= Mid) and (j <= High) do begin if A[i] <= A[j] then begin Temp[k] := A[i]; Inc(i); end else begin Temp[k] := A[j]; Inc(j); end; Inc(k); end; // 复制剩余元素 while i <= Mid do begin Temp[k] := A[i]; Inc(i); Inc(k); end; while j <= High do begin Temp[k] := A[j]; Inc(j); Inc(k); end; // 写回原数组 for k := 0 to High - Low do A[Low + k] := Temp[k]; end; end; // 调用示例 var Data: array of Integer; begin Data := [5, 2, 9, 1, 5, 6]; MergeSort(Data, Low(Data), High(Data)); end; ``` ### 2. 堆排序 (同样 $O(n \log n)$) ```pascal procedure Heapify(var A: array of Integer; Idx, Len: Integer); var Largest, Left, Right: Integer; begin Largest := Idx; Left := 2 * Idx + 1; Right := 2 * Idx + 2; if (Left < Len) and (A[Left] > A[Largest]) then Largest := Left; if (Right < Len) and (A[Right] > A[Largest]) then Largest := Right; if Largest <> Idx then begin Swap(A[Idx], A[Largest]); // 交换函数需自行实现 Heapify(A, Largest, Len); end; end; procedure HeapSort(var A: array of Integer); var i, Len: Integer; begin Len := Length(A); // 建堆 for i := (Len div 2) - 1 downto 0 do Heapify(A, i, Len); // 提取元素 for i := Len - 1 downto 0 do begin Swap(A[0], A[i]); Heapify(A, 0, i); end; end; ``` ### 3. 二分搜索 ($O(\log n)$ 操作) ```pascal function BinarySearch(const A: array of Integer; Target: Integer): Integer; var Low, High, Mid: Integer; begin Low := 0; High := High(A); while Low <= High do begin Mid := (Low + High) div 2; if A[Mid] = Target then Exit(Mid) else if A[Mid] < Target then Low := Mid + 1 else High := Mid - 1; end; Result := -1; // 未找到 end; ``` ### 优化建议 1. **内存管理**:归并排序需要额外空间,大数据集可考虑堆排序 2. **递归深度**:对于极大数据集,迭代式归并排序可避免栈溢出 3. **并行优化**:使用 `TParallel.For` (需 `System.Threading`) 加速分治过程 4. **实际场景选择**: - 小数据集:快速排序(平均 $O(n \log n)$) - 大数据集:堆排序/归并排序 - 搜索:二分搜索前提是数组有序 > 关键点:所有对数级复杂度操作都依赖于 **分治策略** 或 **树结构**,通过减少每次操作的处理范围实现高效计算[^1]。 *** ### 相关问题 1. Delphi 中如何实现线程安全的 $O(n \log n)$ 算法? 2. 归并排序和快速排序在 Delphi 中的实际性能差异有哪些? 3. 如何处理超大数组(超过内存限制)的 $O(n \log n)$ 排序? 4. Delphi 的内置排序函数 `TArray.Sort` 使用什么算法?它的时间复杂度是多少?
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值