排序值,但仅当它们比当前顺序多X时

时间:2009-01-22 13:13:13

标签: algorithm delphi sorting

我一直在搜索Google(当然还有堆栈溢出!),这是一种按值排序整数列表的方法,也是一个额外的因素。我想要实现某种算法来实现。到目前为止,我在Delphi 2007中有一个数组,它将值从最大值分类到最小值,但现在我希望它对列表中的前一个数字的X值进行排序。

例如,值5,7,25,15当前已分类为25,15,7,5。我现在尝试获得的顺序,X值为5,为25,15,5, 7.如您所见,5和7没有切换位置,因为它们之间的差异不超过5个。

不确定我是否特别好解释这一点,但这是一般的想法。

另一个例子是值10,40,18,20,16,28。排序后,它们应该是40,28,18,20,16,10。18,20和16没有移动,因为再一次,每个数字之间不超过5个。

背后的想法是,与数字相关联的项目(例如订购的次数)不会一直变化,因为只有1或2的差异。例如,如果最频繁订购的纸张列表按购买的频率显示在网页上,然后特定类型纸张的订单只会在用户订购超过下一次最常频率五倍以上时更改。

希望这是有道理的,谢谢你的时间!

8 个答案:

答案 0 :(得分:3)

我认为你的要求导致了非常奇怪的结果。最终,您可以使用排序顺序,其中项目的排序方式完全错误,排序方式取决于它们的变化方式。

我认为你需要建立价值观的“阶级”(使用百分位?),然后在每个班级中按字母顺序对报纸进行排序。

例如:几乎没有订购(90%的纸张订购超过这一份),低于中位数(50%的报纸订购超过这些),高于中位数,前10名(按订单数量排序)疗程)。

答案 1 :(得分:3)

至少你需要使用一个稳定的排序,即一种保留等价值排序的排序。

一旦你有了这个,你应该将你的比较定义为abs(a - b)<5,等于,否则,进行正常的比较。这使得compare(a, b)==compare(b, a)成为最好的排序实现应该断言的东西。

如果您使用的是C ++,则可以使用std::stable_sort来执行此操作。

答案 2 :(得分:2)

考虑到这一点后,我认为冒泡排序是唯一可行的排序类型。这是因为在冒泡排序中,数字必须明显大于(或者在这种情况下大5),而不是它上面的数字,以便它们更改位置。这正是你所要求的。

从高层次来看,我认为你需要的是:

  1. 采用自定义比较功能的冒泡排序实现。

  2. 比较函数,如果差值小于5,则返回相等。

  3. 合并这两件事应该可以让你了解你的目标。

答案 3 :(得分:1)

有两件事对我们来说非常重要:

  • 1)你需要一个稳定的排序算法(它不需要冒泡排序,它可能不应该),这意味着如果比较器返回0(=相等)它保留原始顺序。有关概述,请参阅wikipedia's comparison of sorting algorithms

  • 2)您需要一个自定义比较器,在您提到的情况下返回0。

  • 答案 4 :(得分:0)

    尝试使用自定义比较功能进行排序,如果用数字填充TList并调用MyList.Sort(myCompareFunc),则可以快速尝试;

    function  myCompareFunc(item1,item2:Pointer):Integer;
    var 
     v1,v2:Integer;
    begin
    
      v1 := (integer)item1;
      v2 := (integer)item2;
    
      if v1 > v2 then 
           result := 1
      else if (v1 < v2 )
           result := -1
      else 
           result := 0
    
      //most important
      if abs(v1-v2) < 5 result := 0 ; 
    
    end;
    

    答案 5 :(得分:0)

    将排序原则应用于几乎排序的列表可能是有意义的,但是您应该意识到它违反了一般排序算法的基本假设:要排序的元素形成总排序。这显然意味着&lt;运算符的行为方式与实数相同。如果你违反了这个规则,那么你可能会得到奇怪的效果,库算法可能甚至不会终止(甚至崩溃,我已经看到这种情况发生在C ++中的std :: sort)。

    修改您的想法以使其成为总订单的一种方法是对每个数字进行排序,向下舍入到最接近的5的倍数。

    答案 6 :(得分:0)

    我认为这需要两次通过。在第一遍中,识别任何可能被排序的值,并且在第二遍中实际上仅移动那些被识别的值。在你的第二个例子中,使用一个Y / N数组和Y进行排序,你最终得到[Y,Y,N,N,N,Y],然后只排序值Y,N'将是“忽略不符合排序条件“你会得到[40,28,18,20,16,10]的结果列表。 N组(将始终是基于定义的组)应与其组中最高的值进行比较。

    答案 7 :(得分:0)

    TList.Sort不起作用,因为它使用快速排序algoritham作为mghie评论。

    冒泡排序algoritham并不是那么快,这里是实现所以你可以试试,这次是在pascal。

    var I,N,T,D:Integer ;
        A:array of Integer;
        Change:Boolean;
    begin
    
      SetLength(A, 4);
      A[0] := 5;
      A[1] := 7;
      A[2] := 25;
      A[3] := 15;
    
      Change := True;
      N := High(A);
    
      while Change do
      begin
        Change := false;
    
        for I := 1 to N do
        begin
           D := A[I]-A[I-1];
    
           if  (D > 5)  then
           begin
              T := A[I-1];
              A[I-1] := A[I];
              A[I] := T;
              Change := true;
           end;
        end;
      end;
    end;