快速排序

快速排序(Quick Sort)

基本思想:

任意选择一数作为个基准数,通过一趟排序将要排序的数据分割成两个独立的部分。其中一部分所有数都小于基准数,另一部分所有数都大于基准数。然后按照同样的方法对分别对两部分数据进行排序,直到最后所有数据都变得有序。

基准数可以任意选取。

假设现在有这样一个初始序列:



首先,我们选取第一个数 5 作为基准数,并在开头和结尾分安插上一个哨兵 l 和  r。



哨兵 r 先出动,一步步向左移动,如果碰到了一个数比基准数要小,那么他就停下来。此时,换哨兵 l 出动,他也一步一步向右移动,直到碰到一个数比基准数大,然后他也停下。



现在交换哨兵 l 和哨兵 r 所处位置的值。



接下来,哨兵 r 又出动,一步步左移,当他再次碰到一个小于基准数的数,他又停下来。此时,换哨兵 l 出动,他也一步一步右移,直到又碰到一个大于基准数的数,他也停下。



现在交换哨兵 l 和哨兵 r 所处位置的值。



然后,重复上面的步骤,哨兵 r 再次向左移动直到遇到一个小于基准数的数。这时候,哨兵 r 已经与哨兵 l 碰头,将基准数和碰头位置的数交换后,第一趟排序就结束了。



与基准数交换交换,将基准数归位。此时基准数 5 左边的部分都比它小,右边的部分都比它大。


于是,第一趟排序就结束了。


现在,我们分别对左右两部分进行排序。

左边部分为2、3、1,以基准数 2 进行排序,排序完成后结果为 1、2、3。此时, 基准数 2 左边部分为 1,右边部分为 3,左右两边都只有一个数,不用排序。

右边部分为 7、9、6、9、8、10,以基准数 7 进行排序,排序结束后结果为 6、7、9、9、8、10。此时,基准数 7 左边只有一个数,不用排序。基准数 7 右边用同样的方法,最终排序结束后为 8、9、9、10。

这时候,原始序列已经变成了 1、2、3、5、6、7、8、9、9、10。到此,排序完全结束。

话不多说,上代码。

算法实现:

/**
	 * 进行快速排序,[left, right]为将要进行排序的区间,经排序后此区间才有序
	 * @param arr 待排序数组
 	 * @param left 数组起始下标
	 * @param right 数组结束下标
	 */
	public static void quickSort(int[] arr, int left, int right) {
		if (left >= right) // 如果起始下标 >= 结束下标,直接返回
			return;
		
		int l = left;
		int r = right;
		int base = arr[left]; // 基准数
		
		while (l < r) {
			while (l < r && arr[r] >= base) // 从右往左遍历,直到找到一个比基准数小的数,得到其下标
				r--;
			
			while (l < r && arr[l] <= base) // 从左往右遍历,直到找到一个比基准数大的数,得到其下标
				l++;
			
			if (l < r) 
				swap(arr, l, r); // 交换两个数在数组中的位置
		}
		arr[left] = arr[l];
		arr[l] = base; // 基准数放置在正确的位置,即最终 l 和 r 相遇的位置
		
		quickSort(arr, left, l - 1); // 继续处理左边的
		quickSort(arr, l + 1, right); // 继续处理右边的
	}
	
	/**
	 * 交换数组中的两个元素
	 * @param arr 数组
	 * @param i 元素下标
	 * @param j 另一个元素下标
	 */
	public static void swap(int[] arr, int i, int j) {
		int temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}


算法测试:

package algorithms;

import java.util.Random;

/**
 * 快速排序
 * @author Wll
 *
 */
public class QuickSortTest {
	public static void main(String[] args) {
		int[] arr = getRandomArray(130, 10000);
		System.out.println("======快速排序======");
		System.out.println("原始数组:");
		printArray(arr);
		long start = System.currentTimeMillis();
		quickSort(arr, 0, arr.length - 1);
		long end = System.currentTimeMillis();
		System.out.println("耗时 " + (end - start)+ " 毫秒");
	}

	/**
	 * 进行快速排序,[left, right]为将要进行排序的区间,经排序后只有此区间才是有序的
	 * @param arr 待排序数组
 	 * @param left 数组起始下标
	 * @param right 数组结束下标
	 */
	private static void quickSort(int[] arr, int left, int right) {
		if (left >= right) // 如果起始下标 >= 结束下标,直接返回
			return;
		
		int l = left;
		int r = right;
		int base = arr[left]; // 基准数
		
		while (l < r) {
			while (l < r && arr[r] >= base) // 从右往左遍历,直到找到一个比基准数小的数,得到其下标
				r--;
			
			while (l < r && arr[l] <= base) // 从左往右遍历,直到找到一个比基准数大的数,得到其下标
				l++;
			
			if (l < r) 
				swap(arr, l, r); // 交换两个数在数组中的位置
		}
		arr[left] = arr[l];
		arr[l] = base; // 基准数放置在正确的位置,即最终 l 和 r 相遇的位置
		
		quickSort(arr, left, l - 1); // 继续处理左边的
		quickSort(arr, l + 1, right); // 继续处理右边的
	}
	
	/**
	 * 交换数组中的两个元素
	 * @param arr 数组
	 * @param i 元素下标
	 * @param j 另一个元素下标
	 */
	private static void swap(int[] arr, int i, int j) {
		int temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}
	
	/**
	 * 获得一个随机整型数组
	 * @param size 数组大小
	 * @param limit 数组元素大小的上限
	 * @return 一个随机数组
	 */
	private static int[] getRandomArray(int size, int limit) {
		int[] arr = new int[size];
		Random random = new Random();
		for (int i = 0; i < size; i++)
			arr[i] = random.nextInt(limit);
		
		return arr;
	}
	
	/**
	 * 打印数组,默认只打印前一百个
	 * @param arr 待打印数组
	 */
	private static void printArray(int[] arr) {
		int length = arr.length;
		int count = 1;
		for (int i = 0; i < length; i++) {
			System.out.printf("%-10d", arr[i]);
			if (count++ % 10 == 0)
				System.out.println();
			if (count == 101 && count < length) {
				System.out.print("......");
				break;
			}
		}
		System.out.println("\n");
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值