Have a look at the rmTreeNonView component in rmControls library. 
We've been using a modified version of that tree for years as a data container. It's free, fast, non-visual, comes with source code, and is easy to get started with because duplicates TTreeView's methods and properties almost 100%, plus adds some methods of its own--particularly, a fast hash-based search for tree node paths.
I doubt the company is in business any more (http://www.mills-enterprise.ca), but the rmControls package including source is available on many Delphi download sites.
EDIT:
Here's some code showing how to point to nodes in another tree structure from nodes of a VTV...hope I've included enough code to let you see what's going on. TmwDataTreeNode is a node of a TTreeNonView descendant. Note that when the PopulateVT method has completed, the ContextNode field of each TNodeData points to a node in the source data container tree. Note this approach does not make use of VTV's virtual nature, which might more likely be more appropriate for your situation.
type
      //Virtual tree record stuff
  PNodeData = ^TNodeData;
  TNodeData = record
  public
    NodeSelf: PVirtualNode;         //Ptr to our own VT node...needed?
    ContextNode: TmwDataTreeNode;        //ptr to our corresp node of data tree
    GridRecordIndex: integer;      //Grid.RecordIndex of our corresp Alloc formula.
  end;
procedure T_fmExplAllocOut.PopulateVT;
{ Load data to the DragDrop treeview. }
var
  n: TmwDataTreeNode;        //Pointer to a node of my customized TTreeNonView
begin
  VT.NodeDataSize := SizeOf(TNodeData);
  VT.BeginUpdate;
  vtsChangeFontSize(VT, Self.Font.Size);     //Set Tree Font.Size & DefaultNodeHeight
      //Add DragDrop Tree nodes
  n := AllocController.SnapContext.Tree.Items.GetFirstNode;
  while n <> nil do begin
    AddVTNode(nil, n);              //nil=parent node of top-level VT nodes
    n := n.GetNextSibling;
  end;
  VT.FullExpand;
  VT.EndUpdate;
end;
procedure T_fmExplAllocOut.AddVTNode(VTParentNode: PVirtualNode; n: TmwDataTreeNode);
{ Recursively add n & its children to VT. }
var
  NodeData: PNodeData;
  VTNode: PVirtualNode;
begin
  if (n = nil) or not NodeInIncludeFilter(n) then
    exit;
      //Add this node
  VTNode := VT.AddChild(VTParentNode);
  NodeData := VT.GetNodeData(VTNode);
  VT.ValidateNode(VTNode, False);        //else OnFreeNode won't get called
  with NodeData^ do begin
    NodeSelf :=         VTNode;
    ContextNode :=      n;
    GridRecordIndex := -1;
  end;
      //Add child nodes
  n := n.GetFirstChild;
  while n <> nil do begin
    AddVTNode(VTNode, n);            //Pass our added node as Parent
    n := n.GetNextSibling;
  end;
end;