如何从Delphi集中获得最高价值?

时间:2009-05-06 22:56:02

标签: algorithm delphi set

有没有办法提取集合中的最高(或最低)值?例如,如果我有以下“字节集”:

[0, 1, 2, 4, 5, 28, 199]

我可以运行任何功能并返回199作为结果吗?

编辑:有一个明显的暴力解决方案涉及for..in循环。如果可能的话,我想找到比这更好的方法。

5 个答案:

答案 0 :(得分:14)

循环确实是正式的方法。

type
  TSetType = set of TEnumType;

function HighestMember(const s: TSetType): TEnumType;
begin
  for Result := High(Result) downto Low(Result) do
    if Result in s then
      exit;
  raise Exception.Create('empty sets have no highest member');
end;

任何其他类型的解决方案都需要使用类型转换或汇编程序,这两种方式都会迫使您失去类型安全性 - 它们会“超出语言”,可以这么说。

如果你可以保证你的集合不超过32个可能的元素,那么集合可以用普通整数覆盖,你的问题等同于要求在32位整数中设置最高位的位置。之前有人问过这个,差不多:

如果您对集合类型没有32个元素的限制,那么您有Delphi的256个元素限制,并且任何bit-twiddling解决方案都需要处理32- 字节输入

答案 1 :(得分:6)

集合是无序的,因此您不会比循环更好。如果你经常查找集合的最小值/最大值,那么使用heap data structure,它提供O(1)查找以获取最小/最大值和O(log n)查找任何其他值

答案 2 :(得分:2)

这是一个使用字节集内部结构知识的更快版本。

type
  TByteSet = set of Byte;

function HighestElement(const ByteSet: TByteSet): Byte;
type
  TSetBytes = array[0..SizeOf(TByteSet) - 1] of Byte;
var
  I, J: Integer;
  B: Byte;
  SetBytes: TSetBytes;
begin
  if ByteSet <> [] then
  begin
    SetBytes := TSetBytes(ByteSet);
    // Start at the top and work down, one byte at a time
    for I := SizeOf(TByteSet) - 1 downto 0 do
    begin
      // Any bits set here
      B := SetBytes[I];
      if B <> 0 then
      begin
        Result := I * 8;
        for J := 0 to 7 do
          if (B shr J) and 1 <> 0 then
          begin
            Result := Result + J;
            Exit;
          end;
      end;
    end;
  end else
    // No elements set
end;

您可以将集合的类型TByteSet更改为几乎任何集合类型,此功能仍然有效。只需将函数decl和body中的TByteSet替换为集合的类型即可。如果使用一组AnsiChar或一组枚举类型,您也可以修改它以返回实际的元素类型。要获得最低值,将“I”for循环更改为“0到SizeOf(TByteSet) - 1”,并将“J”循环中的if测试更改为“if(B shl J)和$ 80&lt;&gt; 0”

答案 3 :(得分:1)

几乎相同,但更短:

type
  TByteSet = set of Byte;

function MaxSet(S: TByteSet): Byte;
var
  CardArr: Array [0..7] of Cardinal absolute S;
  i: Byte;
begin
  i := 7;
  while (i > 0) AND (CardArr[i] = 0) do
    Dec(i);
  Result := i + Floor(Log2(CardArr[i]));
end;

答案 4 :(得分:1)

最高和最低,不使用数学单位:

type
  TCharSet = set of Char;

function MaxOfSet(aSet: TCharSet):Char;
var
  Data:array[0..SizeOf(TCharSet)-1] of Byte absolute aSet;
  i,r:Byte;
begin
  if aSet<>[] then begin
     i:=SizeOf(TCharSet)-1;
     while (i>0) and (Data[i]=0) do
        Dec(i);
     r:=i*8;
     i:=Data[i];
     while (i and $80)=0 do begin
        i:=i shl 1;
        Dec(r)
     end;
     Result:=Chr(r+7)
  end
  else
     raise Exception.Create('Unable to extract max value from an empty set');
end;

function MinOfSet(aSet: TCharSet):Char;
var
  Data:array[0..SizeOf(TCharSet)-1] of Byte absolute aSet;
  i,r:Byte;
begin
  if aSet<>[] then begin
     i:=0;
     while (i<SizeOf(TCharSet)-1) and (Data[i]=0) do
        Inc(i);
     r:=i*8;
     i:=Data[i];
     while (i and 1)=0 do begin
        i:=i shr 1;
        Inc(r)
     end;
     Result:=Chr(r)
  end
  else
     raise Exception.Create('Unable to extract min value from an empty set');
end;