随机化数组?

时间:2013-03-10 16:06:30

标签: delphi list pascal

在pascal中,我想随机组织一个数组。因此,大多数情况下阵列的组织方式应该不同。

考虑这个数组设置

const
  ARRAY_ELEMENTS = 3;

SetLength(iIndex, ARRAY_ELEMENTS);

for i := Low(iIndex) to High(iIndex) do
begin
   case i of
   0: iIndex[i] := 0;
   1: iIndex[i] := 1;
   2: iIndex[i] := 2;
   end;
end; 

包含值0的iIndex[]如何不能始终位于数组的第一个元素中,并且包含值2的iIndex[]不能始终是最后一个值数组但是随机生成数组的顺序,以便在初始化时数组的顺序并不总是相同的?

2 个答案:

答案 0 :(得分:4)

此代码置换整数数组,但我不确定它是否是最佳的(可能不是)。

type
  TDynIntegerArray = array of integer;

procedure PermuteArray(A: TDynIntegerArray);
var
  B: TDynIntegerArray;
  Z: TDynIntegerArray;
  π: TDynIntegerArray;
  i: Integer;
  j: Integer;
  k: Integer;
begin
  B := Copy(A);
  SetLength(Z, Length(A));
  SetLength(π, Length(A));
  for i := 0 to High(Z) do
    Z[i] := i;
  for i := 0 to High(π) do
  begin
    π[i] := RandomFrom(Z);
    for j := 0 to High(Z) do
    begin
      if Z[j] = π[i] then
      begin
        for k := j to High(Z) - 1 do
          Z[k] := Z[k+1];
        SetLength(Z, length(Z) - 1);
        break;
      end;
    end;
  end;
  for i := 0 to High(A) do
    A[i] := B[π[i]];
end;

更快,但不太酷的方法就是随意交换项目,一次一对:

procedure FastPermuteArray(A: TDynIntegerArray);
  procedure Swap(n, m: integer);
  var
    tmp: integer;
  begin
    tmp := A[n];
    A[n] := A[m];
    A[m] := tmp;
  end;
var
  i: Integer;
begin
  for i := High(A) downto 1 do
    Swap(i, RandomRange(0, i));
end;

答案 1 :(得分:0)

尝试这样的事情:

uses
  System.Generics.Collections;

const
  ARRAY_ELEMENTS = 3;
var
  iArray: array of Integer;
  iIndex: TList<Integer>;
  I, j: Integer;
begin
  Randomize;

  SetLength(iArray, ARRAY_ELEMENTS);

  iIndex := TList<Integer>.Create;
  try
    iIndex.Count := ARRAY_ELEMENTS;
    for i := 0 to Pred(ARRAY_ELEMENTS) do
      iIndex[i] := i;

    for i := Low(iArray) to High(iArray) do
    begin
      j := Random(iIndex.Count);
      iArray[iIndex[j]] := i;
      iIndex.Delete(j);
    end;
  finally
    iIndex.Free;
  end;
end;

如果您的Delphi版本中没有TList<T>,则可以使用普通TList代替:

uses
  Classes;

const
  ARRAY_ELEMENTS = 3;
var
  iArray: array of Integer;
  iIndex: TList;
  I, j: Integer;
begin
  Randomize;

  SetLength(iArray, ARRAY_ELEMENTS);

  iIndex := TList.Create;
  try
    iIndex.Count := ARRAY_ELEMENTS;
    for i := 0 to Pred(ARRAY_ELEMENTS) do
      iIndex[i] := Pointer(I);

    for i := Low(iArray) to High(iArray) do
    begin
      j := Random(iIndex.Count);
      iArray[Integer(iIndex[j])] := i;
      iIndex.Delete(j);
    end;
  finally
    iIndex.Free;
  end;
end;