快速排序 + 前k小数


先介绍快速排序:


找到一个中间的数字9;

现在做的就是使左边所有的数字不大于9,右边所有的数字都不小于9

 

1.   那么在左边找到第一个比9大的数字,把他取出来并放到托管所1里面(意味着取数的地方留下了一个坑,这样比较形象),然后在右边找到第一个比9小的数字,把他放到托管所2里面(意味着取数的地方留下了一个坑);

2.   将托管所里面的两个数字交换,这样就达到了左边的那个坑的数字比9(标准)小,右边那个坑的数字比9大;(如果这里记录一下左边一定比9小的数的最长位置,右边一定比9大的数的最长位置,就会降低时间复杂度,但是这里不记录就是为了直观)





下图中可以看到左边(从左往右看)两个数比9不大,右边(从右往左看)两个数比9不小,(右边明明有三个数56  45 78比9大,但是78我们根本就不知道是否比9大,因为前面找的时候找到倒数第二个位置的时候就中止了)



现在就要做的就是接着在左边找到第一个比9大的数取出来形成一个坑并放到托管所1,然后在右边(从右往左)找到第一个比9小的数取出来放到托管所2,然后同上一样交换






接着重复上面,现在发现左边找到了32而右边却没有比9小的数字了,怎么办呢?

办法就是如果左边或右边没有找到合适的数字,那么就将9(标准数)作为没找到那一边的托管所里面,见下图:




交换后




就这样,左边所有的数字都比32小(现在是32作为中间数),右边所有的数都比32大


然后递归32的左边和右边,这个就不说了


排序源代码

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int M =  100;

void qSort(int a[], int left,int right, int kkkk)
{
	if(left >= right)
		return ;
	int i = left, j = right;
	int x = a[left];    //这个地方为了方便没有放中间那个数, 而是放的第一个, 效果一样的
	while(i < j)        //i < j是由于当i == J的时候就是同一个数了, 就死循环了, 下面一样会有其中一个是死循环 (<= 就会是一个死循环)
	{
		while(i < j && a[j] > x)   //从右到左找到一个比不大的数
			j--;
		if(i < j)                  
		{
			a[i] = a[j];
			i++;
		}
		while(i < j && a[i] <= x)  //从左到右找到一个大的数

			i++;
		if(i < j)
		{
			a[j] = a[i];
			j--;
		}
	}
	a[i] = x;              //这个很重要的,此时i == j,  现在的a[i]是那个最后没有被填上的那个坑, 所以需要把x放进坑里面
	if(i == kkkk - 1)      //如果是前k个数就输出, 这个地方可以return了, 没有return就是完整版的快速排序
	{
		puts("前k小的数:");
		for(int k = 0; k <= i; k++)
			printf("%d ", a[k]);
		puts("");
		return;
	}
	qSort(a, left, i - 1, kkkk);
	qSort(a, i + 1, right, kkkk);
}

int main()
{
	int a[100];
	puts("排序前的数:");
	for(int i = 0; i < 11; i++)
	{
		a[i] = rand() % 850;
		printf("%d ", a[i]);
	}
	puts("");
	qSort(a, 0, 10, 5);
	puts("排序后的数:");
	for(int i = 0; i < 11; i++)
	{
		printf("%d ", a[i]);
	}
	puts("");
	return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值