Как использовать переменную, которая еще не инициализирована - PullRequest
3 голосов
/ 23 апреля 2020

Я пытаюсь создать узел, который имеет строку и массив узлов, но эти другие узлы еще не созданы, так как мне их использовать? Мне нужно будет получить доступ к ребрам конкретного узла позже в 'для всех ребер в узле' l oop. Это структура данных графа. График направлен, то есть узел A может иметь соединение с B, а B не имеет связи с A.

type
  TNode = record
    name: String;
    edges: TNodeArray;
    procedure Init(const aName: String; const aEdges: TNodeArray);
  end;
  TNodeArray = array of TNode;

procedure  TNode.Init(const aName: String; const aEdges: TNodeArray);
begin
  name := aName;  edges := aEdges;
end;

function NewNode(const aName: String; const aEdges: TNodeArray): TNode;
begin
  Result.Init(aName, aEdges);
end;

procedure Main;
var
  n0, n1, n2, n3: TNode;
begin
  n0 := NewNode('new york', TNodeArray.Create(n1, n2));
  n1 := NewNode('london', TNodeArray.Create(n2));
  n2 := NewNode('moscu', TNodeArray.Create(n1, n3));
  n3 := NewNode('other city', nil);  // 'other city' has no connections
end;

1 Ответ

1 голос
/ 23 апреля 2020

В комментариях выяснилось, что это ориентированный граф. Если это так, вы можете использовать что-то вроде этого:

type
  TNode = class
  strict private
    FName: string;
    FOutgoingArcs: TList<TNode>;
    function GetOutgoingArc(Index: Integer): TNode;
    function GetOutgoingArcCount: Integer;
  public
    constructor Create(const AName: string);
    procedure AddOutgoingArc(ANode: TNode);
    procedure AddOutgoingArcs(const ANodes: array of TNode);
    property OutgoingArcs[Index: Integer]: TNode read GetOutgoingArc;
    property OutgoingArcCount: Integer read GetOutgoingArcCount;
    property Name: string read FName write FName;
    destructor Destroy; override;
  end;

implementation

{ TNode }

procedure TNode.AddOutgoingArc(ANode: TNode);
begin
  FOutgoingArcs.Add(ANode)
end;

procedure TNode.AddOutgoingArcs(const ANodes: array of TNode);
var
  Node: TNode;
begin
  for Node in ANodes do
    AddOutgoingArc(Node);
end;

constructor TNode.Create(const AName: string);
begin
  FName := AName;
  FOutgoingArcs := TList<TNode>.Create;
end;

destructor TNode.Destroy;
begin
  FOutgoingArcs.Free;
  inherited;
end;

function TNode.GetOutgoingArcCount: Integer;
begin
  Result := FOutgoingArcs.Count;
end;

function TNode.GetOutgoingArc(Index: Integer): TNode;
begin
  Result := FOutgoingArcs[Index];
end;

Я также думаю, что это хорошо, чтобы отслеживать все узлы в одном списке, поэтому я бы сделал

var
  Nodes: TObjectList<TNode>;

function CreateNode(const AName: string): TNode;
begin
  Result := TNode.Create(AName);
  Nodes.Add(Result);
end;

Теперь мы можем играть (сначала создайте Nodes: Nodes := TObjectList<TNode>.Create(True{say})):

var
  NewYork,
  London,
  Paris,
  Moscow: TNode;
begin

  NewYork := CreateNode('New York');
  London := CreateNode('London');
  Paris := CreateNode('Paris');
  Moscow := CreateNode('Moscow');

  NewYork.AddOutgoingArc(London);
  London.AddOutgoingArcs([NewYork, Paris, Moscow]);
  Paris.AddOutgoingArcs([London, Moscow]);
  Moscow.AddOutgoingArc(NewYork);

Но, конечно, есть тысячи способов создать это. Это только одно возможное решение.

Обновление:

Обратите внимание, что существует только один объект с именем "Лондон", поэтому если вы измените это "через Париж", это будет видно "через Нью-Йорк":

Paris.OutgoingArcs[0].Name := 'The Capital of the United Kingdom';

Теперь

NewYork.OutgoingArcs[0].Name

также 'The Capital of the United Kingdom'.

Также обратите внимание, что с

Nodes := TObjectList<TNode>.Create(True)

узлы будут принадлежать списку объектов Nodes (это то, что означает True), поэтому они будут освобождены при освобождении Nodes. Так, например, если вы используете эти узлы в своем собственном классе TTravelPlanner, вы можете создать Nodes в TTravelPlanner.Create и сделать Nodes.Free в TTravelPlanner.Destroy.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...