快速排序及其优化(java)

package quickSortOptimized;

import java.util.Arrays;

public class QuickSortDemo {
	public static void swap(int arr[], int a, int b) {//交换函数
		int tmp = arr[a];
		arr[a] = arr[b];
		arr[b] = tmp;
	}

	public static void insertSort(int arr[], int start, int end) {//为快速排序优化准备插入排序;
		for(int i=0;i<end;i++) {
			for (int j=i+1;j>0;j--) {
				if(arr[j]<arr[j-1]) {
					swap(arr,j,j-1);
				}
			}
		}
	}
	
	public static void print(int arr[]) {
		System.out.println(Arrays.toString(arr));
	}
	
	public static void quickSort(int arr[],int start,int end) {//原始版快速排序
		int low =start;
		int high=end;
		int key=arr[start];
		while(low<high) {
			while(arr[high]>key&&low<high) {//从high下标开始找到第一个比key小的下标,然后break;
				high--;
			}
			while(arr[low]<key&&low<high) {//从low下标开始找到第一个比key大的下标,然后break;
				low++;
			}
			if(low<high)swap(arr,low,high);
		}
		swap(arr,start,low);//因为是从高往低扫,所以,low=high的时候停留的下标数字一定比key小或等于key,这个时候和key交换.
		//如果2个内层while和key比较的时候没有加等于号,则不需要这个交换.
		System.out.println("low="+low+"  high="+high+"  start="+start+"  end="+end+"  key="+key);//打桩,方便调试
		print(arr);
		if(start<low)quickSort(arr, start, low-1);//从key的两头分别递归
		if(high<end)quickSort(arr, high+1,end );
	}
	
	public static void optimizedQuickSort(int arr[],int start,int end) {//优化过的快速排序
		int low;
		insertSort(arr, start, start+2);
		if(arr[start]==arr[start+1]) {
			low=start;
		}else {
			low=start+1;
		}//优化1.对前3个数字进行排序,然后取中位数作为key;用于避免每次都只能切1个数字来提高性能.
		int high=end;
		int key=arr[low];
		int pointer=low+1;
		while(pointer<high) {//优化2, 用pointer把整个数组扫一遍,小于key则和low++交换,大于key则和high--交换.如果等于则pointer++
			if(arr[pointer]>key) {
				swap(arr,low++,pointer++);
			}else if(arr[pointer]>key) {
				swap(arr,pointer,high--);
			}else {
				pointer++;
			}//这样,start到low-1切成小于key的一块,low和pointer之间则是所有和key相等的值,high到end则是大于key的一块
			//使所有等于key的一块不进入递归.
		}
		if(start+10<low) {//在数组切分至较小的时候切换到插入排序,因为在数组近似有序的情况下,插入排序远远快于快速排序
			optimizedQuickSort(arr, start, low-1);
		}else {
			insertSort(arr, start, low-1);
		}
		if(pointer+10<end) {
			optimizedQuickSort(arr, pointer, end);
		}else {
			insertSort(arr, pointer, end);
		}
		
	}
	
	
	
	public static void main(String[] args) {
		int arr[]=new int [45];
		for(int i=0;i<arr.length;i++) {//生成随机数组
			arr[i]=(int) (Math.random()*1000);						
		}
		System.out.println("原始数组:");
		print(arr);
		//insertSort(arr, 0, arr.length-1);
		//quickSort(arr, 0, arr.length-1);
		optimizedQuickSort(arr, 0, arr.length-1);
		System.out.println("排序后数组:");
		print(arr);
	}

}

写了下快速排序及其优化.前段时间本来我以为我弄懂了,结果今天重写的时候又出了好多问题....之前没有理解原版快速排序key归位的操作...只是看结果正确就没管了.....事实证明,学编程还是要多敲代码啊.....


快速排序思想是把待排序的数组切分成二分.首先选取一个key值,下标小的那份所有数都小于等于key,下标大的那部分所有数都大于等于key.

然后使用递归,继续切分,当分割到不能再分割的时候,整个数组就排序好了.....这种方法,每一次递归,都会使待排序的数字缩小..缩小,,缩小...具体为什么会比其他排序快,我数学不好....反正就他最快,睡觉


然而快速排序还有待优化空间.

第一种优化,避免了极端情况下只切割一个数字出来,使效率降低...而取3个数的中位数则是经过证明的最好的取key方法....

第二种优化,三项切分发,中间项把所有等于key的值聚集起来并且不再进入循环...在数组中有重复数字的情况下效率非常高.

第三种优化,则是在数组比较小的情况下切换到插入排序,因为数组较小的情况下再使用快速排序递归也要递归很多次....而且根据快速排序的特性,在数据切分至较小的情况下数组已经是近似有序了,而面对近似有序的数组,插入排序的速度最快.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值