2012-01-11 64 views
1

請,假設我有這個二叉樹結構:德爾福保存和載入二叉樹

Type 
    TPMyTree = ^TMyTree; 
    TMyTree = Record 
     ID:Integer; 
     FullName:String[50];//<-------- fixed 
     addrs:String[50] // <----------- fixed 
     LeftT:TPMyTree; 
     RightT:TPMyTree; 
    end; 

我怎麼能保存和從流加載它?

+1

http://stackoverflow.com/questions/3820996/delphi-2010-how-to-save-a-whole-record-to-a-文件 – 2012-01-11 13:16:52

+0

我提供了一個問題本身的答案,但不得不問:爲什麼你需要這樣做?如果你需要更多的練習,我建議用固定的東西(比如'string [number]')替換變長字符串,然後構建樹,這樣左右子節點不是實際的指針,而是指向一個大的緩衝。這樣你就可以一次讀寫整個索引,而不是一次一個節點。如果這種情況發生在大量節點上,請確保查看設計用於磁盤的樹形數據結構,如B-Tree。 – 2012-01-11 13:33:03

+0

是否要保存爲XML或文本格式或二進制格式?從你使用String [50]我得到你想要使用二進制格式的想法。我建議你根本不要使用二進制格式,而是保存爲文本格式。我意識到你更新了你的問題,因爲你給出的答案是「變長數據不容易處理二進制格式」。我會說,只是不要做二元格式。餿主意。 – 2012-01-11 23:44:03

回答

1

使用流時,最複雜的問題是處理可變長度的數據。在你的情況下,這是FullNameaddrs,因爲這些字段的類型是String。最簡單的解決方案是使用Delphi的流讀取器和寫入器幫助器類TReaderTWriter,因爲它們提供了使用字符串的簡單方法。其他原因是最明顯的解決方案是遞歸地將樹寫入流,一次一個節點。

警告,編寫的代碼在瀏覽器窗口中:

// This will save one node to the stream, using the TWriter helper. Takes 
// care of potential NIL's. 
procedure SaveBinaryTreeToStreamWriter(RootNode: TPMyTree; W: TWriter); 
begin 
    if Assigned(RootNode) then 
    begin 
     W.WriteBoolean(True); 
     W.WriteInteger(RootNode^.ID); 
     W.WriteString(RootNode^.FullName); 
     W.WriteString(RootNode^.addres); 
     SaveBinaryTreeToStreamWriter(RootNode^.LeftT, W); 
     SaveBinaryTreeToStreamWriter(RootNode^.RightT, W); 
    end 
    else 
    W.WriteBoolean(False); 
end; 

// This will read one NODE from the stream, using the TReader helper. 
// Uses the boolean "nil" marker saved by the writing routine to also 
// return "nil" if needed. 
function ReadBinaryTreeNodeFromReader(R: TReader):TPMyTree; 
begin 
    if R.ReadBoolean then 
    begin 
     Result := AllocMem(SizeOf(TMyTree)); 
     Result^.ID := R.ReadInteger; 
     Result^.FullName := R.ReadString; 
     Result^.addres := R.ReadString; 
     Result^.LeftT := ReadBinaryTreeNodeFromReader(R); 
     Result^.RightT := ReadBinaryTreeNodeFromReader(R); 
    end 
    else 
    Result := nil; 
end; 

// This simply creates the TWriter and then starts the recursive process of 
// writing the tree to stream. 
procedure SaveBinaryTreeToStream(RootNode: TPMyTree; Stream: TStream); 
var W:TWriter; 
begin 
    W := TWriter.Create(Stream, 128); 
    try 
    SaveBinaryTreeToStreamWriter(RootNode, W); 
    finally W.Free; 
    end; 
end;  

// This simply creates the TReader and then starts the recursive process of 
// reading the tree one node at a time: 
function ReadFromStream(Stream:TStream):TPMyTree; 
var R: TReader; 
begin 
    R := TReader.Create(Stream, 128); 
    try 
    Result := ReadBinaryTreeNodeFromReader(R); 
    finally R.Free; 
    end;  
end; 
+0

Now FullName和addrs具有固定大小 – Alexis 2012-01-11 15:45:30

+0

仍然是一個壞主意。你意識到String [50]意味着你現在正在存儲Ansi字符,其中多達50個,並且你存儲到該記錄的unicode字符(以unicode delphi版本)將不能存儲在你的String [50]領域。 (帶有字符類型AnsiChar的固定長度字段)。 – 2012-01-11 23:46:37