`
543089122
  • 浏览: 153204 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

简单_快速选择算法(RANDOMIZED-SELECT)

阅读更多
package sunfa.midNum;

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

/**
 * 
 * 参考:---------------------------------------------
 * http://blog.csdn.net/chen09/article/details/6531678
 * 
 * 快速选择算法 和 第三名:BFPRT 算法 类似,都是在一个无序的数组中寻找第K小的数,
 * 
 * 百度百科上解释了中位数的重要性及其意义,上面的2种算法都是属于中位数算法的
 * 参考:http://baike.baidu.com/view/170892.htm
 * 
 * 总结:-----------------------------------------------
 * 这个中位数之中位数算法,是用来查找未排序集合中第K个数的算法。<br>
 * 主要思想是找到集合中的中间点p,左边的数必须小于中间点位置的数,右边的必须大于它,然后判断找到的中间点是否等于K,<br>
 *  1、如果等于则找到了<br>
 *  2、如果小于(k<p),则对0-p范围的数按上面的思想继续进行查找 <br>
 *  3、如果大于(k>p),则对p-len范围的数按上面的思想继续进行查找,只是不需要找k个数了,而是找p-k个数即可<br>
 * 
 * 找中间点是快速选择算法的核心思想,为什么要找中间点?因为我们没有必要直到这个集合的顺序是怎么样的,<br>
 * 更加没有必要去对其进行排序,我们只需要知道某个中间点的左边的数都<br>
 * 小于该中间点位置的数,反之右边的都大于,如此是递归下去,找到第K大的数只是时间问题.<br>
 * 
 * 其实关于查找第K个最大(小)的数是算法有好多,这只是其中比较好的一种方法,另一种较好的比如借助于大小堆也不错,充分体现了堆的强大,<br>
 * 记得有个面试题是:1亿个数据中找前100个数。就是利用大小堆完成的效率比较高.<br>
 * ------------------------------------------------
 */
public class RandomizedSelect {
	
	private static <T> int partition(T[] a, Comparator<? super T> c, int p, int r) {
		T t = a[r - 1];
		int i = p - 1;// 中间点,小的放在i的左边,大的放右边,最后返回的i就是中间点
		for (int j = p; j < r - 1; j++) {// 从p到r-2,为什么是r-2呢?因为第r-1位置的数已被做为比较的对象了
			if (c.compare(a[j], t) <= 0) {// 从左边开始,循环的拿左边的数和最后一个数进行比较,把小的放在左边大的放右边,并且计数中位数
				i++;
				swap(a, i, j);
			}
		}
		// 在randomizedPartition方法中我们把主元放到了最后,那么中间点找到后我们得把主元放到中间点来,那么i+1便是最后得到的中间点
		swap(a, i + 1, r - 1);
		return i + 1;
	}

	private static <T> int randomizedPartition(T[] a, Comparator<? super T> c,
			int p, int r) {
		int i = new Random().nextInt(r - p) + p;// 随机选择算法
		// 随机出来的位置的数做为主元,所谓主元就是被比较的对象,我们假设有一个数的大小处于p到r的中间,这样的数被称为主元
		// 这个主元要被放到p...r的最后位置,所以这里要和最后一个元素交换
		swap(a, i, r - 1);
		return partition(a, c, p, r);
	}

	private static <T> void swap(T[] a, int i, int j) {
		T t = a[i];
		a[i] = a[j];
		a[j] = t;
	}

	private static <T> T randomizedSelect(T[] t,
			Comparator<? super T> comparator, int p, int r, int i) {
		if (p == r)// 找到第K个数
			return t[p];
		int q = randomizedPartition(t, comparator, p, r);// 找到中间点
		int k = q - p + 1;// 中间点q前面有有多少个数字
		if (i <= k)// 判断是否找到第i个数
			return randomizedSelect(t, comparator, p, q, i);// 区间查找
		else
			return randomizedSelect(t, comparator, q + 1, r, i - k);// 区间查找
	}

	private static <T> T randomizedSelect(T[] t,
			Comparator<? super T> comparator, int i) {
		return randomizedSelect(t, comparator, 0, t.length, i);
	}

	public static void main(String[] args) {
		Integer[] ints = new Integer[20];
		Random ran = new Random();
		int k = 10;
		for (int i = 0; i < ints.length; i++) {
			ints[i] = ran.nextInt(100);
		}
		Integer positiong = randomizedSelect(ints, new Comparator<Integer>() {
			public int compare(Integer o1, Integer o2) {
				return o1.intValue() - o2.intValue();
			}
		}, k);
		System.out.println("快速选择算法求出的,第"+k+"个最大数是:"+positiong);
		Arrays.sort(ints);
		System.out.println("排序后,第"+k+"个最大数是:"+ints[k-1]);
		System.out.println(Arrays.toString(ints));
	}
}

分享到:
评论

相关推荐

    C++实现第K顺序统计量的求解方法

    算法的核心思想是从快速排序的随机划分操作(RANDOMIZED-PARTITION)出发,通过不断地将数组划分为两个部分,然后递归地在正确的一侧查找第k小的元素。以下是算法的伪代码: ``` RANDOMIZED-SELECT(A, p, q, i) if...

    TOP,K算法.pdf

    2. **RANDOMIZED-SELECT**:这是线性期望时间复杂度的算法,随机选取序列中的一个元素作为主元,通常用于快速选择算法。 3. **SELECT算法**:快速选择算法,通过选取序列中“五分化中项的中项”或“中位数的中位数...

    Notes on Randomized Algorithms

    10. 具体算法分析:随机快速排序(Randomized QuickSort)和拉塞夫选择(Lazyselect)算法被用来展示如何应用概率论和随机变量分析来优化算法性能和确定性。 通过这些知识点,可以对随机算法的原理和分析方法有一个...

    05DemoQuick.pdf

    【算法设计】中的核心主题是分治法(Divide and Conquer)以及快速选择算法(Randomized Quickselect)。这两种算法都是在数据排序和查找问题中非常重要的策略。 分治法是一种解决问题的策略,它将一个大问题分解为...

    Java基于分治算法实现的线性时间选择操作示例

    Randomized Select算法是解决线性时间选择问题的一种常用方法,该算法基于分治算法的思想,即将问题分解成较小的子问题,然后对子问题进行解决。Randomized Select算法的main思路是:首先,随机选择一个元素作为划分...

    各种排序算法C语言实现

    随机化选择是寻找数组中第k小(或第k大)元素的算法,可以看作是快速选择的变种,通过随机化选择枢轴元素来提高性能。 9. **快速排序的递归版与非递归版**: 如前所述,递归版使用了函数递归,而非递归版使用循环...

    matlab基于多层编码遗传算法的车间调度算法【matlab优化算法十九】

    `select.m` 可能是选择操作的实现,这是遗传算法的关键步骤,其中较好的个体有更高的概率被选中来生成下一代。 `across.m` 代表“交叉”操作,通常包括单点、多点或部分匹配等交叉策略,用于结合两个父代个体生成新...

    查找第i小的元素

    一种常用的算法是快速选择算法,它是快速排序的一个变体,专注于找到序列中的第k小(或大)元素,而不是完全排序整个序列。 快速选择算法的基本思想是: 1. 选取一个枢轴元素,将序列分为三个部分:小于枢轴的元素...

    算法导论课后习题与思考题答案合集

    顺序统计量的算法包括基于快速排序的快速选择算法(QuickSelect)以及可以达到线性时间复杂度的中位数选择算法。 6. 第11章:哈希表(Hash Tables) 哈希表是解决查找问题的重要数据结构,它能够提供平均情况下...

    归并排序源代码_上机

    在代码中还包含了一个名为 `RANDOMIZED_PARTITION` 的函数,这与快速选择算法有关。快速选择是快速排序的一种变体,用于寻找序列中的第 `i` 小(或大)的元素。在这个函数中,选取了一个随机元素 `x` 作为基准,然后...

    线性时间选择

    一种经典的线性时间选择算法是“随机化快速选择”(Randomized Quickselect),它是快速排序的一个变种。算法的基本思想是:从数组中随机选择一个“枢轴”元素,将数组分为三部分:小于枢轴的元素、等于枢轴的元素和...

    MATLAB基于多层编码遗传算法的车间调度算法.zip

    4. **SELECT.M**: 可能是选择操作的实现,遗传算法中的选择操作是根据适应度值选择一部分个体进入下一代。 5. **across.m**: 可能与交叉操作有关,遗传算法中,个体间的交叉产生新的后代,这是算法进化的重要步骤。...

    Randomizedselect.rar_Windows编程_C/C++_

    随机化选择算法是快速选择算法的一种变体,由C.A.R. Hoare在1960年提出的快速排序算法的基础上发展而来。它的工作原理是通过随机化过程来减少最坏情况下的时间复杂度,使得平均情况下,算法的时间复杂度为线性,即Θ...

    知识中心:一些随机实施

    在算法实现中,随机化算法如快速排序(QuickSort)、随机化快速选择(Randomized QuickSelect)或哈希表(Hash Tables)的冲突解决策略,都依赖于随机数生成。 C++的标准库也提供了数据结构和算法的实现,如`std::...

Global site tag (gtag.js) - Google Analytics