快速排序和归并排序

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值