快速排序 java简单实现

快速排序思想

分而治之的思想,在需要排序的数值中 选取一个主元,然后其他数值与这个主元进行对比,比主元小的放主元的左边,比主元大的放主元右边。之后对主元俩边的子集进行递归处理。这样每一次的主元都是到这个序列中正确的位置。不像简单排序一样,都是临时位置。

主元的选择

选取合适的主元可以提高效率。一般我们是选取序列中最左,中间,最右 三个位置的数值进行比较,选取大小中间的那个。然后最小放最左边,最大放最右边。
当每一次选取的主元刚好是中间的数值,算法效率最快,时间复杂度达到O(NLogN)

选好主元后,将主元放到最右边。这样子集就是Left到right-1的部分。

思路

选取主元后放在子集的最后,
选取俩个指针i,j
i指向子集最左边位置,j指向子集最右边位置。
i位置的数值与主元比较,小于主元时i++,不然就停下来
j位置的数值与主元比较,大于主元时j- -,不然停下来
都停下来时,i与j互换,一直到 i>j时,表示已经走完了,然后将i 与 主元 互换。主元就到达序列的正确位置。
会出现这样一种情况,当i,j都指向同一个数值时,根据这个数值与主元比较会让i或j再走一步,这样i与主元互换就正确了。

程序


package quicksort;

public class Quicksort {
	public int pivot(int a[], int left, int right) {
		int center = (left + right) / 2;
		if (a[left] > a[center])
			swap(a, left, center);
		if (a[left] > a[right])
			swap(a, left, right);
		if (a[center] > a[right])
			swap(a, center, right);
		// 头,中,尾取中位数,并且排好序
		swap(a, center, right ); // 将主元放到最右边的位置
		return a[right];
	}

	// 互换方法
	public void swap(int a[], int i,int j) {
		int b;int c;
		b = a[i];
	    c = a[j];
	    a[i] = c;
	    a[j] = b;
	}

	public void quicksort(int a[], int left, int right) {
        if(left >= right)
        	return;
        
		int temp = pivot(a, left, right);
		int i = left ;
		int j = right-1;
		while(i < j){
			while ( a[i] < temp && i <= j) { // 左边位置,当大于等于主元时,停下来准备做交换
				i++;
			}
			while (a[j] > temp  && i <= j) { // 右边位置,小于等于主元时,停下来准备做交换
				j--;
			}
			if (i < j) {
				swap(a, i, j);
			   
			} else 			
				break;
			
		}
			swap(a, i, right);// 找到正确位置,与主元互换

			quicksort(a, left, i - 1);// 进行递归
			quicksort(a, i + 1, right);
		}
	

	public void QuickSort(int a[]) {
		int left = 0;
		int right = a.length - 1;
		quicksort(a, left, right);
	}

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		int a[] = {6,8,7,5,4,9,12,8,7,1,5 };
		Quicksort test = new Quicksort();
		test.QuickSort(a);
		for (int i : a) {
			System.out.print(i + " ");
		}
	}
}

思考

当子集划分小到一定程度时,用简单的插入排序会更快,因为快速排序主要是递归,可以设定一个阈值,当子集小于一个数时,可以使用插入排序,结束递归。
当遇到数值与主元相等的时候,要不要交换呢?
如果交换的话,考虑极端情况,序列中数大都相等。这样会做很多无谓的交换,但是最后i和j会停在了序列中间位置,这样子集划分会平均一半,这样为递归减小了时间复杂度。平均时间复杂度为NLogN。

不交换的话,上述的情况,这样i直接到了右端,子集划分不平衡,递归时间复杂度大,最坏情况 N²。

所以还是交换好,这样快速排序 是不稳定的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值