排序(一):快速排序

快排和归并排序一样都是分治法思想。

快速排序的主要思想:

      将序列分为左右两部分, 使得左边的数都比基准值小,右边的数都比基准值大。递归这个过程,直到不能再分。

那么如何将序列分为左右两部分,以及基准值怎么选取是快排的核心。

先看图:图片来自https://www.cnblogs.com/onepixel/p/7674659.html

快速排序的几种实现方式:

第一种, 左右交叉交换。

基准值取法为 区间i-j的任意值

先从右边找到一个比基准值小的数,然后将基准值和该数换位置

然后从左边找到一个比基准值大的数,然后将基准值和该数换位置

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
using namespace std;
int arr[1000005];
int n;
void q_sort(int i, int j){
    if(i>=j) return;  
    int x =i+rand()%(j-i+1); // 随机取一个基准值
    int piovt = arr[x];
    arr[x] = arr[i];
    int low = i;
    int high = j;
    while(low<high){
         while(low<high&&arr[high]>=piovt) --high;
              arr[low] = arr[high];  
         while(low<high&&arr[low]<=piovt) ++low;
              arr[high] = arr[low];      
    }
    arr[low] = piovt;
	q_sort(i,low-1);
	q_sort(low+1,j);		
};
int main(){
    scanf("%d",&n);
    for(int i = 0; i < n; i++){
	    scanf("%d",&arr[i]);
    }
    q_sort(0,n-1);
    for(int i = 0; i < n; i++){
	    i ? printf(" %d",arr[i]) : printf("%d",arr[i]);
    }
    return 0;
} 

第二种:

左右交换

基准值选中间值

将右边比基准值小的数和左边比基准值大的数交换。

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
using namespace std;
int arr[1000005];
int n;
void q_sort(int i, int j){ 
	if(i>=j) return;  
	int piovt = arr[(i+j)/2];
	int low = i;
	int high = j;
	while(low<=high){	
		while(arr[high]>piovt) --high;   
		while(arr[low]<piovt) ++low;       
		if(low<=high){
//			cout<<low<<"   "<<high<<endl;
			swap(arr[high],arr[low]);
			--high;
			++low;
		}    
//		for(int l = 0; l < n; l++) cout<<arr[l]<<" "; cout<<endl;		//     1 3 1 2 5    
	}
	if(i<high)q_sort(i,high);
	if(j>low)q_sort(low,j);		
};
int main(){
	scanf("%d",&n);
	for(int i = 0; i < n; i++){
		scanf("%d",&arr[i]);
	}
	q_sort(0,n-1);
	for(int i = 0; i < n; i++){
		i ? printf(" %d",arr[i]) : printf("%d",arr[i]);
	}
	return 0;
} 

当存在大量重复数据时,第二种会优于第一种

强烈推荐第二种。

发布了52 篇原创文章 · 获赞 114 · 访问量 6002

猜你喜欢

转载自blog.csdn.net/GD_ONE/article/details/102993225