快速排序的两种常见实现方法以及思路讲解

关于快速排序

快速排序是一种高效的排序算法,它采用了分治思想,通过不断地划分区间并对子区间进行排序来实现整体排序。

算法流程如下:

  1. 从数列中选取一个元素作为枢轴(通常选择第一个元素)

  1. 分别从数列的两端扫描数列,设两个指针left和right

  1. 将小于枢轴的元素移动到左边,大于枢轴的元素移动到右边,直到left和right相遇

  1. 将枢轴元素放在相遇点,此时数列被分成了两个子区间

  1. 分别对左右子区间递归地进行上述操作,直到整个数列有序

快速排序的时间复杂度取决于枢轴选取的方式,如果每次都能够将数列划分为大小接近的两个子区间,则时间复杂度为O(nlogn),为一种非常高效的排序算法

快速排序的递归实现

#include <iostream>
using namespace std;

void quickSort(int arr[], int left, int right) {
    int i = left, j = right;
    int pivot = arr[(left + right) / 2];
    int temp;

    while (i <= j) {
        while (arr[i] < pivot)
            i++;
        while (arr[j] > pivot)
            j--;
        if (i <= j) {
            temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
            i++;
            j--;
        }
    }
    if (left < j)
        quickSort(arr, left, j);
    if (i < right)
        quickSort(arr, i, right);
}

int main() {
    int arr[] = { 3,6,8,10,1,2,1 };
    int n = sizeof(arr) / sizeof(arr[0]);
    quickSort(arr, 0, n - 1);
    for (int i = 0; i < n; i++)
        cout << arr[i] << " ";
    return 0;
}

这是经典的使用递归来实现快速排序算法,也是较为常见的一种模式。首先,它选取数组中的中间元素作为枢轴,然后从两端向中间扫描数组元素,将小于枢轴的元素移到左边,将大于枢轴的元素移到右边,最后递归调用快速排序函数来对左右两个部分进行排序。

快速排序的迭代实现

以下为快速排序的迭代实现,这种实现方式会使用更少的递归调用,因此适用于数据量较大的场景。

#include <iostream>
#include <stack>
using namespace std;

void quickSort(int arr[], int left, int right) {
    stack<int> s;
    s.push(left);
    s.push(right);
    while (!s.empty()) {
        int r = s.top();
        s.pop();
        int l = s.top();
        s.pop();
        int pivot = arr[(l + r) / 2];
        int i = l, j = r;
        while (i <= j) {
            while (arr[i] < pivot)
                i++;
            while (arr[j] > pivot)
                j--;
            if (i <= j) {
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
                i++;
                j--;
            }
        }
        if (l < j) {
            s.push(l);
            s.push(j);
        }
        if (i < r) {
            s.push(i);
            s.push(r);
        }
    }
}

int main() {
    int arr[] = { 3,6,8,10,1,2,1 };
    int n = sizeof(arr) / sizeof(arr[0]);
    quickSort(arr, 0, n - 1);
    for (int i = 0; i < n; i++)
        cout << arr[i] << " ";
    return 0;
}

使用迭代法实现快速排序的思路主要如下:

  1. 使用栈来存储每一个待排序的区间,初始时将整个数组的左右索引压入栈中。

  1. 每次从栈中弹出一个区间,在该区间内选取一个元素(通常选择中间元素)作为枢轴。

  1. 使用两个指针,从区间的两端开始向中间移动,移动过程中将小于枢轴的元素移动到左边,大于枢轴的元素移动到右边。

  1. 将枢轴两边的子区间分别压入栈中,并继续对子区间进行排序。

  1. 重复上述过程直至栈为空。

这种方法的优点是能够避免递归带来的栈空间的限制,能够更好的处理大规模的数据。同时,由于栈的特性,也能较好地保证算法的稳定性。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 好的,快速排序是一种常用的排序算法,它的思路是选取一个基准点,将数组分为左右两部分,左边的数都比基准点小,右边的数都比基准点大,然后递归对左右两部分进行排序,最终得到一个有序的数组。 对于这个数组 {49, 38, 65, 97, 76, 13, 27, 49},我们可以选择第一个数 49 作为基准点,将数组分为左右两部分: ``` 左边:38 13 27 右边:65 97 76 49 49 ``` 接着,对左右两部分分别进行递归排序,左边的数组可以再次选择第一个数 38 作为基准点,将数组分为左右两部分: ``` 左边:13 27 38 右边: ``` 此时左边的数组已经有序了,右边的数组也是空数组,排序完成。接下来对右边的数组进行排序,选择第一个数 65 作为基准点,将数组分为左右两部分: ``` 左边:49 49 右边:97 76 65 ``` 对左右两部分分别进行递归排序,左边的数组已经有序了,右边的数组再次选择第一个数 97 作为基准点,将数组分为左右两部分: ``` 左边:76 65 右边:49 49 ``` 对左右两部分分别进行递归排序,左边的数组已经有序了,右边的数组再次选择第一个数 49 作为基准点,将数组分为左右两部分: ``` 左边: 右边:49 ``` 此时左边的数组是空数组,右边的数组已经有序了,排序完成。 最终得到的有序数组是:13 27 38 49 49 65 76 97。 ### 回答2: 快速排序是一种基于比较的排序算法,它的思路是通过划分和递归来实现排序。 第一步,选择一个基准元素。我们可以选择列表中的任意一个元素作为基准,这里我们选择第一个元素49。 第二步,划分。将列表中小于基准元素的数放在基准元素的左边,大于基准元素的数放在基准元素的右边。通过一趟划分操作后,49左边的数都比49小,右边的数都比49大。经过第一次划分后,列表变为: 13, 38, 27, 49, 76, 97, 65, 49 第三步,递归。对基准元素的左右两个子列表进行递归操作,直到子列表的长度为1或0,即不需要再进行排序为止。 对于基准元素左边的子列表来说,我们选择38作为基准元素,进行划分操作。划分后的列表为: 13, 27, 38, 49, 76, 97, 65, 49 继续对子列表进行递归操作,对基准元素右边的子列表来说,我们选择76作为基准元素,进行划分操作。划分后的列表为: 13, 27, 38, 49, 49, 65, 76, 97 再次对子列表进行递归操作。此时,左右子列表长度都为1或0,排序完成。最终的有序列表为: 13, 27, 38, 49, 49, 65, 76, 97 快速排序思路是通过划分和递归来实现排序。每次划分都选择一个基准元素,将小于基准元素的数放在左边,大于基准元素的数放在右边。通过递归操作,不断将子列表进行划分,直到子列表长度为1或0为止。最终得到一个有序列表。 ### 回答3: 快速排序是一种常用的排序算法,其基本思想是选取一个基准元素,通过不断划分将数组分为两个子数组,左子数组的元素都小于等于基准元素,右子数组的元素都大于等于基准元素,然后对两个子数组分别进行递归排序,直到子数组的长度为1时结束。下面以给定数组[49, 38, 65, 97, 76, 13, 27, 49]为例进行快速排序讲解。 首先,选择基准元素。一种常见的选择方法是选择数组的第一个元素,即49。 然后,将数组分为两个子数组,小于等于基准元素的元素放在左边,大于等于基准元素的元素放在右边。经过一次划分后,得到子数组[38, 13, 27, 49, 49]和[65, 97, 76],此时基准元素的位置为第一个49。 接着,对左右子数组进行递归排序。对于左子数组[38, 13, 27, 49, 49],选择新的基准元素为38,再次进行划分,得到子数组[13, 27]和[49, 49],此时基准元素的位置为第二个49。对于右子数组[65, 97, 76],选择新的基准元素为65,再次进行划分,得到子数组[65]和[97, 76],此时基准元素的位置为第一个97。 继续对子数组进行递归排序,左子数组[13, 27]不需要划分,右子数组[49, 49]选择新的基准元素为49,再次进行划分,得到子数组[49]和[49],基准元素的位置为第一个49。右子数组[97, 76]选择新的基准元素为97,不需要划分。 最后,排序完成后的数组为[13, 27, 38, 49, 49, 65, 76, 97]。 快速排序的时间复杂度为O(nlogn),其中n为数组的长度。快速排序是一种原地排序算法,不需要占用额外的内存空间,具有较好的排序性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SegTr_LX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值