分而治之:快数排序

分而治之:快数排序

从归并排序到快速排序:

  1. 归并排序:简化分解,侧重合并
  2. 快速排序:侧重分解,简化合并
    在这里插入图片描述

快速排序的分解:

快速排序侧重分解过程,其分解的主要方法是数组划分

数组划分:

基本思想:

  1. 任选元素x作为分界线,称为主元(pivot)
  2. 交换重排,满足x左侧元素小于右侧
    在这里插入图片描述

实现方法:

  1. 选取固定位置主元x(一般是首元素或尾元素)
  2. 维护两个部分的右端点变量i,j
  3. 考察数组元素A,只和主元比较
    若A[j] ≤ x,则交换 A[j] 和 A[i+1] ,i与j右移;
    若A[j] > x,则j右移.
    在这里插入图片描述

数组划分代码:

void splitArr(int *arr, int len){
    
    
	int i = -1;
	int x = arr[len-1];  //arr[len-1]为主元 
	int temp;
	
	for(int j=0; j<len; j++;){
    
    
		if(arr[j] <= x){
    
    
			temp = arr[i+1];
			arr[i+1] = arr[j];
			arr[j] = temp;
			i++;
		}
		else j++;
   }
   
	temp = arr[i+1];
	arr[i+1] = arr[len-1];
	arr[len-1] = temp;  //最后把arr[len-1]放到位置i+1
}

固定主元的时间复杂度:

  1. 最好情况:O(nlogn)
  2. 最坏情况:O(n2)

如此看,快速排序并不优于归并排序。反思最差情况,数组划分时选取固定位置主元,可以针对性构造最差情况;所以,如果数组划分时选取随机位置的主元,就无法构造针对性最差情况了。

随机选取主元:

在这里插入图片描述
随机化数组划分代码:

#include <cstdlib> //rand()函数的头文件
#include <ctime>	//time()函数的头文件

int rand(int l,int r){
    
    	//生成随机种子
    srand(time(NULL));
    return rand()%(r-l+1)+l;
}

void splitArr(int *arr, int len){
    
    
	int i = -1;
	int k = rand(0,len-1);	//选取随机数
	int x = arr[k];  //arr[k]为主元 
	int temp;
	
	for(int j=0; j<len; j++){
    
    
		if(arr[j] <= x){
    
    
			temp = arr[i+1];
			arr[i+1] = arr[j];
			arr[j] = temp;
			i++;
		}
		else j++;
   }
   
	temp = arr[i+1];
	arr[i+1] = arr[k];
	arr[k] = temp;  //最后把arr[k]放到位置i+1
}

算法分析图:

在这里插入图片描述

随机化快速排序代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <ctime> 

using namespace std;
const int N = 1001;
int a[N];

int rand(int l,int r)//生成随机种子
{
    
    
    srand(time(NULL));
    return rand()%(r-l+1)+l;
}

void Quick_sort(int left,int right){
    
    
    if(left >= right) return;
    
    //随机选取主元,对于原数组有序程度高的情况下,时间复杂度会退化成O(n^2) 这时采用随机化算法使得复杂度稳定在O(nlogn)
    int k = rand(left,right);
    int x = a[k];//主元 
    int i = left;
    int j = right;
    swap(a[left],a[k]);//将主元放到首位置 
     
     for(int j=left+1; j<=right; j++){
    
    
		if(a[j] <= x){
    
    
			swap(a[i+1],a[j]);
			i++;
		}
		else j++;
    }
    
    /*
    while(i!=j){
        while(a[j]>=x && i<j)
            j--;
        while(a[i]<=x && i<j) 
            i++;
        swap(a[i],a[j]);
    }*/
    
    swap(a[left],a[i]);//将主元交换到分界 
    Quick_sort(left,i-1);
    Quick_sort(i+1,right);
}

int main()
{
    
    
    int n;
    scanf("%d",&n);
    
    for(int i=0;i<n;i++)
        scanf("%d",&a[i]);
        
    Quick_sort(0,n-1);
    for(int i=0;i<n;i++)
        printf("%d ",a[i]);
        
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44524918/article/details/108940046