C++排列

一.排列方法:

说到排序,c++首选sort(),其平均复杂度为O(nlogn),但它不是很稳定的排序方法,而且许多题并不能运用sort()来解决。除了sort()以外,我们常用的还有快速排列和归并排列。

二.快速排列:

1.实现:

例如:有一个序列长度为8的序列a[7]={4,8,5,7,1,3,6,2}。

排列步骤:

1.先处理:选中一个元素放到x这个位置,将比a[x]小的元素全部放到左边,不比a[x]小的元素全部放在右侧。

2.分解问题:

3.问题合并:

当子问题无法分解,也就是只剩一个点的时候,处理结束。因为每个子问题有序,所以原问题也必定有序。

说明:若选中基准数字4,将序列分成两段,在实现过程中先指定一个指针p=1,在寻找比4小的数,如果找到,则指针右移动,且把数字放到当前位置。完成后,交换指针与l的位置即可。

2.代码呈现

一般我们会将快速排列写成函数形式

void qspx(int x,int y){
	if(x>y) return;
	int l=a[x],r=x;
	for(int i=x;i<=y;i++){
		if(a[i]>l) swap(a[++r],a[i]);
	}
	swap(a[x],a[r]);
	qspx(x,r-1);
	qspx(r+1,y);
}

例题:

给定一个数组,统计前k大的数并且把这k个数从大到小输出。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+3;
int a[N];//根据题目给定的范围来定
void qspx(int x,int y){//快速排序函数
	if(x>y) return;
	int l=a[x],r=x;
	for(int i=x;i<=y;i++){
		if(a[i]>l) swap(a[++r],a[i]);
	}
	swap(a[x],a[r]);
	qspx(x,r-1);
	qspx(r+1,y);
}
int main(){
	int n;cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	qspx(1,n);//从1到n进行排列
	int k;cin>>k;
	for(int i=1;i<=k;i++){
		cout<<a[i]<<endl;
	}
	return 0;
}

三.归并排列:

归并排序是建立在归并操作上的一种有效,稳定的排列算法,该算法是采用的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

例如:有一个序列长度为8的序列a[7]={4,8,5,7,1,3,6,2}

将序列平均分成两段。int mid=(l+r)/2

假如我们用归并排列来做一下上面那道题。

代码:

#include<bits/stdc++.h>
using namesapce std;
const int N=1e5+5;
int a[N],b[N];
void mergesort(int l,int r){//归并排列函数
    if(l>=r) return;
    int mid=(l+r)/2;
    mergesort(l,mid);
    mergesort(mid+1,r);
    //递归到子问题得出答案进行合并两个子问题
    int i=l,j=mid+1,k=l;
    while(i<=mid&&j<=r){
        if(a[i]>a[j]) b[k++]=a[i++];
        else b[k++]=a[j++];
    }
    while(i<=mid) b[k++]=a[i++];//子问题1没有处理完的直接放到序列后面
    while(j<=r) b[k++]=a[j++];//子问题1没有处理完的直接放到序列后面
    for(int i=l;i<=r;i++) a[i]=b[i]; //更新原序列
}
int main(){
    int n;cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    mergesort(1,n);
    int k;cin>>k;
    for(int i=1;i<=k;i++) cout<<a[i]<<endl;
    return 0;
}

归并排列的优点是比快速排列更稳定,且比暴力枚举时间复杂度更低,所以我们大多数时候都会用归并排列来做。

感谢各位大佬的阅读!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值