常用模板1:快速排序

参考:https://www.acwing.com/blog/content/277/

快速排序模板

void quick_sort(int q[], int l, int r)
{
    if (l >= r) 
    	return;

    int i = l - 1, j = r + 1, x = q[l + r >> 1];
    while (i < j)
    {
       	while(q[i] < x) 
       		i++;
		while(q[j] > x) 
			j--;
        if (i < j) 
        	swap(q[i], q[j]);
    }
    quick_sort(q, l, j), quick_sort(q, j + 1, r);
}

本模板实现的是升序排序,改降序的话直接修改while里面的符号,改成

while(q[i] > x) i++;
while(q[j] < x) j--;

即可。

模板思路:

  • 这个函数接受三个参数:一个整数数组q,以及两个表示要排序部分的起始(l)和结束(r)的索引。
  • 在函数的开头,我们首先检查数组的长度是否大于1。如果l >= r,那么数组的长度为0或1,我们可以直接返回,因为长度为0或1的数组已经是排序好的。
  • 接下来,我们初始化两个指针i和j,分别指向数组的开始和结束,然后选择基准元素x。这里的基准元素是数组中间的元素(l + r >> 1表示(l + r) / 2,即数组的中点)。
  • while循环开始了分区操作。在这个循环中,我们首先移动i直到找到一个大于等于基准的元素然后移动j直到找到一个小于等于基准的元素,然后交换这两个元素。当i < j不再满足,循环结束,此时所有小于基准的元素都在j的左边,所有大于基准的元素都在j的右边
  • 最后,我们对基准左侧和右侧的两个子数组递归调用quick_sort函数。

两个while的解释:

while(q[i] < x) i++;和while(q[j] > x) j–;这两行代码的作用是找到需要交换的元素

  • while(q[i] < x) i++;这一行是在找数组中第一个大于等于基准元素x的元素。从左边(即较小的索引)开始遍历,只要遇到的元素小于基准元素,就将索引i向右移动一位,即i++。一旦找到一个大于等于基准元素的元素,就跳出循环。

  • 同样,while(q[j] > x) j–;这一行是在找数组中第一个小于等于基准元素x的元素。这次从右边(即较大的索引)开始遍历,只要遇到的元素大于基准元素,就将索引j向左移动一位,即j–。一旦找到一个小于等于基准元素的元素,就跳出循环。

这两步操作的目标是找到数组中的一对元素,其中左边的元素大于基准元素,右边的元素小于基准元素,然后交换这对元素。这样,在每次循环结束时,都能保证基准元素左边的元素都小于或等于基准元素,右边的元素都大于或等于基准元素,从而完成了一轮的分区操作。

使用示例

void quick_sort(int q[], int l, int r)
{
    if (l >= r) return;

    int i = l - 1, j = r + 1, x = q[l + r >> 1];
    while (i < j)
    {
        do i ++ ; while (q[i] < x);
        do j -- ; while (q[j] > x);
        if (i < j) swap(q[i], q[j]);
    }
    quick_sort(q, l, j), quick_sort(q, j + 1, r);
}

int main() {
    int arr[] = {10, 7, 8, 9, 1, 5};
    int n = sizeof(arr) / sizeof(arr[0]);
    quick_sort(arr, 0, n - 1);
    for(int i = 0; i < n; i++)
        cout << arr[i] << " ";
    return 0;
}

时间复杂度与空间复杂度

快速排序(QuickSort)的性能依赖于选择的“pivot”(基准)元素。如果恰好每次都能选择中间值,快速排序表现最好;如果每次选择的都是最小(或最大)的元素,快速排序表现最差。

  1. 时间复杂度

    • 最好情况:如果每次我们都能选取到数组的中间值作为pivot,快速排序的性能最好。这种情况下,快速排序的时间复杂度为O(n log n)。
    • 最坏情况:如果每次我们都选取到数组的最小值或最大值作为pivot,快速排序的性能最差。这种情况下,快速排序的时间复杂度为O(n^2)。
    • 平均情况:在随机选择pivot的情况下,快速排序的平均时间复杂度为O(n log n)。
  2. 空间复杂度

    • 快速排序是原地排序算法,不需要额外的存储空间,所以其空间复杂度为O(1)。但是,快速排序需要用到递归,递归需要堆栈空间。
    • 递归的深度在最坏情况下为n,在最好情况下为log n。因此,快速排序的空间复杂度通常描述为递归堆栈的大小。
    • 最好情况(平均情况):递归树的深度为log n,所以空间复杂度为O(log n)。
    • 最坏情况:递归树的深度为n,所以空间复杂度为O(n)。

空间复杂度上,O(n)是快排最差的,O(logn)是一般情况或者平均。面试被问到直接两种都说出来更好。

空间复杂度的计算

空间复杂度计算的时候, 不算上结果数组 但是会算除了结果数组之外的部分,例如开的除了结果数组之外的额外空间,和有的stl算法本身消耗的空间

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值