关于快速排序
快速排序是一种高效的排序算法,它采用了分治思想,通过不断地划分区间并对子区间进行排序来实现整体排序。
算法流程如下:
从数列中选取一个元素作为枢轴(通常选择第一个元素)
分别从数列的两端扫描数列,设两个指针left和right
将小于枢轴的元素移动到左边,大于枢轴的元素移动到右边,直到left和right相遇
将枢轴元素放在相遇点,此时数列被分成了两个子区间
分别对左右子区间递归地进行上述操作,直到整个数列有序
快速排序的时间复杂度取决于枢轴选取的方式,如果每次都能够将数列划分为大小接近的两个子区间,则时间复杂度为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;
}
使用迭代法实现快速排序的思路主要如下:
使用栈来存储每一个待排序的区间,初始时将整个数组的左右索引压入栈中。
每次从栈中弹出一个区间,在该区间内选取一个元素(通常选择中间元素)作为枢轴。
使用两个指针,从区间的两端开始向中间移动,移动过程中将小于枢轴的元素移动到左边,大于枢轴的元素移动到右边。
将枢轴两边的子区间分别压入栈中,并继续对子区间进行排序。
重复上述过程直至栈为空。
这种方法的优点是能够避免递归带来的栈空间的限制,能够更好的处理大规模的数据。同时,由于栈的特性,也能较好地保证算法的稳定性。