归并排序、快速排序

归并排序、快速排序

时间复杂度为o(nlogn)

分治思想:分治,顾名思义,就是分而治之(divide and conquer),将一个大问题分解成一个小的子问题来解决,小的问题解决了,大问题也就解决了。

(分治是一种解决问题的处理思想,递归是一种编程技巧,这两者并不冲突

  • 归并排序(Merge Sort)

核心思想:如果要排序一个数组,我们先把数组从中间分成前后两部分,然后对前后两部分分别排序,再将排好序的两部分合并在一起,这样整个数组就有序了。

写递归代码的技巧

  • 分析出递推公式

 Merge_sort(p...r)=merge(merge_sort(p...q),merge_sort(q+1...p))    q=(q+r)/2

  • 然后找到终止条件

p>=r  不用再继续分解

merge函数作用就是将已经有序的a[p...q]和a[q+1...r]合并成一个有序的数组。(我们申请一个临时数组temp,大小和a[]相同,用两个游标i,j,分别指向a[p...q]和a[q+1...r]的第一个元素,比较这两个元素a[i]和a[j],如果a[i]<a[j],我们就把a[i]放入到临时数组temp,并将i后移一位,否则将a[j]放入到数组temp,j后移一位。)

动态演示:

代码:(c)

void Merge(int a[], int temp[], int start, int mid, int end)

{

    int i = start, j = mid + 1, k = start;

    while (i != mid + 1 && j != end + 1)

    {

    if (a[i] <= a[j])

    temp[k++] = a[i++];

    else

    temp[k++] = a[j++];

    }

    while (i != mid + 1)

    temp[k++] = a[i++];

    while (j != end + 1)

    temp[k++] = a[j++];

    for (i = start; i <= end; i++)
    
    {

    a[i] = temp[i];

    }

}

//内部使用递归

void merge_sort(int a[], int temp[], int start, int end)

{

    int mid;

    if (start < end)
    
    {

    mid = start + (end-start) / 2;  //避免溢出int

    merge_sort(a, temp, start, mid);
    
    merge_sort(a, temp, mid + 1, end);

    Merge(a, temp, start, mid, end);

    }

}

结论:

  • 归并排序是一个稳定的排序算法。
  • 归并排序的时间复杂度(最好、最坏、平均时间复杂度都是o(nlogn))。
  • 归并排序不是原地排序算法,空间复杂度为o(n)。

  • 快速排序(Quick_Sort)

核心思想:如果要排序的数组中下标从p到r之间的一组数据,我们选择p到r之间的任意一个数据作为pivot(分区点)。我们遍历p到r之间的数据,将小于pivot的放到左边,将大于pivot的放到右边,将pivot放到中间。经过这一步骤之后,数组p到r之间的数据就被分成了三部分,前面的p到q-1之间都是小于pivot的,中间是pivot,后面的q+1到r之间是大于pivot的。

  • 递推公式:

quick_sort(p...r)=quick_sort(p...q-1)+quick_sort(q+1...r)      q=pivot

  • 终止条件:p>=r

动态演示:

 代码:(c)

void swap(int* p1, int* p2)

{

    int temp = *p1;

    *p1 = *p2;

    *p2 = temp;

}

int partition(int a[], int start, int end)

{

    int pivot = a[start];

    int i = end;

    for (int j = end; j >start; j--)

    {

        if (a[j] > pivot)

        {

        swap(&a[i],&a[j]);

        i++;

        }

    }

    swap(&a[i],&a[start]);

    return i;

}

void quick_sort(int a[],int start,int end)

{

    if (start < end)

    {

    int q = partition(a,start,end);  //获取分区点

    quick_sort(a, start, q - 1);

    quick_sort(a, q + 1, end);

    }
    
}

结论:

  • 快速排序是原地排序算法。
  • 快速排序是一种不稳定的排序算法。
  • 快速排序的时间复杂度(最好情况是o(nlogn),最坏情况是o(n²),平均情况是o(nlogn))
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值