title: 快速排序和归并排序
date: 2019-05-22 22:17:49
tags: 排序
排序算法 O(nlogn)
1.快速排序——分治思想
难点在于划分 不稳定排序
线性时间复杂度
注意下标的边界问题 --> 背模板
注意:快速排序过程中,如果每次取区间起点或者终点作为分界点,则会超时。
分界点换成随机值,或者区间中点即可。
当给定的序列有序时,如果每次选择区间左端点进行划分,每次会将区间[L, R]划分成[L, L]和[L + 1, R],那么相当于每次递归右半部分的区间长度只会减少1,所以就需要递归 n−1次了,时间复杂度会达到 n^2。但每次选择区间中点或者随机值时,划分的两个子区间长度会比较均匀,那么期望只会递归 logn层。
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
const int maxn=1e5+5;
int q[maxn];
void quick_sort(int q[],int l,int r)
{
if(l>=r)//指针指向同一个数之后就停止了
return ;//只有一个数或者没有数也直接return
int x=q[l+r>>1];//随意取一个作为参照
int i=l-1,j=r+1;//我们就将指针初始化指向两侧
while(i<j)
{
do//每次循环必++ --一次,不会在之前的位置上操作
i++;
while(q[i]<x);//使得i左边的一定是小于x的
do
j--;
while(q[j]>x);//这个地方为什么不取>=呢???会段错误
//因为右边找的是<=x的数跳过 ,要保留的是>x的数 =x也不动它
if(i<j)//如果指针还没有相遇,就交换这两个数
swap(q[i],q[j]);
}
quick_sort(q,l,j);//参照的X一定不能取到q[r]
quick_sort(q,j+1,r);
//写成 quick_sort(q,l,i-1); 用q[l]会死循环
// quick_sort(q,i,r);
// eg: 1 2 (0,-1) “(0,1)”会一直递归这个
// quick_sort(q,i,r);也可 但是注意不能取到l左边界,不然会死循环 // 此时x=q[(l+r+1/2)];
}
int main()
{
//java里面用buffer_read 比scanner快10~20倍
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&q[i]);
quick_sort(q,0,n-1);
for(int i=0;i<n;i++)
printf("%d ",q[i]);
return 0;
}
6
3 2 1 1 4 7
0 3
1 2
0 1
1 1 2 3 4 7
会出现在左区间只有 1 1 的时候的交换
Java的快速读入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
n = Integer.parseInt(br.readLine()) ;
String [] v = br.readLine().split(" ");
2.归并排序
难点在于归并,是稳定排序
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#define ll long long int
const int maxn=1e6+5;
const int mod=10000;
using namespace std;
int q[maxn],temp[maxn];
int n;
void merge_sort(int q[],int l,int r)
{
if(l>=r)
return ;
int mid=l+r>>1;
merge_sort(q,l,mid);
merge_sort(q,mid+1,r);
int k=0;
int i=l,j=mid+1;
while(i<=mid&&j<=r)
{
if(q[i]<=q[j])
temp[k++]=q[i++];
else
temp[k++]=q[j++];
}
while(i<=mid)
temp[k++]=q[i++];
while(j<=r)
temp[k++]=q[j++];
for(i=l,j=0;i<=r;i++,j++)
q[i]=temp[j];
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&q[i]);
merge_sort(q,0,n-1);
for(int i=0;i<n;i++)
printf("%d ",q[i]);
cout<<endl;
return 0;
}