快速排序递归思想 n个元素中第m小的元素

利用快速排序的思想,编写一个递归算法,求出给定的n个元素中第m个最小的元素

思路:取数组第m个元素也就是a[m-1]作为每一次循环的一个阈值,将大于a[m-1]的全部放在数组的右边,小于a[m-1]的全部放在数组的左边,如果一直这样循环下去,那么最后a[m-1]这个单元中存放的就一定是第m小的数据。
 
代码分析:至于程序中比较难理解的我觉得是:
  if(j < m-1) left = i;  //这一句的意思是,程序是想寻找第m小的数据,但是j<m-1,表示现在这个阈值比第m个最小的数还小,然而存放在数组中,比当前阈值大的数的集合中的第一个数的下标正好是i,因为i是从while(privot < a[i]) i++;这个语句中跳出来的,所以这个时候将左查找范围设置为i。
  if(i > m-1) right = j; 跟上面的理解差不多。
  
注意:其实这两个if判断来修正left和right查找范围的语句完全可以不需要,因为不修改的话每次都是从最左端查找到最右端,结果是一定能够查找出来的,只是效率方面可能就没有加上这两句好了。

PS:本文借鉴了https://blog.csdn.net/laoniu_c/article/details/38127967的思路,根据题意进行编程,代码如下:

#include <iostream>
using namespace std;

int findm_min(int *a, int n, int m, int left, int right)
{
	int piv = a[m-1];	//取阙值 
	int i = left, j = right; 
	if(i < j)
	{
		//将右端比阙值小的数和左端比阙值大的数交换位置 
		while(piv < a[j]) j--;
		while(piv > a[i]) i++;
		if(i < j)
		{
			//通过位运算交换两个数的位置
			a[i] = a[i] ^ a[j];
			a[j] = a[i] ^ a[j];
			a[i] = a[i] ^ a[j];
			i++, j--;
		}
		if(i == j && a[i] == piv)
			return piv;	//符合预想条件,返回最后结果
	}
	else return a[m-1];
	//优化算法
	if(j < m - 1) left = i;
	if(i > m - 1) right = j;
	//递归
	findm_min(a, n, m, left, right);
}

int main()
{
	int n, m;
	//输入n,m
	cout << "请输入n和m:" << endl;
	cin >> n >> m;
	//输入数组元素
	int *a = new int[n];
	cout << "请输入n个数:" << endl;
	for(int i = 0; i < n; i++) cin >> a[i];
	//计算并输出最后结果
	cout << n << "个数中第" << m << "小的数为:" << endl;
	cout << findm_min(a, n, m, 0, n - 1) << endl;
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43302818/article/details/85849113
今日推荐