面试_快排(递归、非递归实现)+三数取中优化

package com.basic.order;

import java.util.Arrays;
import java.util.Stack;

//最好、平均是o(nlgn)、最坏都是o(n^2),不稳定
public class QuickSort {
	// 快慢指针法:数组前后各设置两个指针,左指针(从左向右走)遇到第一个比基准值大的数停下
	// 右指针(从右向左走)遇到第一个比基准值小的数停下,然后交换两个指针指的值
	// 如果基准定在左边一定要先动右指针,反之亦然
	public static void quickSort(int[] arr, int low, int high) {
		if (arr == null || arr.length <= 0 || low >= high)
			return;
		// 左右指针
		int left = low;
		int right = high;
		// 基准位置的值
		int index = left;
		int temp = arr[left];
		while (left < right) {
			// 右指针(从右向左走)
			while (left < right && arr[right] >= temp) {
				right--;
			}
			// 左指针(从左向右走)
			while (left < right && arr[left] <= temp) {
				left++;
			}
			swap(arr, left, right);
		}
		swap(arr, right, index);
		quickSort(arr, low, left - 1);
		quickSort(arr, left + 1, high);
	}

	// 快排递归方法(挖坑),以某个数作为基数,划分成数组,左边子数组每个元素都小于右边数组,挖坑法
	public static void quickSort2(int[] arr, int low, int high) {
		if (arr == null || arr.length <= 0 || low >= high)
			return;
		int left = low;
		int right = high;
		// 挖坑1:保存基准的值
		int temp = arr[left];
		while (left < right) {
			while (left < right && arr[right] >= temp) { // 坑2:从后向前找到比基准小的元素,插入到基准位置坑1中
				right--;
			}
			arr[left] = arr[right];
			while (left < right && arr[left] <= temp) { // 坑3:从前往后找到比基准大的元素,放到刚才挖的坑2中
				left++;
			}
			arr[right] = arr[left];
		}
		arr[left] = temp; // 基准值填补到坑3中,准备分治递归快排
		System.out.println(Arrays.toString(arr));
		quickSort2(arr, low, left - 1);
		quickSort2(arr, left + 1, high);
	}

	public static void swap(int[] array, int low, int high) {
		int temp = array[low];
		array[low] = array[high];
		array[high] = temp;
	}

	// 快排非递归实现
	/**
	 * 非递归
	 */
	public static void qSort2(int[] a, int low, int high) {
		int pivot;
		if (low >= high)
			return;
		Stack<Integer> stack = new Stack<Integer>();
		stack.push(low);
		stack.push(high);
		while (!stack.empty()) {
			// 先弹出high,再弹出low
			high = stack.pop();
			low = stack.pop();
			pivot = partition(a, low, high);
			// 先压low,再压high
			if (low < pivot - 1) {
				stack.push(low);
				stack.push(pivot - 1);
			}
			if (pivot + 1 < high) {
				stack.push(pivot + 1);
				stack.push(high);
			}
		}
	}

	/**
	 * 递归调用
	 */
	public static void qSort(int[] a, int low, int high) {
		int pivot;
		if (low >= high)
			return;

		// 原始递归操作
		// pivot = partition(a, low, high); // 将数列一分为二
		// qSort(a, low, pivot - 1); // 对低子表排序
		// qSort(a, pivot + 1, high); // 对高子表排序

		// 优化递归操作
		while (low < high) {
			pivot = partition(a, low, high); // 将数列一分为二
			qSort(a, low, pivot - 1); // 对低子表排序
			low = pivot + 1;
		}
	}

	/**
	 * 对数组a中下标从low到high的元素,选取基准元素pivotKey, 根据与基准比较的大小,将各个元素排到基准元素的两端。 返回值为最后基准元素的位置
	 */
	public static int partition(int[] a, int low, int high) {

		// 三数取中,将中间元素放在第一个位置
		if (a[low] > a[high])
			swap(a, low, high);
		if (a[(low + high) / 2] > a[high])
			swap(a, (low + high) / 2, high);
		if (a[low] < a[(low + high) / 2])
			swap(a, (low + high) / 2, low);

		int pivotKey = a[low]; // 用第一个元素作为基准元素
		while (low < high) { // 两侧交替向中间扫描
			while (low < high && a[high] >= pivotKey)
				high--;
			a[low] = a[high];
			// swap(a, low, high); //比基准小的元素放到低端
			while (low < high && a[low] <= pivotKey)
				low++;
			a[high] = a[low];
			// swap(a, low, high); //比基准大的元素放到高端
		}
		a[low] = pivotKey; // 在中间位置放回基准值
		return low; // 返回基准元素所在位置
	}

	public static void main(String[] args) {
		int[] array = { 4, 1, 7, 6, 9, 2, 8, 0, 3, 5 };
		// quickSort(array, 0, array.length - 1);
		// quickSort2(array, 0, array.length - 1);
		qSort(array, 0, array.length - 1);
		// qSort2(array,0, array.length - 1);
		System.out.println(Arrays.toString(array));
	}
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值