三、排序_02 &快速排序 &快速排序的优化——三点中值法(笔记)

先上代码

import java.util.Arrays;
import java.util.Random;

public class A008_快排的优化_1_三点中值法 {
	static int cnt = 0;

	public static void main(String[] args) {
		int len = 2000;
		int max = 1000000000;
		int[] arr = getRandomArr(len, max);
		System.out.println(Arrays.toString(arr));
		quicksort(arr, 0, len - 1);
		System.out.println(cnt + "正常的| " + Arrays.toString(arr));

		arr = getRandomArr(len, max);
		System.out.println(Arrays.toString(arr));
		cnt = 0;
		quicksortINmid(arr, 0, len - 1);
		System.out.println(cnt + "三点中值法| " + Arrays.toString(arr));
	}

	public static void quicksortINmid(int[] arr, int left, int right) {
		if (left >= right)
			return;
			
		int mid = (left + right) / 2;
		int midValue = -1;
		if (arr[left] <= arr[mid] && arr[left] >= arr[right]) {
			midValue = left;
		} else if (arr[right] <= arr[mid] && arr[right] >= arr[left]) {
			midValue = right;
		} else
			midValue = mid;
		int t = arr[midValue];
		arr[midValue] = arr[left];
		arr[left] = t;

		int head = arr[left];
		int L = left;
		int R = right;
		while (L < R) {
			cnt++;
			while (L < R && head < arr[R])
				R--;
			while (L < R && head >= arr[L])
				L++;
			t = arr[L];
			arr[L] = arr[R];
			arr[R] = t;
		}
		arr[left] = arr[R];
		arr[R] = head;
		quicksortINmid(arr, left, R - 1);
		quicksortINmid(arr, R + 1, right);
	}

	public static void quicksort(int[] arr, int left, int right) {
		if (left >= right)
			return;
		int head = arr[left];
		int L = left;
		int R = right;
		while (L < R) {
			cnt++;
			while (L < R && head < arr[R])
				R--;
			while (L < R && head >= arr[L])
				L++;
			int t = arr[L];
			arr[L] = arr[R];
			arr[R] = t;
		}
		arr[left] = arr[R];
		arr[R] = head;
		quicksort(arr, left, R - 1);
		quicksort(arr, R + 1, right);
	}

	public static int[] getRandomArr(int len, int max) {
		int[] arr = new int[len];
		Random ran = new Random(max);
		for (int i = 0; i < len; i++) {
			arr[i] = ran.nextInt(max) + 1;
		}
		return arr;
	}
}

这是运行结果:
在这里插入图片描述
我的数组用的是一个随机生成的数组。数组比较长,就不截全了,主要的是文字前面的cnt的值,首先是正常的快排,取的主元是这一段里面的第一个元素,然后分别把左右指针,赋一个变量,L和R,我的快排是在《啊哈算法》一书中学的,作者讲的很形象,特别好理解:
他把指针比做了两个士兵,一个从右向左走,一个从左向右,从右向左的时候,只要发现当前R下标下的这个元素,小于主元,那么就停住,翻译成代码,也就是当R下标的元素,一直比主元大的时候,那么R就要一直–,(这里也是我一开始写快排,一直出错的地方,小于大于,傻傻的分不清)
然后当R这个士兵停住后,也就是退出循环了,那么,L这个士兵就开始向右走,那么道理也与R一样,当L下标的这个元素大于主元的时候,就停住,那么翻译成代码,也就是只要L下标的这个元素,一直小于等于主元的话,L就一直++
最后他们停住了,那么停住的时候,R下标的这个元素就是小于主元的,而L下标的这个元素是大于主元的,随后就进行交换,然后终止条件就是,当这两个相等的时候,我这里写的可能与其他人写的不太一样,没有增加判断条件,是因为我这里的L和R是不可能出现L>R的情况,最多就是L==R,这与3个while循环判断的条件有关;在跳出最大的循环后,就把主元和当前元素交换就行了,这里L和R可以随意用,因为L肯定是等于R的。
接下来讲三点中值法:

		int mid = (left + right) / 2;
		int midValue = -1;
		if (arr[left] <= arr[mid] && arr[left] >= arr[right]) {
			midValue = left;
		} else if (arr[right] <= arr[mid] && arr[right] >= arr[left]) {
			midValue = right;
		} else
			midValue = mid;
		int t = arr[midValue];
		arr[midValue] = arr[left];
		arr[left] = t;

三点中值法的代码就这点,虽然多,也主要是if…else……语句那边多,三点中值法,其实就是在left、mid、right这三个点中,取一个中间的值的下标,仔细瞅一瞅代码,就能明白,他首先把left和mid和right进行比较,等价于=>(mid<=left<=right)剩下的如上所属。在确定主元后,我下面的三行交换,也是为了偷懒,因为先写好的快排不想修改,所以把中间的下标的那个值,和left进行交换,其他的没变化。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值