算法学习:快速排序(java实现)

快速排序(英语:Quicksort),又称分区交换排序(partition-exchange sort),简称快排,一种排序算法,最早由东尼·霍尔提出。在平均状况下,排序n个项目要O(n logn) O(nlog n)(大O符号)次比较。在最坏状况下则需O(n^2)次比较,但这种状况并不常见。事实上,快速排序O(n logn)通常明显比其他算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地达成。
-----《维基百科》

快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为较小和较大的2个子序列,然后递归地排序两个子序列。
步骤为:

  1. 挑选基准值:从数列中挑出一个元素,称为“基准”(pivot),在这篇博客中使用要排序的数列的中间位置元素作为pivot。
  2. 分割:重新排序数列,所有比基准值小的元素摆放在基准左边,所有比基准值大的元素摆在基准右边(然而与基准值相等的数可以到任何一边)。在这个分割结束之后,对基准值的排序就已经完成。只要某个元素的左边所有的元素都小于或者等于这个元素,并且该元素的右边的所有元素都大于等于该元素,那么该元素的位置就是整个数列排序后的最终位置。
  3. 递归排序子序列:递归地将小于基准值元素的子序列和大于基准值元素的子序列排序。

其中最重要的是如何实现分割,既该如何将数列里所有小于基准的元素放在其左边,而把所有大于基准的元素放在其右边。 其实就是同过数值的交换来实现,就类似冒泡排序的两两交换,但又不同的是,快速排序实现了跨越式的交换,这样就能避免一些不必要的交换,从而大大提高了执行效率。

先用 l ( l 是L的小写) 指向指向待排序数列中第一个元素,r指向待排序数列的最后一个元素,pivot要等于待排序数列的中间元素(注意:这里的pivot存储的是数值,而不是下标,原因会在代码中给出),在 l < r的条件下,如果arr[i]

整体的排序过程:

代码:

package hxz.Sort;

import java.util.Arrays;

public class QuickSort {
	public static void main(String[] args) {
		int[] arr = {4,3,6,7,5,2,1,9,8};
		QuickSort.quickSort(arr, 0, arr.length-1);
		System.out.println(Arrays.toString(arr));
	}
	
	public static void quickSort(int[] arr, int left, int right) {
		int l = left;
		int r = right;
		int pivot = arr[(left+right)/2];  //为什么pivot不能用arr[left+right]来代替?? 例子:假如在只有两个数的情况下:
		//2 1 pivot指向2,l也指向了2,r指向了1,l不移动,r向左移动一位,r==l,跳出循环,那么2 1就是排序失败的结果
		int temp;
		while(l<r) {
			while(arr[l]<pivot) {
				l++;
			}
			while(arr[r]>pivot) {
				r--;
			}
			if(l>=r) {//if(l==r)??? 代表着pivot左右两边的值都<=或者都>=pivot
				break;
			}
			temp = arr[l];
			arr[l] = arr[r];
			arr[r] = temp;
			
			/*当arr[l]==arr[pivot]或者arr[r]==arr[pivot]时,如果不对下标l或r进行l++,r--操作的话那么在后面的程序
			 * 运行过程中,l或者r将不会移动(因为他们不会再进入下面的循环:
			 * while(arr[l]<arr[pivot]) {
				l++;
			}
			while(arr[r]>arr[pivot]) {
				r--;
			}),循环将一直进行下去,例子:arr={4,3,5,8,5,6,1,5,9}
			 */
			if(arr[l]==pivot) { 
				r--;//注意是r--,因为l和r交换值之后,r指向的就是l原先指向的值
			}
			if(arr[r]==pivot) {
				l++;
			}
		}
		//while循环结束,代表着pivot左右两边的值都<=或者都>=pivot
		//System.out.println(Arrays.toString(arr)); 打印每一次数列排序后的结果
		
		if(l==r) {
			l++; r--;
		}
		
		if(left<r) {
			quickSort(arr, left, r);
		}
		if(l<right) {
			quickSort(arr, l, right);
		}
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值