Arrays 阵列序列算法效率

Arrays 阵列序列算法效率,arrays,algorithm,ada,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. -

我正在寻找一种更有效的算法的建议,以确定数组是否包含从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;
你可以使用一些内置的。我不认为它一定能执行得更快,但是如果你打开完全优化,并且你的编译器的优化器很好,它可能会执行得更快。我之所以这样说,是因为它可以打包您的数组并一次比较32个布尔值,而不需要对每个布尔值进行循环迭代。同样,它还可以一次创建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替换退出语句你知道在那一点上它不匹配,所以在例行程序中做更多的工作是没有意义的。

你可以使用一些内置的。我不认为它一定能执行得更快,但是如果你打开完全优化,并且你的编译器的优化器很好,它可能会执行得更快。我之所以这样说,是因为它可以打包您的数组并一次比较32个布尔值,而不需要对每个布尔值进行循环迭代。同样,它还可以一次创建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替换退出语句你知道在那一点上它不匹配,所以在日常工作中做更多的工作是没有意义的。

在我的电脑上,我用

  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;

在我的电脑上,我得到了一个稍微好一点的结果

  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;


你能更好地解释一下这个要求吗?例如:你在索引
i
检查
a[abs(a[i])-1]>0
如果没有
返回false
否则
a[abs(a[i])-1]*=-1
并继续迭代。复杂性是
O(n)
要求确定数组是否包含从1到数组长度的所有值。值可以是任意顺序,但必须表示每个值。例如,一个6元素数组必须包含值1..6.时间效率,或空间效率?时间效率。您能更好地解释一下要求吗?例如:您位于索引
i
检查
a[abs(a[i])-1]>0
如果没有
返回false
否则
a[abs(a[i])-1*=-1
并继续迭代。复杂性是
O(n)
要求确定数组是否包含从1到数组长度的所有值。值可以是任意顺序,但必须表示每个值。例如,一个6元素的数组必须包含值1..6.0,或者在时间上空间有效。使用传入数组的实际范围是错误的。值序列必须从1开始,因此无论传入的数组有多长,Flags数组都必须从1开始。当传入数组的长度大于Integer'Last时,使用标志数组将失败,例如,当传入数组的范围为Integer'First..Integer'Last时。@JimRogers-我想知道这一点(请参阅我的注释,关于不完全理解要求)。因此,在这种情况下,我将把这些放回,但是认为这是一个强烈的建议,考虑在切片通过的情况下,算法会发生什么。可以简单地改变要求,使得传递的数组定义为数组(正范围)。Integer@JimRogers这难道不允许有人通过(5..10)考试吗阵列?是的,会的。试试看。测试值的for循环与传入数组的索引范围无关。它使用传入的任何范围。该范围将是切片的范围,而不是数组基类型的范围。使用传入数组的实际范围是错误的。值序列必须从1开始,因此无论传入的数组有多长,Flags数组都必须从1开始。当传入数组的长度大于Integer'Last时,使用标志数组将失败,例如,当传入数组的范围为Integer'First..Integer'Last时。@JimRogers-我想知道这一点(请参阅我的注释,关于不完全理解要求)。因此,在这种情况下,我将把这些放回,但是认为这是一个强烈的建议,考虑在切片通过的情况下,算法会发生什么。可以简单地改变要求,使得传递的数组定义为数组(正范围)。Integer@JimRogers这难道不允许有人通过(5..10)考试吗阵列?是的,会的。试试看。测试值的for循环与传入数组的索引范围无关。它使用传入的任何范围。该范围将是切片的范围,而不是数组基类型的范围。