填坑法
在网上随便搜一下就可以知道填坑法得思想,下面仅对代码进行分析
void quickSort(int left, int right, int* p)
{//从小到大排序
if (left < right)
{
int i = left, j = right;
int temp = p[i];//以序列得第一个数作为了基准数
//temp为第一个坑位
//1. 第一种写法
while (i < j)
{
while (i < j && p[i] <= temp) i++;
p[j] = p[i];//将右边待填的坑位用左边满足的数填上
while (i < j && p[j] >= temp) j--;//当右边找到比基数小的数时,或者没找到时,退出循环
p[i] = p[j];//将左边待填的坑位用右边满足的数填上
}
//2. 第二种写法
//while (i < j)
//{
// while (i < j && p[j] >= temp) j--;//当右边找到比基数小的数时,或者没找到时,退出循环
// if (i < j) p[i++] = p[j];//将左边待填的坑位用右边满足的数填上
// while (i < j && p[i] <= temp) i++;
// if (i < j) p[j--] = p[i];//将右边待填的坑位用左边满足的数填上
//}
//差别分析:第一种带等号 可以跳过自身
//第二种不带等号 需要将相应的标志加减
//错误的就是既不带等号也不将标志加减 这样遇到重复值就会死循环例如[1,1]
//退出循环 i==j
p[i] = temp;//将基准数填到最后的坑位实现了左边都比基准数小 右边都比基准数大
quickSort(left, i - 1, p);
quickSort(i + 1, right, p);
}
}
int main()
{
int p[] = { 8,1,4,9,0,3,5,2,7,6 };
quickSort(0, 9, p);
for (int i = 0; i < 10; ++i)
{
cout << p[i] << " ";
}
}
上边是以序列的第一个数为基准数,就要从左边开始找,因为这样可以保证当最后填坑时满足小于的进行交换
如果是以序列的最后一个数为基准数,将标志的查找顺序交换就好了。
这样:
//1. 第一种写法
while (i < j)
{
while (i < j && p[i] <= temp) i++;
p[j] = p[i];//将右边待填的坑位用左边满足的数填上
while (i < j && p[j] >= temp) j--;//当右边找到比基数小的数时,或者没找到时,退出循环
p[i] = p[j];//将左边待填的坑位用右边满足的数填上
}
交换法
算法思路:每次设置一个基准数,设置一个左右哨兵,进行搜寻,哨兵的位置即为数组的下标。左哨兵寻找比基准数大的数,右哨兵寻找比基准数小的数(从小到大排序)。然后交换数据,直到左右哨兵相遇,交换基准数,继续处理子序列。直到序列之中只剩一个数时。
void quickSort(int left ,int right,int *p) {//从小到大排序
//每次序列的第一个数即left做对应的数即为基准数
int i, j, t, temp;//i左哨兵,j右哨兵。
if (left > right) return;//不符合条件退出
temp = p[left];//temp中存储基准数
i = left;
j = right;
while (i != j) {//说明这趟数据处理完毕,
//必须j先走。因为如果反之,i在大于基准数的地方停下,j在小于基准数的地方停下,如果i先走,最后停下跟基准数交换时,总是大于基准数的。
while (p[j] >= temp && i < j) {//当右边找到比基数小的数时,或者没找到时,退出循环
j--;
}
while (p[i] <= temp && i < j) {//当左边找到比基数大的数时,或者没找到时,退出循环
i++;
}
if (i < j) {//说明正常退出循环,找到了符合的数,进行交换数据。
t = p[j];
p[j] = p[i];
p[i] = t;
}
}
//数据处理完毕以后,最终将基准数归位,i也可以替换为j。因为此时i==j。
p[left] = p[j];//将满足的数据换到数列的第一个位置
p[i] = temp;//将基准数换到数列中
quickSort(left, i - 1,p);//处理子左数列
quickSort(j + 1, right,p);//处理子右数列
}
int main()
{
#pragma region 快速排序
cout << "请输入数组大小" << endl;
int N; cin >> N;
int* p = new int[N + 1];
for (int i = 1; i <= N; ++i) cin >> p[i];
quickSort(1, N,p);
for (int i = 1; i <= N; ++i) {
cout << p[i] << " ";
}
delete[]p;
时间复杂度:快速排序的最差时间复杂度和冒泡排序是一样的,都是 O(N*N),它的平均时间复杂度为 O (NlogN)
同样的如果采用序列的最右边的数为第一个为基准数,交换查找顺序,要保证与基准数交换的数满足排序要求
对于基准数的选取以及其他优化方式可以参考这篇文章:点击跳转