排序之快速排序

快速排序是一种常用的排序算法,是对冒泡排序的一种改进。C语言标准库中的函数qsort实现的就是快速排序。快速排序使用了分而治之的算法思想。通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。下面我们来看一下快速排序。

操作处理

我们先来处理一趟划分,找到第一个枢轴的最终位置。步骤如下:
第一步:

将第一个元素作为枢轴(pivot)暂存,此时low所指向的位置是空闲位置,再将49后面的元素依次与枢轴作比较。
在这里插入图片描述

第二步:

我们从后往前将元素依次与枢轴进行比较,high表示的是比枢轴元素大的元素。由于65比49大,high做减1操作,向前移动一位,指向27
在这里插入图片描述

第三步:

由于27比49小,将27移到low所指向的空闲位置处。
在这里插入图片描述

第四步:

原来27的位置就空闲出来了。接下来,我们作比较的话,就应该找大的放在现在的high所指的空闲位置。所以,我们现在就不能和high所指的元素进行比较,而是和low所指的元素进行比较。由于27小于49,则low下移,指向38.在这里插入图片描述

第五步:

由于38小于49,继续下移。
在这里插入图片描述

第六步:

由于65大于49,所以65应该移到后面去,27所在的位置是空闲的,将65移到27所在的位置。
在这里插入图片描述

第七步:

由于65大于49,high继续向前移动,high指向13。由于13小于49,移动到low所指向的空闲位置。
在这里插入图片描述
在这里插入图片描述

第八步:

由于13小于49,low向前移动,low指向97,由于97大于49,将97移动到high所指向的空闲位置。
在这里插入图片描述
在这里插入图片描述

第九步:

由于97大于49,high向前移动,指向76。76大于49,high仍然向前移动,指向97。
在这里插入图片描述
在这里插入图片描述

第十步:

此时,low和high相等时,说明我们已经把小于49的元素放到左边,大于49的元素放到右边了。而此时的这个位置就是枢轴的最终位置,我们把49放到这里。
在这里插入图片描述
一趟划分完成后,将这一组数据从枢轴49这里分成左右两块。然后我们就可以用递归的思想实现了。

代码展示

第一种:枢轴在左(Java版)
import java.util.Scanner;

public class QuickSort {

	public static void main(String[] args) {
		int[] a = new int[10];
		Scanner in = new Scanner(System.in);
		System.out.println("请输入10个元素:");
		for (int i = 0; i < 10; i++) {
			a[i] = in.nextInt();
		}
		show(a);
		System.out.println();
		sort(a, 0, a.length - 1);
		show(a);
		in.close();
	}
	public static void sort(int a[], int low, int high) {
		int i, j;
		int pivot;
		i = low;
		j = high;
		pivlot = a[i];
		if (low >= high)/// 递归结束条件
			return;
		else {
			while (i < j) {
				while (i < j && a[j] >= pivot) {///从右往左扫描,找到第一个比基准元素小的元素
					j--;
				}
				a[i] = a[j];///将a[j]元素放到空闲位置
				while (i < j && a[i] < pivot) {///从左往右扫描,找到第一个比基准元素大的元素
					i++;
				}
				a[j] = a[i];///将a[i]元素放到空闲位置
			a[i] = pivot;///基准元素归位
			sort(a, low, i - 1);///对基准元素左边的元素进行递归排序
			sort(a, i + 1, high);///对基准元素右边的元素进行递归排序
		}
	}
	public static void show(int a[]) {
		for (int i = 0; i < a.length; i++)
			System.out.print(a[i] + " ");
	}
}

下面,我们来演示枢轴在中间的情形。

在这里插入图片描述
在这里插入图片描述

第二种:枢轴在中间(Java版)
import java.util.Scanner;

public class QuickSort {
	public static void main(String[] args) {
		int[] nums = new int[10];
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入10个整数:");
		for (int i = 0; i < nums.length; i++) {
			nums[i] = sc.nextInt();
		}
		for (int t : nums) {
			System.out.print(t + " ");
		}
		System.out.println();
		sort(nums, 0, nums.length - 1);
		for (int t : nums) {
			System.out.print(t + " ");
		}
		System.out.println();
		sc.close();
	}

	public static void sort(int[] nums, int _left, int _right) {
		int left = _left, right = _right;
		int pivlot = nums[(left + right) / 2];
		while (left <= right) {
			while (nums[left] < pivlot) {
				left++;
			}
			while (pivlot < nums[right]) {
				right--;
			}
			if (left <= right) {
				int t = nums[left];
				nums[left] = nums[right];
				nums[right] = t;
				left++;
				right--;
			}
		}
		if (_left < right)
			sort(nums, _left, right);
		if (left < _right)
			sort(nums, left, _right);
	}
}

总结:

快速排序虽然很快,但是这是要考虑综合情况的。快速排序最好情况下的时间复杂度为O(nlogn),但是最坏情况下时间复杂度却为O(n^2)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值