C++快速排序和一些细节思考

一、原理

       选一个基准数,通常选需要排序数组的第一个元素,将该基准数从两端开始比较,找到从左边起比此基数大的数,从右边起比此基数小的数,然后交换两数,两端相遇后一轮截止,相遇的位置就是基准数的正确位置,且基准数左边都小于此基准数,右边都大于此基准数。所以,一次排序过后,能找到第一个元素的正确位置,且把数组分为左右两个部分。然后采用递归的思想,左右两边重复调用第一次排序的函数,不断分割数组,直至所需要排序的数组长度为0。

 用一幅图简单表示一轮排序:

 ①选取左端第一个数为基准数

 ②从数组左右两端开始与基准数比较

 ③找到左端比基准数大的数,右端比基准数小的数

 ④交换i,j位置对应的两数

 ⑤交换完后继续往中间靠,可见元素9,4也需要交换位置

 ⑦最后i,j在中间相遇,相遇位置即基准数6的正确位置,将该基准数与i,j相遇所在位置交换

二、C++代码实现

#include<iostream>
#include<string>
using namespace std;

void quick_sort(int* arr, int begin, int end) {
	if (begin >= end) {
		return;
	}
	int temp = arr[begin];
	int i = begin;
	int j = end;
	while (i != j) {
		while (arr[j] >= temp && i<j) {
			j--;
		}
		while (arr[i] <= temp && i<j){
			i++;
		}
		int t = arr[i];
		arr[i] = arr[j];
		arr[j] = t;
	}

	arr[begin] = arr[i];
	arr[i] = temp;
	quick_sort(arr, begin, i - 1);
	quick_sort(arr, i + 1, end);

}


void main() {
	int arr[10] = { 7,5,3,4,1,2,10,8,6,9 };
	quick_sort(arr, 0, 9);
	cout << "quick_sort:" ;
	for (auto i : arr) {
		cout << i << " ";
	}
}

该代码首先定义快速排序函数,无返回值,需传入数组指针,排序的起始位置和结束位置。

函数内定义一个temp保存基准数,i,j表示从两端开始移动,只要i,j不相等就通过++或--逐渐靠拢,直至相遇,中间需要将左端比基准数大的数与右端比基准数小的数交换。

相遇后再将相遇位置与基准数交换。

以i或j为界分为左右两部分,利用递归分别再进行排序,quick_sort(arr, begin, i - 1)负责对左边部分排序,quick_sort(arr, i + 1, end)负责对右边部分排序。

三、思考

      在自己写代码的时候有一个疑问,为什么递归的终止条件可以是begin>end,>=,而不是==?

        按道理来说,左端排序开始位置是0,结束位置通过i-1不断减小,两个相等的时候表示长度为一了,终止就行,右端也是一样,一个循序渐进的过程不就是从大于到等于再到小于吗?等于的时候就该终止了。

        实际上,终止是在下一次递归实现的。考虑最后一次排序,就是当找到的i,j与begin相等时,后面就不用排了,所以在后面递归的quick_sort(arr, begin, i - 1)应该终止,而此时begin已经与i相等了,所以终止条件应该是begin == end+1,也就是begin>end。写begin == end+1也能通过测试。

猜你喜欢

转载自blog.csdn.net/qq_43575504/article/details/130358029