归并排序和快速排序

博客介绍了归并排序和快速排序两种快速排序算法。归并排序先递归后合并,时间复杂度稳定为O(nlogn),但需额外空间;快速排序利用二分法和递归,空间复杂度为O(1),时间复杂度不稳定。还对比了二者排序顺序的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这篇博客记录一下两种比较快速的排序。

归并排序和快速排序。


归并排序(\(O(nlogn)\)

归并排序,顾名思义就是先递归后合并,这里画了一张图简单理解归并过程:

1732842-20190712111700979-1112076114.jpg

代码肯定要用到递归啦,递归到不能再细分就可以开始合并了。而合并是通过申请额外的内存空间来完成的,合并时在左右两个区间内进行比较,按照大小依次放入额外的空间中,最后复制回原数组,这样一直递归往上,就实现了排序。

代码:

void merge_sort(int arr[], int a,int b)//递归
{
    if (a >= b)
        return;
    int mid = (a + b) / 2;
    merge_sort(arr, a, mid);
    merge_sort(arr, mid + 1, b);
    merge(arr, a, mid, b);
}

void merge(int arr[], int l, int mid, int r)//合并
{
    int *temp=new int[r - l + 1];//申请额外空间
    int i = l, j = mid + 1, k = 0;
    while (i <= mid && j <= r)//比较并存放在额外的空间里
    {
        if (arr[i] <= arr[j])
            temp[k++] = arr[i++];
        else
            temp[k++] = arr[j++];
    }
    /*将剩下元素的放入额外空间*/
    while (i <= mid)
        temp[k++] = arr[i++];
    while (j <= r)
        temp[k++] = arr[j++];
    for (int i = l; i <= r; i++)//复制回原空间
        arr[i] = temp[i - l];
    delete[]temp;
}

时间复杂度推算:

1732842-20190712111836999-1487251210.jpg

归并排序的一大好处就是不管数据是什么样的,它的时间复杂度都为\(O(nlogn)\)。但它的缺点就是会用额外空间,空间复杂度为\(O(n)\)


快速排序

快速排序也是利用二分法和递归进行排序。

下面是简单的快排过程:

1732842-20190712111849946-1599031622.jpg

快排的核心就在\(partition\)这个函数,他的作用就是再区间里随机找一个点(一般找最右边哪个元素),将这个点作为中心点,将比他小的元素放在左边,比他大的元素放在右边(升序),然后不断二分最后就得到一个排列好的数组了。

void quick_sort(int arr[], int a, int b)
{
    if (a >= b)
        return;
    int p = partition(arr, a, b);
    quick_sort(arr, a, p - 1);
    quick_sort(arr, p + 1, b);//这里一定是p+1,将中心点排除在外,不然会在区间里有重复元素的时候陷入死循环!!!!
}

int partition(int arr[], int a, int b)
{
    int i = a, j;
    int p = arr[b];//记录中心点
    for (j = a; j < b; j++)
    {
        if (arr[j] < p)//找到比中心点小的元素就交换
        {
            swap(arr[i], arr[j]);
            i++;
        }
    }
    swap(arr[i], arr[b]);//将中心点交换到中间
    return i;//返回中心点下标
}

因为快排是个空间复杂度为\(O(1)\)的原地排序,所以在找中心点的时候为了不用额外空间算法设计的很巧妙。

这里将\(i\)作为一个游标,他的左边是已经处理的区间,右边为未处理区间,用\(j\)去找那些比中心点小的元素并和\(i\)交换,最后把选定的中心点和\(i\)交换就完成处理了。

值得注意的是快排是一种时间复杂度不稳定的算法,它一般情况下时间复杂度为\(O(nlogn)\),但在极端条件下会退化为\(O(n^2)\)


快速排序和归并排序的区别

快速排序和归并的区别就在于它正好和递归的排序反过来。快速排序先排序再递归细分,排序是从上到下的。归并排序先递归细分再排序,排序是从下到上的。

转载于:https://www.cnblogs.com/JMWan233/p/11175006.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值