【问题标题】:How to check if Array is sorted?如何检查数组是否已排序?
【发布时间】:2014-07-11 15:52:43
【问题描述】:

如何检查TArray 是否已经排序?我正在使用默认的TArray.Sort 对我的数组进行排序。

【问题讨论】:

  • 如果我有 1000 万个元素怎么办?
  • 如果不检查每个元素与其相邻元素,您无法判断数组是否已排序。如果您有 1000 万个元素,并且除了 3 个在这 1000 万个中某个位置不合适的元素之外,所有元素都已排序怎么办?最简单的做法是要么对数组进行排序,要么开始检查乱序元素,当你找到一个你对数组进行排序的那一刻(这意味着你现在已经将检查数组的时间添加到时间它将需要排序)。增加的时间是否有问题取决于您。

标签: delphi delphi-xe6


【解决方案1】:

使用与排序相同的比较器检查邻居对

Result := True;
for i := Low(Arr) + 1 to High(Arr) do
  if Compare(Arr[i], Arr[i - 1]) < 0 then
    Exit(False);

需要 O(n) 时间(相对于 O(nlogn) 进行排序)

【讨论】:

  • 除非你发现数组没有排序,然后无论如何都要排序,这种情况下你的效率无论如何都被吹出窗外了。
  • +1 事实上,TArray.Sort uses quicksort,在几乎/已经排序的数组 performs even worse 的情况下,比 O(nlogn) 的时间长。
  • @Ken White 所以作者必须考虑最有可能的情况——大多数时候数组是排序的吗?
  • 是的,这就是我在对问题的评论中所说的。 :-)(顺便说一句,我对您的评论带有 +1 ;如果您确实需要检查,这就是这样做的方法。)
  • @GSerg 实际上,使用 QuickSort 并不能保证几乎/已经排序的数据的最坏情况下的性能。它还取决于实现如何选择其枢轴元素。不幸的是,我没有最新版本的 Delphi 来检查TArray.Sort,但如果它使用Classes.QuickSort:则该实现以中间元素为中心。在这种情况下,已经排序的数组实际上是获得最佳性能的最佳分布。
【解决方案2】:

我这样做如下。事实上,我的班级有更多好东西,我刚刚包含了测试数组是否有序的代码。我使用TArray 并将版本隐藏在Generics.Collections 中,但从它派生以继承其功能。这会导致代码可读性更好,尽管使用隐藏可能会让您一开始就感到不安。

uses
  System.SysUtils,
  System.Generics.Defaults,
  System.Generics.Collections;

type
  TSortType = (stIncreasing, stDecreasing);

  TArray = class(System.Generics.Collections.TArray)
  private
    class function Comparison<T>(SortType: TSortType): TComparison<T>; static;
    class function Comparer<T>(const Comparison: TComparison<T>): IComparer<T>; static;
  public
    class function Sorted<T>(var Values: array of T; SortType: TSortType; Index, Count: Integer): Boolean; overload; static;
    class function Sorted<T>(var Values: array of T; SortType: TSortType): Boolean; overload; static;
    class function Sorted<T>(var Values: array of T; const Comparison: TComparison<T>; Index, Count: Integer): Boolean; overload; static;
    class function Sorted<T>(var Values: array of T; const Comparison: TComparison<T>): Boolean; overload; static;
    class function Sorted<T>(GetValue: TFunc<Integer,T>; const Comparison: TComparison<T>; Index, Count: Integer): Boolean; overload; static;
  end;

class function TArray.Comparison<T>(SortType: TSortType): TComparison<T>;
var
  DefaultComparer: IComparer<T>;
begin
  DefaultComparer := TComparer<T>.Default;
  Result :=
    function(const Left, Right: T): Integer
    begin
      case SortType of
      stIncreasing:
        Result := DefaultComparer.Compare(Left, Right);
      stDecreasing:
        Result := -DefaultComparer.Compare(Left, Right);
      end;
    end;
end;

class function TArray.Comparer<T>(const Comparison: TComparison<T>): IComparer<T>;
begin
  Result := TComparer<T>.Construct(Comparison);
end;

class function TArray.Sorted<T>(var Values: array of T; SortType: TSortType; Index, Count: Integer): Boolean;
begin
  Result := Sorted<T>(Values, Comparison<T>(SortType), Index, Count);
end;

class function TArray.Sorted<T>(var Values: array of T; SortType: TSortType): Boolean;
begin
  Result := Sorted<T>(Values, Comparison<T>(SortType));
end;

class function TArray.Sorted<T>(var Values: array of T; const Comparison: TComparison<T>; Index, Count: Integer): Boolean;
var
  i: Integer;
begin
  for i := Index+1 to Index+Count-1 do begin
    if Comparison(Values[i-1], Values[i])>0 then begin
      Result := False;
      exit;
    end;
  end;
  Result := True;
end;

class function TArray.Sorted<T>(var Values: array of T; const Comparison: TComparison<T>): Boolean;
begin
  Result := Sorted<T>(Values, Comparison, 0, Length(Values));
end;

class function TArray.Sorted<T>(GetValue: TFunc<Integer, T>; const Comparison: TComparison<T>; Index, Count: Integer): Boolean;
var
  i: Integer;
begin
  for i := Index+1 to Index+Count-1 do begin
    if Comparison(GetValue(i-1), GetValue(i))>0 then begin
      Result := False;
      exit;
    end;
  end;
  Result := True;
end;

【讨论】:

    猜你喜欢
    • 2012-04-08
    • 2013-08-09
    • 2018-04-10
    • 1970-01-01
    • 2018-12-18
    • 2016-09-23
    • 2020-06-04
    • 1970-01-01
    • 2011-11-06
    相关资源
    最近更新 更多