2011-03-18 17 views
0

總結:如何交換兩維數組的兩行,爲什麼它會工作?

請檢查大衛,Uwe和其他專家下面的評論。

============================================== ==================================

下面的代碼交換在二維兩行,雙值的動態數組。我想知道:(1)以下代碼是否是交換兩維數組的兩行的最佳做法?如果不是,那麼做這種工作的最佳做​​法是什麼? (2)爲什麼下面的代碼有效?我的意思是,不是二維數組一個 連續 連續的內存部分?下面的代碼是否只能運氣?任何建議表示讚賞!

unit Unit5; 

    interface 

    uses 
     Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
     Dialogs; 

    type 
     TAADouble = array of array of Double; 

     TForm5 = class(TForm) 
     procedure FormShow(Sender: TObject); 
     private 
     { Private declarations } 
     public 
     { Public declarations } 
     end; 

    var 
     Form5: TForm5; 

    procedure SwapRows(arr: TAADouble; row0, row1: Integer); 

    implementation 

    {$R *.dfm} 

    procedure SwapRows(arr: TAADouble; row0, row1: Integer); 
    var 
     Tmp: Integer; 
    begin 
     {$IFDEF FPC} 
     Tmp := PtrUInt(arr[row0]); 
     PtrUInt(arr[row0]) := PtrUInt(arr[row1]); 
     PtrUInt(arr[row1]) := Tmp; 
     {$ELSE} 
     Tmp := Integer(arr[row0]); 
     Integer(arr[row0]) := Integer(arr[row1]); 
     Integer(arr[row1]) := Tmp; 
     {$ENDIF} 

    end; 

    procedure TForm5.FormShow(Sender: TObject); 
    var 
     tmpArray: TAADouble; 
     I, J: Integer; 
     rowStr: string; 
    begin 
     SetLength(tmpArray, 10, 10); 
     rowStr := ''; 

     for I := 0 to 9 do 
     for J := 0 to 9 do 
      tmpArray[I][J] := I * J; 

     for I := 0 to 9 do 
     begin 
     rowStr := ''; 
     for J := 0 to 9 do 
      rowStr := rowStr + FloatToStr(tmpArray[I][J]) + ' '; 
     OutputDebugString(PWideChar(rowStr)); 
     end; 

     SwapRows(tmpArray, 3, 4); 

     for I := 0 to 9 do 
     begin 
     rowStr := ''; 
     for J := 0 to 9 do 
      rowStr := rowStr + FloatToStr(tmpArray[I][J]) + ' '; 
     OutputDebugString(PWideChar(rowStr)); 
     end; 
    end; 

    end. 
+1

雖然上述作品(目前),鑄造一個指向整數並不安全 - 這將在64位版本到達時慘敗......如果您使用的是最新的Delphi,請使用NativeInt類型,否則請自行定義您自己的設置,以便自己匹配指針大小。 – 2011-03-18 22:45:24

回答

4

你問:

只有 運氣是否將下面的代碼工作?

嗯,是的,你是依靠實施的具體細節。

事實上把它寫正確的做法是完全自然而簡單:

type 
    TDoubleArray = array of Double; 
    TDoubleMatrix = array of TDoubleArray; 

procedure SwapRows(M: TDoubleMatrix; Row1, Row2: Integer); 
var 
    Temp: TDoubleArray; 
begin 
    Temp := M[Row1]; 
    M[Row1] := M[Row2]; 
    M[Row2] := Temp; 
end; 

你需要聲明一箇中間類型的行,TDoubleArray,這樣就可以在交換進行到臨時分配常規。

二維恆定尺寸數組

array [1..M] of array [1..N] of TMyType 

是一個連續的內存塊。

二維動態尺寸數組你有不是。事實上,它甚至可以是粗糙的,因爲行具有不同數量的列。所以你可以有一個三角矩陣。

+0

@David:很高興知道'2D恆定大小的數組是連續的內存塊。一個2D動態大小的數組,如你所擁有的不是。事實上,它甚至可以是粗糙的,因爲行數有不同的列數。「非常感謝您的幫助! – SOUser 2011-03-18 11:11:13

+0

@David:但是,是否有必要爲'TDoubleMatrix'設置'var'前綴?我的意思是,如果'var'前綴不存在,我應該期待奇怪的錯誤嗎? – SOUser 2011-03-18 11:12:03

+1

@Xichen不,它不是。我想這是出於習慣。沒有它,它會很好地工作。我不覺得有沒有令人信服的理由去做或不做這個變種,這只是我的習慣。 – 2011-03-18 11:14:09

4

一個動態數組被實現爲一個指針表示陣列的存儲器塊。所以二維動態數組實際上是一個指向數組指針的指針。這就是爲什麼交換行( - 指針)實際上工作。

見大衛的回答更清潔的方式。

更新: 如果你被允許使用仿製藥,你不妨這樣做:

procedure <SomeClassOrRecord>.SwapRows<T>(var arr: TArray<T>; row0, row1: Integer); 
var 
    Tmp: T; 
begin 
    Tmp := arr[row0]; 
    arr[row0] := arr[row1]; 
    arr[row1] := Tmp; 
end; 
+0

@Uwe:非常感謝您的寶貴意見! – SOUser 2011-03-18 11:14:17

+0

@David:你能幫忙評論一下你的意思嗎?如果行的引用計數不同,它將不起作用。 – SOUser 2011-03-18 11:48:48

+1

@Xichen不,我感到困惑,那個陳述是不正確的。 – 2011-03-18 11:50:59

相關問題