算法之快速排序

基本思想

1)分解(divide):对于数组 a [p : r],以a[ p ]为基准将其分解为三段 a[ p ]的a[p : q-1],a[ q ] ,a[q+1 : r],前者都比a[q]小,后者都比a[q]大。
(2)递归求解(conquer)
递归调用快速排序算法,分别对a[p : q-1]和a[q+1 : r]进行排序。
(3)合并(merge)
排序时并没有分解所以不用合并。


核心算法如下

1、QuickSort:

private static void QuickSort( int p, int r) {
		if(p<r) {
			int q = partition(p,r);//分区
			QuickSort(p,q-1);//递归调用对前半部分排序
			QuickSort(q+1,r);//递归调用对后半部分排序
		}
	}

2、partition: 以下俩个方法类似,下图为第一个方法的配图

在这里插入图片描述

private static int partition(int p, int r) {
	int x  = a[p];
	int i=p,j;
	for(j=p+1;j<=q;j++){
		if(a[j]<=x){
			i++;
			swap(a,i,j);
		}
	}
	swap(a,p,i);
	return i;
}
	private static int partition(int p, int r) {
		int i=p,j=r+1;
		int x = a[p];//以待排序的第一个数作为基准
		while(true) {
			while(a[++i]<x&&i<r);//有数大于x则停止
			while(a[--j]>x);//有数小于x则停止
			if(i>=j)//i>=j排序结束
				break;
			swap(i,j);//交换i,j位置数组的值
		}
		a[p] = a[j];//循环结束后,将第一个(作为基准的数)与a[i] 交换位置
		a[j] = x;
		return j;
	}

改进

该算法在不同情况时间复杂度为:
√ 最好情况:O(n*n)
√ 最坏情况:O(nlogn)
√ 一般情况:O(nlogn)
辅助空间:O(nlogn)
稳定性:不稳定

1、最坏情况

  • 如果数组已经有序,每次只能将数组划分为1n-1两段,此时,快速排序退化为冒泡排序。

  • T(n) = T(1) + T(n-1) +O(n)
    T(n) = T(1) + T(1) + T(n-2) + O(n-1) + O(n)
    T(n) = T(1) + T(1) + T(1)+ T(n-3) +T(n-2) + O(n-1) + O(n)
    T(n) = O(n) + O(n*n)
    T(n) = O(n*n)

2、最好情况

  • T(n) = 2*T(n/2) +O(n) 由主定理可知
    T(n) = O(nlongn)

3、一般情况

假设规模为N的问题分为一个规模为9/10N的问题和规模为1/10N的问题,即T(n) = T(9n/10) + T(n/10) + Θ(n),用递归树分析可得 T(n) = O(nlongn)
数学证明老师讲了,忘了 qwq

4、主定理

在这里插入图片描述f(n) = c*n(c为常数)
a<bT(n) = O(n)
a=bT(n) = O(nlogn)
a>bT(n) = O(n的logba次方)
在这里插入图片描述f(n) = c
a=1T(n) = O(n)
a!=1T(n) = O(n的logba次方)

5、Random改变基准数

改QuickSort:

	private static void QuickSort( int p, int r) {
		if(p<r) {
			Random ran = new Random();
			int k =ran.nextInt(100);
			swap(p,(p+1+k%(r-p)));
			int q = partition(p,r);//
			QuickSort(p,q-1);
			QuickSort(q+1,r);
		}
	}

汇总

import java.util.Random;
import java.util.Scanner;

public class Oj1_QuickSort {
	static int[] a;
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()) {
			int n = sc.nextInt();
			a = new int[n];
			for(int i=0;i<n;i++) {
				a[i] = sc.nextInt();
			}
			QuickSort(0,n-1);//分区
			
			for(int i=0;i<n;i++) {
				System.out.print(a[i]+" ");
				//a[i] = sc.nextInt();
			}
			System.out.println();
		}
	}

	private static void QuickSort( int p, int r) {
		if(p<r) {
			Random ran = new Random();
			int k =ran.nextInt(100);
			swap(p,(p+1+k%(r-p)));
			int q = partition(p,r);//
			QuickSort(p,q-1);
			QuickSort(q+1,r);
		}
	}

	private static int partition(int p, int r) {
		int i=p,j=r+1;
		int x = a[p];
		while(true) {
			while(a[++i]<a[p]&&i<r);
			while(a[--j]>a[p]);
			if(i>=j)
				break;
			swap(i,j);
		}
		a[p] = a[j];
		a[j] = x;
		return j;
	}

	private static void swap(int i, int j) {
		int z = a[i];
		a[i] = a[j];
		a[j] = z;
	}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值