一、概述
在c++语言中,有许多的排序方法值得我们学习,虽然有sort函数可以排序,但是在某种情况下,我们用sort函数会超时,所以就要用快速排序算法或者二分排序。本博文会给大家介绍几种排序方法。
以下给大家推荐一道题,这道题不能用sort进行排序,所以要用快速排序算法或者二分排序。
输出前k大的数
总时间限制: 10000ms 单个测试点时间限制: 1000ms 内存限制: 65536kB
描述
给定一个数组,统计前k大的数并且把这k个数从大到小输出。
输入
第一行包含一个整数n,表示数组的大小。n < 100000。
第二行包含n个整数,表示数组的元素,整数之间以一个空格分开。每个整数的绝对值不超过100000000。
第三行包含一个整数k。k < n。
输出
从大到小输出前k大的数,每个数一行。
样例输入
10
4 5 6 9 8 7 1 2 3 0
5
样例输出
9
8
7
6
5
二、排序
1.快速排序算法
基本思想
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
函数代码
void qsort(int l,int r){
int mid,i=l,j=r;
mid=a[(l+r)/2];
do{
while(a[i]<mid) i++;
while(a[j]>mid) j--;
if(i<=j){
int t=a[i];
a[i]=a[j];
a[j]=t;
i++;
j--;
}
}while(i<=j);
if(l<j) qsort(l,j);
if(r>i) qsort(i,r);
}
详细点击快速排序算法(百度百科)
2.二分排序
基本思想
二分排序是指利用二叉树这种数据结构所设计的一种排序算法,可以利用数组的特点快速定位指定索引的元素。
算法步骤
- 初始化操作:将数组指针指向第一个叶子结点。
- 再将该记录与其上层结点和兄弟结点比较。
- 每比较一次,数组指针加一,重复2步骤直至最后一个结点。
- 数组指针指向上一层最左边结点。
- 重复2,3,4步骤直至根结点。
- 以上5步骤重复操作log2n次。
函数代码
void msort(int s,int t){
int m,i,j,k;
if(s==t)
return;
m=(s+t)/2;
msort(s,m);
msort(m+1,t);
i=s;
j=m+1;
k=s;
while(i<=m&&j<=t){
if(a[i]<=a[j]){
r[k]=a[i];
k++;
i++;
}
else{
r[k]=a[j];
k++;
j++;
}
}
while(i<=m){
r[k]=a[i];
k++;
i++;
}
while(j<=t){
r[k]=a[j];
k++;
j++;
}
for(i=s;i<=t;i++)
a[i]=r[i];
}
详细点击二分排序(百度百科)
3.桶排序
基本思想
桶排序也叫所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n))。但桶排序并不是比较排序,他不受到O(n log n) 下限的影响。其实就是一个萝卜一个坑,此处不具体演示。
详细点击桶排序(百度百科)
4.堆排序
基本思想
堆排序是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。
函数代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int len;
int heap[105];
void put(int k){
heap[len++]=k;
//push_heap(heap,heap+len);//大根堆
push_heap(heap,heap+len,greater<int>());//小根堆
}
int get(){//排序
pop_heap(heap,heap+len,greater<int>());
return heap[--len];
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++){
int tmp;
cin>>tmp;
put(tmp);
}
for(int i=0;i<n;i++)
cout<<get()<<" ";
cout<<endl;
}
详细点击堆排序(百度百科)
5.二叉排序树
定义
二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:
1. 若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值;
2. 若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;
3. 左、右子树也分别为二叉排序树;
函数代码
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int heap[100005],n,len;
void push(int k){
heap[++len]=k;
int a=len,b;
while(a>=1){
b=a/2;
if(heap[a]>=heap[b]) break;
swap(heap[a],heap[b]);
a=b;
}
}
int get(){
int a,b,ans;
ans=heap[1];
heap[1]=heap[len--];
a=1;
while(a*2<=len){
b=a*2;
if(b<=len&&heap[b+1]<heap[b]) b++;
if(heap[a]<=heap[b]) break;
swap(heap[a],heap[b]);
a=b;
}
return ans;
}
int main()
{
int x;
cin>>n;
for(int i=1;i<=n;i++){cin>>x;push(x);}
cout<<get();
for(int i=2;i<=n;i++)
cout<<" "<<get();
}
详细点击二叉排序树(百度百科)