为什么合并排序和快速排序的平均时间复杂度都是O(nlogn)

合并排序和快速排序的平均时间复杂度都是O(nlogn)的原因:它们都采用了分治策略,将问题分解成子问题并递归地求解。合并排序算法将待排序序列不断划分成两个子序列,直到每个子序列只有一个元素;快速排序算法每次分割操作将数组分成两个长度较为相等的部分。

一、合并排序和快速排序的平均时间复杂度都是O(nlogn)的原因

合并排序和快速排序的平均时间复杂度都是 O(nlogn),是因为它们都采用了分治策略,将问题分解成子问题并递归地求解。

合并排序

当我们计算合并排序的时间复杂度时,需要考虑拆分和合并这两部分。在每一次拆分中,我们将输入数组划分成两个子数组,其中每个子数组的长度为n/2,因此我们需要做log(n)轮拆分。每一轮拆分的时间复杂度为O(n),因此平均时间复杂度为O(nlogn)。

快速排序

快速排序算法中每次分割操作将数组分成了两个长度相等的部分,因此需要做log(n)次分割。在每个分割操作中,需要扫描数组一次找到最终位置的关键值,并将其与数组中的其他值分成两个部分。因此,每个分割操作的时间复杂度为O(n),平均时间复杂度为O(nlogn)。

二、合并排序简介

合并排序是采用分治策略实现对N个元素进行排序的算法,是分治法的一个典型应用和完美体现,它是一种平衡,简单的二分分治策略,计算过程分为三步:

  1. 分解:将待排序元素分成大小大致相同的两个子序列。
  2. 求解子问题:用合并排序法分别对两个子序列递归地进行排序。
  3. 合并:将排好序的有序子序列进行合并,得到符合要求的有序序列。

算法步骤

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;
  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置;
  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
  4. 重复步骤 3 直到某一指针达到序列尾;
  5. 将另一序列剩下的所有元素直接复制到合并序列尾。

代码

int min(int x, int y) {
    return x < y ? x : y;
}
void merge_sort(int arr[], int len) {
    int* a = arr;
    int* b = (int*) malloc(len * sizeof(int));
    int seg, start;
    for (seg = 1; seg < len; seg += seg) {
        for (start = 0; start < len; start += seg + seg) {
            int low = start, mid = min(start + seg, len), high = min(start + seg + seg, len);
            int k = low;
            int start1 = low, end1 = mid;
            int start2 = mid, end2 = high;
            while (start1 < end1 && start2 < end2)
                b[k++] = a[start1] < a[start2] ? a[start1++] : a[start2++];
            while (start1 < end1)
                b[k++] = a[start1++];
            while (start2 < end2)
                b[k++] = a[start2++];
        }
        int* temp = a;
        a = b;
        b = temp;
    }
    if (a != arr) {
        int i;
        for (i = 0; i < len; i++)
            b[i] = a[i];
        b = a;
    }
    free(b);
}

三、快速排序简介

快速排序的基本思想是随机找出一个数,可以随机取,也可以取固定位置,一般是取第一个或最后一个称为基准,然后就是比基准小的放在左边,比基准大的放到右边。如何放呢?就是和基准进行交换,这样交换完左边都是比基准小的,右边都是比较基准大的,这样就将一个数组分成了两个子数组,然后再按照同样的方法把子数组再分成更小的子数组,直到不能分解为止。快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。

算法步骤

  1. 从数列中挑出一个元素,称为 “基准”(pivot)。
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

代码

typedef struct _Range {
    int start, end;
} Range;
Range new_Range(int s, int e) {
    Range r;
    r.start = s;
    r.end = e;
    return r;
}
void swap(int *x, int *y) {
    int t = *x;
    *x = *y;
    *y = t;
}
void quick_sort(int arr[], const int len) {
    if (len <= 0)
        return; //避免len等于负值时错误
    //r[]模拟堆疊,p为数量,r[p++]为push,r[--p]为pop且取得元素
    Range r[len];
    int p = 0;
    r[p++] = new_Range(0, len - 1);
    while (p) {
        Range range = r[--p];
        if (range.start >= range.end)
            continue;
        int mid = arr[range.end];
        int left = range.start, right = range.end - 1;
        while (left < right) {
            while (arr[left] < mid && left < right)
                left++;
            while (arr[right] >= mid && left < right)
                right--;
            swap(&arr[left], &arr[right]);
        }
        if (arr[left] >= arr[range.end])
            swap(&arr[left], &arr[range.end]);
        else
            left++;
        r[p++] = new_Range(range.start, left - 1);
        r[p++] = new_Range(left + 1, range.end);
    }
}

延伸阅读

选择排序算法简介

选择排序(Select Sort)是直观的排序,通过确定一个 Key 最大或最小值,再从带排序的的数中找出最大或最小的交换到对应位置。再选择次之。双重循环时间复杂度为 O(n^2)。算法描述为:

  • 在一个长度为 N 的无序数组中,第一次遍历 n-1 个数找到最小的和第一个数交换。
  • 第二次从下一个数开始遍历 n-2 个数,找到最小的数和第二个数交换。
  • 重复以上操作直到第 n-1 次遍历最小的数和第 n-1 个数交换,排序完成。

文章标题:为什么合并排序和快速排序的平均时间复杂度都是O(nlogn),发布者:Z, ZLW,转载请注明出处:https://worktile.com/kb/p/49352

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
Z, ZLW的头像Z, ZLW
上一篇 2023年4月15日
下一篇 2023年4月15日

相关推荐

  • 项目管理培训内容有哪些类型

    项目管理培训内容主要包括:基础知识培训、项目规划与控制培训、风险管理培训、质量管理培训、团队管理与领导力培训等。其中,基础知识培训是培训的起点,它主要涵盖项目管理的定义、项目生命周期、项目管理过程等关键概念,让参与者对项目管理有一个全面的理解。 一、基础知识培训 基础知识培训是项目管理培训的基石,主…

    2024年7月24日
    1000
  • bim项目管理平台有哪些内容

    BIM项目管理平台包含的内容主要有:项目管理模块、模型管理模块、协作与沟通模块、任务管理模块、文件管理模块、质量安全模块等。其中,项目管理模块是最核心的部分,它主要负责对项目整体进度的管理,包括项目计划、项目进度、项目成本、项目风险等方面的管理。该模块通常包含了项目信息管理、项目进度管理、项目成本管…

    2024年7月24日
    400
  • 旅游局管理哪些行业项目

    旅游局是一个专门负责管理和监管旅游活动的政府机构,主要负责的行业项目包括:旅游资源开发、旅游景区管理、旅游市场营销、旅游服务质量监管、旅游政策制定、旅游企业管理、旅游行业统计数据收集与分析、旅游规划与建设、旅游文化推广等。其中,旅游资源开发是旅游局的重要职责之一,它涉及到对旅游资源的勘查、评价、利用…

    2024年7月24日
    400
  • 项目管理的职业证书有哪些

    在项目管理领域,各种职业证书层出不穷,但以下几种证书是最为知名和公认的:PMP(项目管理专业人士)、PRINCE2(项目内控环境)、CAPM(认证项目管理师)、MSP(管理成功的项目)、ACP(敏捷认证专家)和CSM(认证Scrum Master)。各种证书的培训和取得,对从事项目管理工作的人来说,…

    2024年7月24日
    300
  • 项目管理的关键点有哪些

    项目管理的关键点包括:明确目标、制定详细计划、有效沟通、风险管理、资源分配、进度监控、质量控制、变更管理。明确目标是项目管理的基础,确保项目的所有参与者都了解并认同项目的最终目标,这是项目成功的第一步。明确目标不仅要清晰具体,还需可衡量、可实现、有时间限制和相关性。制定详细计划则是根据项目目标,分解…

    2024年7月24日
    300

发表回复

登录后才能评论
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部