找到数组中第k小的值(利用快排的划分函数)

在数组中找到第K小的值,我们利用划分函数,可以做到和快排异曲同工的效果。
话不多说,先上在快排中的划分函数代码:

int Parition(vector<int>& ar, int left, int right)
{
     
	assert(!ar.empty());
	int tmp = ar[left];

	while (left < right)
	{
     
		while (left < right && ar[right] > tmp) --right;
		ar[left] = ar[right];

		while (left < right && ar[left] <= tmp) ++left;
		ar[right] = ar[left];
	}

	ar[left] = tmp;
	return left;
}

我们知道,每一次划分后,划分标准值就将数组划分为两个部分,前部分全都小于等于标准值,后半部分全都大于标准值。划分后,划分标准值与最左边值的距离x,即表示这个划分标准值是这段数据里的第x小的数,此时我们只需要将K值与每一次划分标准值的下标比较大小,即可确定第K小的值在划分后的前部分还是后部分。
在这里比较困难的是,每次划分后,都要更新K值,和需要找寻第K小的值的数据范围。这样说有些迷糊,让我们从数据中感受。
找到数组中第k小的值(利用快排的划分函数)_第1张图片
比如我们找第7小的值,即K = 7。上面俩数据,第一组是原始数据,第二组是经过第一次划分后的。此时45 ~ 56有5个数据,K = 7 > 5,所以我们后面应该在90 ~ 100范围内找,但是这时候我们应该注意,在90~100里我们找第K-5小即第2小的值,才能对应原始数据中第K即第7小的值 ,所以每次划分后,我们都需要确定下一次找寻范围,并更新K值。
利用划分函数找第K小的值的剩下递归代码:

int Select_Kmin(vector<int>& br, int left, int right, int k)
{
     
	if (left == right && k == 1) return br[left];
	if (left == right && k != 1) exit(-1);//如果一开始K值小于0或者K大于数据数量,则不存在这样的第K小的值,就会执行这个语句

	int index = Parition(br, left, right);//划分后,划分标准值的下标
	int pos = (index - left + 1);//划分后,划分标准值在这部分数据里对应的是第pos小
	if (k <= pos)
		return Select_Kmin(br, left, index, k);
	else
		return Select_Kmin(br, index + 1, right, k - pos);
}

你可能感兴趣的:(数据结构和算法,c++)