快速排序

#include <cstdio>

const int MAXN = 1010;
int a[MAXN] = {10,9,8,7,6,5,4,3,2,1};
void swap(int i, int j) {
	int temp = a[i];
	a[i] = a[j];
	a[j] = temp;	
} 

// 选基准的方式,取头中尾三个元素的中位数。并操作数组
int median3(int a[], int left, int right) {
	int center = (left + right) / 2;
	if(a[left] > a[center]) swap(left, center);
	if(a[left] > a[right]) swap(left, right);
	if(a[center] > a[right]) swap(center, right);  
	swap(center, right - 1);
	return a[right - 1];
}
void quickSort(int a[], int left, int right) {
	if(left < right) { 
		int pivot = median3(a, left, right);
		int i = left, j = right - 1;
		while(1) {
			while(a[++i] < pivot) {}
			while(a[--j] > pivot) {}
			if(i < j) swap(i, j);
			else break;  
		}
		swap(i, right - 1);
		quickSort(a, left, i - 1);  //主元的位置已经定了
		quickSort(a, i + 1, right);
	} 
}
int main() {
    int len = 10;
	quickSort(a, 0, len - 1);
	for(int i=0; i<10; i++)
		printf("%d ",a[i]);
	return 0;
}

(转自:https://blog.csdn.net/wthfeng/article/details/78037228) 

过程

在数组中选一个基准数(通常为数组第一个)。将数组中小于基准数的数据移到基准数左边,大于基准数的移到右边。对于基准数左、右两边的数组,不断重复以上两个过程,直到每个子集只有一个元素,即为全部有序。

交换的过程

在数组的头部和尾部分别设置一个哨兵,同时向对方走去。尾部的哨兵如发现有比基准数小的数,停下。头部的哨兵如发现有比基准数大的数,停下。交换两个数。再重新走重复前面的交换过程。直到两个哨兵相遇,交换基准数和尾哨兵

有一数组为6 1 2 7 9 3 4 5 10 8,演示

6为基准数,设i,j为两哨兵,目前指向首尾两个数。
6 1 2 7 9 3 4 5 10 8

两哨兵分别走向对方,直到遇到交换条件,并做交换。
6 1 2 7 9 3 4 5 10 8
6 1 2 5 9 3 4 7 10 8

此时来观察交换后的队列,除去基准数,是不是哨兵走过的位置都已部分有序了呢? 左边1 2 5都比基准数小,右边7 10 8都比基准数大。
1 2 5 9 3 4 7 10 8

继续走直到相遇,基准数复位
6 1 2 5 9 3 4 7 10 8
6 1 2 5 4 3 9 7 10 8
6 1 2 5 4 3 9 7 10 8
3 1 2 5 4 6 9 7 10 8

这样就完美地将一个数组以一个基准数为中心分为两个子集。然后重复这个过程即可实现快速排序。

有一点需特别注意:若以第一个元素为基准数(就如上面的示例),在哨兵互走过程需右边的哨兵先走。 原因很好理解,看上面过程解析就会明白:哨兵互走交换的过程就是不断排序的过程。若右边的哨兵先走,不管走多少次,最后相遇时的那个数是小于基准数的。这时与基准数交换,正好分为两个序列。可若是左边的先走,相遇在大于基准数上就不好办了。

以第一个元素作为基准,Java实现:

   public void quickSort(int[] arr, int low, int high) {
        // low,high 为每次处理数组时的首、尾元素索引

        //当low==high是表示该序列只有一个元素,不必排序了
        if (low >= high) {
            return;
        }
        // 选出哨兵元素和基准元素。这里左边的哨兵元素也是基准元素
        int i = low, j = high, base = arr[low];
        while (i < j) {
            //右边哨兵从后向前找
            while (arr[j] >= base && i < j) {
                j--;
            }
            //左边哨兵从前向后找
            while (arr[i] <= base && i < j) {
                i++;
            }
            swap(arr,i,j);  //交换元素
        }
        swap(arr,low,j);  //基准元素与右哨兵交换
        
        //递归调用,排序左子集合和右子集合
        quickSort(arr,low,j-1);  
        quickSort(arr,j+1,high);

    }

    private void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值