通过一趟排序将要排序的数据分割成两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此步骤对这两部分的数据进行快速排序,整个排序的过程可以使用递归进行。以此达到整个数据变成有序序列。
快速排序通过多次比较和多次交换来实现排序,排序历程:
(1)首先设定一个分界值,通过该分界值将数组分成左右两部分(一般分界值为第一个)
(2)将大于或等于分界值的数据集中到数组的右边,小于分界值的数据集中到数组的左边。这时,左边部分各元素小于或等于分界值,而右边部分各元素都大于或等于分界值。
(3)分别对左边和右边进行相同操作,继续寻找分界值左边和右边类似的操作,类似与递归操作。
(4)重复上述过程,递归左边和右边分别排序完成后,整个数组排序也就完成。
(一)左右指针
第一趟排序:
排序全过程:
#include
using namespace std;
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int partition(int low, int high, int a[]) {
int privotKey = a[low];
while (low < high) {
while (low < high&&a[high] >= privotKey) --high;
swap(&a[low], &a[high]);
while (low < high&&a[low] <= privotKey) ++low;
swap(&a[low], &a[high]);
}
return low;
}
void quickSort(int low, int high, int a[]) {
if (low < high) {
int privotLoc = partition(low, high, a);
quickSort(low, privotLoc - 1, a);
quickSort(privotLoc + 1, high, a);
}
}
int main() {
int array[] = { 49,38,65,97,76,13,27,49 };
for (int i = 0; i <= 7; i++) {
cout << array[i] << " ";
}
cout << endl;
quickSort(0, 7,array);
for (int i = 0; i<=7; i++) {
cout << array[i] << " ";
}
system("pause");
return 0;
}
(二)挖坑法
1.定义两个指针left指向起始位置,right指向最后一个元素的位置,然后指定一个基数key(right),作为坑
2.left寻找比基数(key)大的数字,找到后将left的数据赋给right,left成为一个坑,然后right寻找比基数(key)小的数字,找到将right的数据赋给left,right成为一个新坑,循环这个过程,直到begin指针与end指针相遇,然后将key返回给那个坑(最终:key的左边都是比key小的数,key的右边都是比key大的数),然后进行递归操作。
void quickSort(int left, int right, int a[])
{
if (left >= right) return;
//以第一个元素为基准,执行一趟划分
int i = left, j = right;
int t = a[left];
while (i < j)
{
while (i < j && a[j] >= t) //从右向左扫描,选取第一个小于t的元素交换
j--;
a[i] = a[j];
while (i < j && a[i] <= t) //再从左往右扫描,选取第一个大于t的元素交换
i++;
a[j] = a[i];
}
a[i] = t;
//递归执行划分
for (int i = 0; i <= 7; i++) {
cout << a[i] << " ";
}
cout << endl;
quickSort(left, i - 1, a);
quickSort(i + 1, right, a);
}
(三)前后指针法
1.定义两个指针,一前一后,cur(前)指向起始位置,prev(后)指向cur的前一个位置;选择数组最后一个元素作为key(right)
2.实现过程:cur找比key小的数,prev在cur没有找到的情况下,一直不动(即保证prev一直指向比key大的数);直到cur找到比key小的数(+ +prev && prev != cur时)然后++cur,prev仍然不动。
3.直到cur走到right前一个位置,终止循环。最后++prev,交换prev和right的值。返回中间位置prev。最后再继续递归。
int QuickSort_Cur(int* a,int left,int right)
{
int cur = left;
int prev = left -1;
int key = a[right];
while(cur < right)
{
if(a[cur] < key && ++prev != cur)
{
swap(a[cur],a[prev]);
}
++cur;
}
swap(a[++prev],a[right]);
return prev;
}
快速排序——非递归
利用栈保存左右区间
1. 左右区间入栈(先右后左)
2. 取栈顶元素,出栈
3. 排序
4. 入栈,先右后左(直到栈为空,停止循环)
void QuickSortNOR(int* a,int left,int right)
{
stack s;
if(left < right)
{
s.push(left);
s.push (right);
}
while(!s.empty ())
{
int right = s.top ();
s.pop ();
int left = s.top ();
s.pop();
int div = PartSort1(a,left,right);
if((right-left +1) < 20) //小区间时不再递归
{
InsertSort(a+left,right-left+1);
}
else
{
if(left < div-1)
{
s.push (left);
s.push (div-1);
}
if(div+1