快速排序 写法 版本 效率

快速排序   写法   版本   效率

Input:
10
72 6 57 88 60 42 83 73 48 85
Output:
6 42 48 57 60 72 73 83 85 88 

1.挖坑填数+分治法

该方法的基本思想是:

1.1.先从数列中取出一个数作为基准数。

1.2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。

1.3.再对左右区间重复第二步,直到各区间只有一个数。

针对洛谷P1177 【模板】快速排序代码如下:

#include <stdio.h>
#define maxn 100010
int a[maxn];
void qs(int left,int right){
	int val,i,j;
	val=a[left];//a[left]即a[i]就是第一个坑
	i=left,j=right;
	while(i<j){
		while(i<j&&a[j]>val)j--;//从右向左找小于等于val的数来填a[i]
		if(i<j)a[i]=a[j],i++;//将a[j]填到a[i]中,a[j]就形成了一个新的坑
		while(i<j&&a[i]<val)i++;// 从左向右找大于等于val的数来填a[j]
		if(i<j)a[j]=a[i],j--;//将a[i]填到a[j]中,a[i]就形成了一个新的坑
	}
	a[i]=val;//i==j,退出时,i等于j.将val填到这个坑中。
	if(left<i)qs(left,i-1);
	if(i<right)qs(i+1,right);
}
int main(){
	int i,n;
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d",&a[i]);
	qs(1,n);
	printf("%d",a[1]);
	for(i=2;i<=n;i++)printf(" %d",a[i]);
	printf("\n");
	return 0;
}

数据处理过程,部分如下:

位置1  2 3  4  5  6  7  8  9  10
数值72 6 57 88 60 42 83 73 48 85

处理区间[1,10],以a[1]=72为基准

i=1,j=10,j--
位置1  2(i) 3  4  5  6  7  8  9(j)  10
数值48 6    57 88 60 42 83 73 48    85

i=2,j=9,i++
位置1  2 3  4(i)  5  6  7  8(j)  9  10
数值48 6 57 88    60 42 83 73    88 85

i=4,j=8,j--
位置1  2 3  4  5(i)  6(j)  7  8  9  10
数值48 6 57 42 60    42    83 73 88 85

i=5,j=6,i++
位置1  2 3  4  5  6(i,j)  7  8  9  10
数值48 6 57 42 60 42      83 73 88 85

i=6,j=6
位置1  2 3  4  5  6(i,j)  7  8  9  10
数值48 6 57 42 60 72      83 73 88 85

1.分治区间[1,5]
位置1  2 3  4  5
数值48 6 57 42 60

处理区间[1,5],以a[1]=48为基准
i=1,j=5,j--
位置1  2(i) 3  4(j)  5  
数值42 6    57 42    60

i=2,j=4,i++
位置1  2  3(i,j)  4  5  
数值42 6  57      57 60

i=3,j=3,
位置1  2  3(i,j)  4  5  
数值42 6  48      57 60


2.分治区间[7,10]
i=7,j=10
位置7  8  9  10
数值83 73 88 85

2.针对上述代码,进行写法的改进,改进的代码,并不意味着效率的提高。

针对洛谷P1177 【模板】快速排序代码如下:

 

#include <stdio.h>
#define maxn 100010
int a[maxn];
void qs(int left,int right){
	int val,i,j,t;
	val=a[left];
	i=left,j=right;
	while(i<j){
		while(i<j&&a[j]>=val)j--;//=不能省
		while(i<j&&a[i]<=val)i++;//=不能省
		if(i<j) t=a[i],a[i]=a[j],a[j]=t;
	}
	a[left]=a[i],a[i]=val;//i==j。
	if(left<i)qs(left,i-1);
	if(i<right)qs(i+1,right);
}
int main(){
	int i,n;
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d",&a[i]);
	qs(1,n);
	printf("%d",a[1]);
	for(i=2;i<=n;i++)printf(" %d",a[i]);
	printf("\n");
	return 0;
}

3.针对上述代码,进行写法的改进,改进的代码,此时意味着效率的提高。

针对洛谷P1177 【模板】快速排序代码如下:

#include <stdio.h>
int a[100010];
void qs(int left,int right){//自小到大 
    int i=left,j=right,t;
    int mid=a[(i+j)/2];//a[left];
    while(i<=j){//结束时i>j
        while(a[i]<mid)i++;
        while(a[j]>mid)j--;
        if(i<=j)t=a[i],a[i]=a[j],a[j]=t,i++,j--;
    }
    if(left<j) qs(left,j);
    if(i<right) qs(i,right);
}
int main(){
    int i,n;
    scanf("%d",&n);
    for(i=1;i<=n;i++) scanf("%d",&a[i]);
    qs(1,n);
    printf("%d",a[1]);
    for(i=2;i<=n;i++) printf(" %d",a[i]);
    printf("\n");
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值