/** * @(#)FuzzySort.java * * * @author * @version 1.00 2009/7/17 */ //算法导论7-6 对区间的模糊排序 /**问题描述: * 考虑这样的一种排序问题,即无法准确地知道待排序的各个数字到底是多少。对于其中的每个数字, * 我们只知道它落在实轴上的某个区间内。亦即,给定的是n个形如[a(i), b(i)]的闭区间(这里小括 * 后起下标的作用,后同),其中a(i) <= b(i)。算法的目标是对这些区间进行模糊排序 * (fuzzy-sort),亦即,产生各区间的一个排列<i(1), i(2), ..., i(n)>,使得存在一个c(j)属于 * 区间[a(i(j)), b(i(j))],满足c(1) <= c(2) <= c(3) <= ... <= c(n)。 * a) 为n个区间的模糊排序设计一个算法。你的算法应该具有算法的一般结构,它可以快速排序左部 * 端点(即各a(i)),也要能充分利用重叠区间来改善运行时间。(随着各区间重叠得越来越多, * 对各区间进行模糊排序的问题会变得越来越容易。你的算法应能充分利用这种重叠。) * b) 证明:在一般情况下,你的算法的期望运行时间为Θ(nlgn),但当所有的区间都重叠时,期望的 * 运行时间为Θ(n)(亦即,当存在一个值x,使得对所有的i,都有x∈[a(i), b(i)])。你的算法 * 不应显式地检查这种情况,而是应随着重叠量的增加,性能自然地有所改善。 */ /**算法思想: *利用快速排序算法的思想,对区间序列进行划分。但此时的主元区间元素是一个区间元素集合中所有区间元素的公共区间(交集), *即是说该集合中的所有区间元素都是“相等的”或者说“任意序都是有序的”。初始时,算法任选一个区间元素作为主元(同快速排序)。 *算法运行过程中,如果某个区间元素严格小于主元,则将其放到序列左边;如果其严格大于主元,则将其放到序列右边; *否则,说明该区间元素与主元相交,则更新主元区间大小为该相交的区间部分,并将该区间元素加入到与主元“相等”的区间元素集合中。 *处理完当前序列后,再递归处理左边和右边的子序列(分治思想嘛,同快速排序)。 */ import java.io.*; import java.util.*; import java.math.*; // 区间 class Interval{ int first; int second; public Interval(int i,int j){ this.first = i; this.second = j; } } public class FuzzySort { /** * Creates a new instance of <code>FuzzySort</code>. */ //划分 public static Interval fuzzyPartition(Interval[] arr, int p, int r){ int i = p, k = p+1, j = r; Interval x = new Interval(arr[p].first,arr[p].second); while (k<=j){ if(arr[k].second<x.first){//比主元区间小 swap(arr[k],arr[i]); i++; k++; } else if(arr[k].first>x.second){//比主元区间大 swap(arr[k],arr[j]); j--; } else{//区间重叠 取交集 x.first = Math.max(x.first, arr[k].first); x.second = Math.min(x.second, arr[k].second); k++; } } return new Interval(i,j); } //交换 public static void swap(Interval a,Interval b){ int itmp=0,jtmp=0; itmp = a.first;jtmp = a.second; a.first = b.first;a.second = b.second; b.first = itmp;b.second = jtmp; } //递归排序 public static void fuzzySort(Interval[] arr, int p, int r){ if(p<r){ Interval q = fuzzyPartition(arr,p,r); fuzzySort(arr, p, q.first - 1); fuzzySort(arr, q.second + 1, r); } } //主函数 public static void main(String[] args) { // TODO code application logic here Interval[] arr = {new Interval(7,9),new Interval(9,10),new Interval(2,5),new Interval(4,8),new Interval(1,10)}; //Interval[] arr = {new Interval(7,9),new Interval(2,5)}; //Interval[] arr = {new Interval(4,8),new Interval(2,5)}; //Interval[] arr = {new Interval(1,2),new Interval(2,3),new Interval(3,4),new Interval(4,5),new Interval(5,6)}; fuzzySort(arr,0,arr.length-1); for(int i = 0;i<arr.length;i++){ System.out.print("["+arr[i].first+","+arr[i].second+"]"); System.out.print(" "); } } }