数据结构与算法-快速排序

282 阅读1分钟

执行流程

  1. 从序列中选择一个轴点,可以每次选择index=0位置的元素
  2. 利用轴点元素,将序列分割成2个子序列,将小于轴点的元素放在轴点左侧,将大于轴点的元素放在轴点右侧,等于轴点的元素放哪边都可以
  3. 对子序列执行1,2操作,直到子序列只有一个元素为止

快速排序的本质:逐渐把每个元素都转换成轴点元素

1:执行流程

轴点元素的构造

接下来的一个问题是,我们怎么找到轴点元素,看图 2:轴点元素的构造

代码

public class QuickSort {
	public static void main(String[] args) {
		int[] array = {9, 5, 3, 2, 7, 6, 1};
		QuickSort quickSort = new QuickSort(array);
		quickSort.sort();
		Arrays.stream(array).forEach(System.out::println);
	}

	private int[] array;

	public QuickSort(int[] array) {
		this.array = array;
	}

	/**
	 * 排序
	 */
	public void sort() {
		sort(0, array.length);
	}

	/**
	 * 对[begin,end)范围内的元素进行排序
	 */
	private void sort(int begin, int end) {
		//子序列必须大于2个元素,才能进行排序
		if (end - begin < 2) {
			return;
		}
		//确定轴点位置
		int mid = pivotIndex(begin, end);
		//对轴点左侧子序列进行快速排序
		sort(begin, mid);
		//对轴点右侧子序列进行快速排序
		sort(mid + 1, end);
	}

	/**
	 * 确定[begin,end)之间的轴点元素位置
	 */
	private int pivotIndex(int begin, int end) {
		//默认取第一个元素为轴点元素
		//备份轴点元素
		int pivotValue = array[begin];
		//从end位置开始遍历
		end--;
		while (begin < end) {

			while (begin < end) {
				//如果end位置元素>轴点元素
				if (pivotValue < array[end]) {
					end--;
				}
				//end位置元素<=轴点元素
				else {
					array[begin] = array[end];
					begin++;
					break;
				}
			}

			while (begin < end) {
				//如果轴点元素>begin位置的元素
				if (pivotValue > array[begin]) {
					begin++;
				}
				//轴点元素<=begin位置的元素
				else {
					array[end] = array[begin];
					end--;
					break;
				}
			}
			//用轴点元素替换最后的位置
			array[begin] = pivotValue;
		}
		return begin;
	}
}

总结:快速排序平均时间复杂度O(nlogn),空间复杂度为O(logn),快速排序在左右子序列极度不平衡的情况下,时间复杂度会退变成O(n2),为了避免出现这样的情况,我们在开始选择轴点元素时可以随机选择一个元素,而不是每次都选择第一个元素.