快速排序的思想其实比较好理解,但是实际码代码的时候,会遇到一些问题,并不是想象的那么简单。
在网上看了一下,感觉大多数的博客介绍其排序原理的时候说得很生动形象,但给出的实现代码其实逻辑说得不是很清晰,甚至是错误的。
这里我自己写了一下快速排序,过程中也遇到了一些问题,但总算是解决了。这里给出来,并详细说一下其逻辑。
(1) Quick.h 头文件
#pragma once
#include "stdafx.h"
using namespace std;
class Quick
{
public:
Quick(vector<int> a);
void sort();
bool isSorted();
void show();
private:
vector<int> v;
int N;
void exch(int i, int j);
int position(int lo, int hi);
void sort(int lo, int hi);
};
(2) Quick.cpp 具体实现
#include "stdafx.h"
#include "Quick.h"
using namespace std;
Quick::Quick(vector<int> a) : v(a)
{
N = v.size();
}
void Quick::sort()
{
sort(0, N - 1);
}
void Quick::sort(int lo, int hi)
{
// random array
if (hi <= lo) return;
int j = position(lo, hi);
exch(lo, j);
sort(lo, j - 1);
sort(j + 1, hi);
}
int Quick::position(int lo, int hi)
{
int i = lo , j = hi+1; // 注意其起点
int base = v[lo];
while (1)
{
while (v[--j] > base); //就算j移到了 lo,也会因为v[j]==v[lo]==base,而退出此循环
while (v[++i] < base) if(i==j) break;
// base右侧的数组有3种情况:
// (1) 均大于base; 则j会移动到lo,i递增1次后结束;此时j<i。不需要exch(i,j),且要直接退出while(1)
// (2) 均小于base; 则j递减1次,到hi;i递增至hi;此时i==j。不需要exch(i,j),且要直接退出while(1)
// (3) 一般情况 ; 当i<j且需要交换二者时,执行exch(i,j)。假如某时刻,i和j之间的数都大于base,则j会移至i的位置,之后i会再递增1次,此时会出现j<i。
if (j <= i) break;
else exch(i, j);
}
return j;
}
void Quick::exch(int i, int j)
{
int temp = v[i];
v[i] = v[j];
v[j] = temp;
}
void Quick::show()
{
for (int k = 0; k < N; ++k)
{
cout << v[k] << " ";
}
cout << endl;
}
(3)注释说明
具体的实现只需要看 void Quick::sort(int lo, int hi); int Quick::position(int lo, int hi);两个函数。
sort(int lo, int hi) 递归,position()用来找到基数的合适位置。
exch(int i, int j)函数很简单,就是交换i,j处的元素。
详细说明position()函数。
i和j的起始位置需要注意一下,因为要配个后面的 ++i和 --j 的操作
在while(1)循环中,先左移j,注意的是递减是在while条件判断里的;
在基数右侧的所有数,有3种情况,见代码注释。
这里一定要想清楚 i 和 j 可能的位置关系。