【转】模糊排序问题(Fuzzy sort)

来源:互联网 发布:linux怎么打开文件夹 编辑:程序博客网 时间:2024/05/18 11:22

算法导论第2版的7-6,首先理解题目就花了n久,从网上找了些思路,下面具体来说

 

题目内容:

考虑这样的一种排序问题,即无法准确地知道待排序的各个数字到底是多少。对于其中的每个数字,我们只知道它落在实轴上的某个区间内。亦即,给定的是n个形如[ai, bi]的闭区间,其中ai<= bi。算法的目标是对这些区间进行模糊排序(fuzzy-sort),亦即,产生各区间的一个排列<i1, i2, ..., in>,使得存在一个cj属于区间[aij, bij],满足c1 <= c2 <= ... <= cn
a) 为n个区间的模糊排序设计一个算法。你的算法应该具有算法的一般结构,它可以快速排序左部端点(即各ai),也要能充分利用重叠区间来改善运行时间。(随着各区间重叠得越来越多,对各区间进行模糊排序的问题会变得越来越容易。你的算法应能充分利用这种重叠。)

b) 证明:在一般情况下,你的算法的期望运行时间为Θ(nlgn),但当所有的区间都重叠时,期望的运行时间为Θ(n)(亦即,当存在一个值x,使得对所有的i,都有x∈[ai, bi])。你的算法不应显式地检查这种情况,而是应随着重叠量的增加,性能自然地有所改善。

 

 

算法思路:这是对一组给定的区间序列来模糊排序,可以利用快速排序的思想,对区间序列进行划分。但此时的主元区间元素是一个区间元素集合中所有区间元素的公共区间(交集),即是说该集合中的所有区间元素都是“相等的”或者说“任意序都是有序的”。初始时,算法任选一个区间元素作为主元(同快速排序的哨兵元素)。如果某个区间元素严格小于主元,则将其放到序列左边;如果其严格大于主元,则将其放到序列右边;否则,说明该区间元素与主元相交,则更新主元区间大小为该相交的区间部分,该区间元素放置在整个序列的中间部分(对这部分区间序列可以不作严格排序,因为只需要满足<存在一个cj..>),然后递归的处理左边和右边区间序列即可

 

 

算法描述:

private static int[] patition(Interval[] Int, int p, int r)
{
      Interval pivot = new Interval(Int[r].begin,Int[r].end);
      int i = p;
      int j = p;
     int k = r;
      while (j < k)
      {
           if (Int[j].end <= pivot.begin)
          {
           Interval temp0 = Int[i];
            Int[i] = Int[j];
           Int[j] = temp0;
            i++;
           j++;
           }
         else if (Int[j].begin >=pivot.end)
        {
          Interval temp1 = Int[k];
            Int[k] = Int[j];
            Int[j] = temp1;
            k--;
        }
        else
        {
          pivot.begin=(Int[j].begin>pivot.begin?Int[j].begin:pivot.begin);
           pivot.end=(Int[j].end<pivot.end?Int[j].end:pivot.end);
           j++;
        }
       }
      return new int[] {i,k};
}

 

变量i和k的作用就是标识左区间的结束位置+1和右区间开始位置-1,返回一个{i,k}数组便于排序算法使用,下面是排序过程

public static void quickSort(Interval[] Int,int p,int r)
{
     if(p<r)
     {
          int[] q=patition(Int, p, r);
         quickSort(Int, p, q[0]-1);
         quickSort(Int, q[1]+1, r);
      }
}

 

 

算法性能简单分析:利用快速排序思想,分析每步运算期望时间复杂度为Θ(nlgn),并充分利用的区间重叠减少运行时间,当所有区间都有相同重叠部分时,这时patition过程消耗Θ(n),左右区间都为空,故不需要再作递归,整个时间复杂度满足要求。当然,对中间重叠部分可以作排序处理(比如快排每个区间的左端点值)显得更严谨,也可能是多此一举吧,不然为什么称为"模糊"排序呢?最后是Interval的定义和测试

class Interval

{
    public float begin;
    public float end;

   public Interval(float a, float b)
   {
       this.begin = a;
        this.end = b;
    }

    public static void main(String[] args)
   {
     Interval[] b = { new Interval(1, 2), new Interval(0.5f, 1), new Interval(3, 4),

                         new Interval(7.5f, 8.0f), new Interval(5, 8), new Interval(3, 4.5f) };

     quickSort(b, 0, 5);
   }
}

 

 

文章出处:http://hi.baidu.com/pink629/blog/item/0550f302f908418ed53f7c66.html