You can create a class like this:
enum NodeType
{ Node, Output };
class TreeElement
{
NodeType myType;
union
{
Node myNode;
Output myOutput;
} NodeVariant;
};
The Node
and Output
classes are taken from your listing. The difference is that the Node
class can contain a list of TreeElement
instances. This list represents the element's children.
The Composite pattern might be quite useful here. You can implement nodes as a sort of container which holds outputs or node objects again. In the link you'll see more code snippets as implementation hint.
Create a Node class which has a value and an array of siblings. The array of siblings may be empty in which case it is a value node. The value may be null in which case it is a joint.
Seems you should really need more freeform structure than a tree. Each node can have a number of nodes connected to it; each connection has a direction. Any node can have input or output attached. Enforcing no circular connections and only one input would be up to you upon tree creation and update.
The structures could be multiply linked lists and go like this:
struct Node {
NodeContentType type; //Input, Output, None.
InOutNode* content; //pointer to input or output
Link* links; //pointer to first connection (if any), NULL if none.
}
struct Link {
Node* node; //node this connection links to.
Link* next; //pointer to next connection
}
Example tree:
INPUT
|
root
|
branch1---leaf2---output2
|
leaf1
|
output1
could go like this: (order is obviously wrong...)
Node root = { Input, &input_function, &link1 };
Link link1 = { &branch1, NULL };
Node branch1 = { None, NULL, &link2 };
Link link2 = { &leaf1, &link3 };
Link link3 = { &leaf2, NULL };
Node leaf1 = { Output, &output_function1, NULL };
Node leaf2 = { Output, &output_function2, NULL };