数组序列算法效率

时间:2017-02-06 15:02:57

标签: arrays algorithm ada

我正在寻找更有效算法的建议,以确定数组是否包含从1到数组长度的所有值。我设计的解决方案使用Ada2012正常工作。

------------------------------------------------------------------
-- Build a function to determine whether an array contains --
-- all the values from 1 through the length of the array. --
------------------------------------------------------------------
with Ada.Text_IO; use Ada.Text_IO;

procedure Sequence_test is
   type Sequence_Array is array(Positive range <>) of Integer;

   function Is_Sequence(Item : Sequence_Array) return Boolean is
      Flags : Array(Positive range 1..Item'Length) of Boolean := (Others => False);
   begin
      for Num of Item loop
         if Num in Flags'Range then
            Flags(Num) := True;
         else
            exit;
         end if;
      end loop;
      return (for all P of Flags => P = True);
   end Is_Sequence;
   A : Sequence_Array := (1,2,3,4,5,6);
   B : Sequence_Array := (6,5,4,3,2,1);
   C : Sequence_Array := (1,1,1,6,6,6);
   D : Sequence_Array := (1,2,3,4,6);
   E : Sequence_Array := (6,1,5,2,4,3);
   F : Sequence_Array := (1,1,1,2,3,4,5,9,10,11);
begin
   Put_Line("A is " & Boolean'Image(Is_Sequence(A)));
   Put_Line("B is " & Boolean'Image(Is_Sequence(B)));
   Put_Line("C is " & Boolean'Image(Is_Sequence(C)));
   Put_Line("D is " & Boolean'Image(Is_Sequence(D)));
   Put_Line("E is " & Boolean'Image(Is_Sequence(E)));
   Put_Line("F slice is " & Boolean'Image(Is_Sequence(F(3..7))));
end Sequence_test;

我的程序输出

A is TRUE
B is TRUE
C is FALSE
D is FALSE
E is TRUE
F slice is TRUE

2 个答案:

答案 0 :(得分:3)

可以使用一些内置的set support。我认为它不能保证更快地执行,但是如果你打开完全优化并且编译器的优化器是好的,它可能执行得更快。我这样说是因为它可以打包你的数组并一次比较32个bool,而不需要为每个数组进行循环迭代。同样,也可以一次创建你的比较数组32。

当然,如果你的优化器真的好,它可能会弄清楚如何用你的代码做同样的事情。

function Is_Sequence(Item : Sequence_Array) return Boolean is
  All_There constant : Array(Positive range 1..Item'Length) of Boolean 
    := (Others => True);
  Flags : Array(Positive range 1..Item'Length) of Boolean := not All_There;

begin
  for Num of Item loop
     if Num in Flags'Range then
        Flags(Num) := True;
     else
        exit;
     end if;
  end loop;
  return Flags = All_There;
end Is_Sequence;

我给你的另一个建议就是用return False;替换那个退出语句你知道那时它不匹配,所以在例程中没有任何意义并且做更多工作。

答案 1 :(得分:2)

在我的电脑上,我用

获得了更好的结果
  for Num of Item loop
     exit when Num not in Flags'Range;
     Flags(Num) := True;
  end loop;
  return (for all P of Flags => P);

更令人惊讶的是,一个命名的子类似乎可以提供更好的结果:

type Item_Length_Array is array(Positive range 1..Item'Length) of Boolean;
Flags : Item_Length_Array := (others => False);

经过测试:

Start_Time := Ada.Real_Time.Clock;
for I in 1..10_000_000 loop
   Ignore := Is_Sequence(A);
   Ignore := Is_Sequence(B);
   Ignore := Is_Sequence(C);
   Ignore := Is_Sequence(D);
   Ignore := Is_Sequence(E);
   Ignore := Is_Sequence(F(3..7));
end loop;
End_Time := Ada.Real_Time.Clock;