参考思路快速排序算法_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1at411T75o/?spm_id_from=333.1007.top_right_bar_window_history.content.click&vd_source=e4463ee0b281106a9dc0dec11813ce26感觉他解释得比较清晰,根据这个思路写,多写几遍应该就能记住,做个备份。
import <iostream>;
import <random>;
import <functional>;
void quickSort(int array[], int left, int right)
{
int pivot = array[left]; // 标杆值/基准值
int l_pointer = left+1, r_pointer = right; //l_pointer向右移动一位
//std::cout << "Pivot: " << pivot << std::endl;
// 将数组分为两部分;对于下面的while循环,一个循环做了两件事:针对左右两个指针,要么移动,要么交换值
// 针对每一次while循环,分三种情况:
//1、如果右指针移动了,说明右指针的值本来就大于或等于pivot;下一个if,如果左指针移动了,说明左指针的值本来就小于或等于pivot;这种情况可能会导致循环最后左指针比右指针大1,应当在循环结束后做检查
//2、如果右指针移动了,说明右指针的值本来就大于或等于pivot;下一个if,如果左指针和右指针值交换了,即让左指针的比pivot大的值去了右指针那,那么下一次while循环右指针一定会向左移动一位(避免重复检查和死循环);
//3、如果右指针和左指针交换了,即让右指针的比pivot小的值去了左指针那,那么这次循环的下一个if左指针一定会向右移动一位(避免重复检查和死循环)
while (l_pointer < r_pointer) //当左右指针重合时停止移动
{
if (array[r_pointer] >= pivot) //先移动右指针,当右指针上的值大于或等于pivot时,将右指针向左移动一位
r_pointer--;
else //当右指针的值小于pivot时,让右指针的值与左指针的值交换
std::swap(array[l_pointer], array[r_pointer]);
if (array[l_pointer] <= pivot ) //再移动左指针,当左指针上的值小于或等于pivot时,将左指针向右移动一位
l_pointer++;
else //当左指针的值大于pivot时,让左指针的值与右指针的值交换
std::swap(array[l_pointer], array[r_pointer]);
}
//一定要分析最终l_pointer和r_pointer相邻时的四种情况: !!!!
//假设pivot=6,当l-pointer和r_pointer相邻时,有四种情况需要考虑;
//1、l_pointer的值是5,r_pointer的值是7;->最终l_pointer=r_pointer+1
//2、l_pointer的值是7,r_pointer的值是5;->最终l_pointer=r_pointer
//3、l_pointer的值是5,r_pointer的值是5;->最终l_pointer=r_pointer
//4、l_pointer的值是7,r_pointer的值是7;->最终l_pointer=r_pointer+1
if (r_pointer == l_pointer-1) //针对l_pointer=r_pointer+1,把pivot值放到r_pointer的位置
std::swap(array[--l_pointer], array[left]); //同时将l_pointer移动至r_pointer处
else //针对l_pointer=r_pointer,有两种情况:两个指针的值是小于或等于pivot,还是大于pivot
{
if (array[l_pointer] <= pivot) //如果指针的值小于或等于pivot,就直接交换指针与pivot的值(因为此时指针位置前面的值都会小于pivot)
std::swap(array[l_pointer], array[left]);
else //如果指针的值大于pivot,就需要交换指针前一位与pivot的值(不然会把这个大于pivot的值放到left的位置)
{
std::swap(array[l_pointer - 1], array[left]);
l_pointer--; //把l_pointer和r_pointer移到交换点
r_pointer--;
}
}
//std::cout << "l_pointer and r_pointer: " << l_pointer << " " << r_pointer << std::endl;
//经过上面的双指针的移动,结果应该是l_pointer和r_pointer位置重合,这个位置左边的数小于或等于pivot,这个位置右边的数大于或等于pivot
//可以先把下面的递归函数注释掉,先试试上面的l_pointer和r_pointer是不是相等,以及对应的值是否等于pivot。
//下面是递归函数,递归的基线条件是pivot左右两边的数组大小为1
if (l_pointer > left+1 ) quickSort(array,left,l_pointer-1); //只有当pivot左边的数组大小大于1时才需要进一步排序
if (r_pointer < right-1) quickSort(array,r_pointer+1,right); //只有当pivot右边的数组大小大于1时才需要进一步排序
}
auto createUniformPseusoRandomNumber(int max)
{
std::random_device seeder;
std::default_random_engine generator{ seeder() };
std::uniform_int_distribution distribution{ -10,max };
return std::bind(distribution, generator);
}
int main()
{
//int numbers[]{ 3,-3,6,7,3,2,2,1,3,5,1 };
//std::cout << "Size: " << std::size(numbers) << std::endl;
//quickSort(numbers,0,std::size(numbers)-1);
//for (size_t i{ 0 }; i < std::size(numbers); ++i)
// std::cout << i << "\t" << numbers[i] << std::endl;
auto random{ createUniformPseusoRandomNumber(20) };
int numbers[]{ random(),random(),random(),random(),random(),random(),random(),random(),random(),random()};
for (size_t i{ 0 }; i < std::size(numbers); ++i)
std::cout << numbers[i] << "\t";
std::cout << std::endl;
std::cout << "Size: " << std::size(numbers) << std::endl;
quickSort(numbers,0,std::size(numbers)-1);
for (size_t i{ 0 }; i < std::size(numbers); ++i)
std::cout << i << "\t" << numbers[i] << std::endl;
return 0;
}
因为要测试quickSort,总是手动改数组有点麻烦,再写了一个createUniformPseusoRandomNumber函数用来生成整数随机数。