快速排序(先归并再快排)

题目:
——给出n个数,从小到大排序,并输出
牛客例题1
牛客例题2
例题3:求第k大,并输出

啊哈一书快排思想:(分好区间后选定的哨兵位置可以确定)

二分思想:
先对大区间进行排序,并不是真正意义上的排好序:
1. 以大区间第一个数为哨兵,实现以下操作:
	a. 比它小的通通放到左边,比它大的通通放到右边
	b. 并不要求哨兵的左右各部分必须是有序的
	如何实现操作a,遍历交换即可
		c. 需要两个指针i,j,最初指向区间的最左、最右端
		   让 j 从位置 j 往左找,找到比哨兵小的数,停下。
		   接着让 i 从位置 i 往右找,找到比哨兵大的数,停下。
		   若i 此刻小于 j,交换位置上的值,目的是小的站左边,大的站右边
		   反反复复进行此操作,直至 i 与 j 碰头
		d. 此刻哨兵站在区间首位,哨兵后面的已经分好了2队,左队和右队,
			此刻只需左队最后的一个位置与哨兵交换,即可实现哨兵左边都比哨兵小,哨兵右边都比哨兵大。
2. 大区间完成后,可发现哨兵改变了位置,把大区间分为了两个小区间,接着再进行操作 1

代码:

#include<stdio.h>
int a[110000];
void swap(int i,int j)
{
	a[i]^=a[j];
	a[j]^=a[i];
	a[i]^=a[j];
}
void quickSort(int l,int r)
{
	if(l>=r)	return;
	int i=l,j=r,temp=a[l];
	while(i<j)
	{
		//两个while位置不能交换,不然试试代码下面的样例
		while(a[j]>=temp&&i<j) 
			j--;
		while(a[i]<=temp&&i<j)
			i++;
		if(i<j)
			swap(i,j);
	}
	//下面两行很关键:确定了哨兵的最后位置
	a[l]=a[i];
	a[i]=temp;
	quickSort(l,i-1);
	quickSort(i+1,r);
}
int main()
{
	int n;
	while(~scanf("%d",&n))
	{
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		quickSort(1,n);
		for(int i=1;i<=n;i++)
		{
			if(i!=1)	printf(" ");
			printf("%d",a[i]);
		}
		printf("\n");
	}
	return 0;
}
n特别大过不了,但确实就是快排思想
不超时的代码网上有,但我感觉这个比较理解,
可以确定每次哨兵的位置,不用管边界问题。

样例
5 3
2 4 1 5 3

在这里插入图片描述
在这里插入图片描述
代码:

//第k大算法
//这种不知道算不算二分思想,先这样写吧 
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N],kk;
void quickSort(int l,int r)
{
	if(l>=r)   return;
	int i=l,j=r,temp=a[l];
	while(i<j)
	{
		while(a[j]>=temp&&i<j)	j--;
		while(a[i]<=temp&&i<j)	i++;
		if(i<j)	swap(a[i],a[j]);
	}
	a[l]=a[i];
	a[i]=temp;
	if(kk<=i)
		quickSort(l,i-1);
	else
		quickSort(i+1,r);
}
int main()
{
	int n,i;
	scanf("%d %d",&n,&kk);
	for(i=1;i<=n;i++)
		scanf("%d",&a[i]);
	quickSort(1,n);
	printf("%d\n",a[kk]);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值