Understanding how Grasshopper handles data is crucial for taking full advantage of GH’s capabilities. For collections of data, they can either be in the form of lists or trees.
A list is a collection of items of data, in a particular order, but with no hierarchical structure. Here is a list of numbers:

The component in the top-right is the param viewer. Double click it to see this:

The ‘N’ denotes a list with N items. A list can be thought of as a tree with a single branch {0}. So here, we are looking at a single list, with address {0}, containing 5 items.
A tree is any data structure in GH with multiple branches. In other words, it’s a data structure with multiple lists. Each list has its own address.
Now, let’s make a grid of points. We can do this with our list of numbers and the ‘construct point’ component.

Here, we have cleverly grafted the Y input to coerce Grasshopper into giving us 25 points for our list of 5 numbers. But the output looks a little different. Instead of a list of 25 points, we have 5 groups of 5 points each.
What’s happened here is that Grasshopper has created 5 branches. Each branch contains a list of 5 points. Each branch has its own address {0} to {4}, shown in the panel.
We can verify this using the param viewer.

Trees in C#
Trees can be created and manipulated in C# components too. When we add data to a tree in C#, we need two pieces of information:
- The data we are saving, such as a Point3d or an integer
- The path we are saving to
The path is declared as a list of numbers denoting the sequence of the branches needed to access the list we are interested in. As some examples:
DataTree<Point3d> myTree = new DataTree<Point3d>();
GH_Path pth = new GH_Path(2);
myTree.Add(P, pth);
point P will be written to the list at the end of branch 2.
GH_Path pth = new GH_Path(i,j)
point P will go down branch i, then be added to the list at the end of branch j
Setting up a tree
You can either add to a tree on the fly – if you know that the data in the tree will be in the same order that you’ll be adding to it. But a more flexible way is to create a blank tree of the size you want, and then edit the values later.
Setting up a tree called boolTree (I am creating a tree based upon another tree called pts):
//declare tree
DataTree<bool> boolTree = new DataTree<bool>();
//set up tree
for(int i = 0; i < pts.BranchCount;i++)
{
GH_Path pth = new GH_Path(i);
for (int j = 0; j < pts.Branch(0).Count;j++)
{
boolTree.Add(false, pth);
}
}
This has now created a tree filled with ‘false’.
Editing values in the tree
boolTree.Branch(1,2)[5] = true;
This edits the 5th value of the list at the end of branch 1, sub-branch 2 to ‘true’.