What does it mean for a data structure to be "intrusive"?
I've seen the term intrusive used to describe data structures like lists and stacks, but what does it mean?
Can you give a code example of an intrusive data structure, and how it differs from a non-intrusive one?
Also, why make it intrusive (or, non-intrusive)? What are the benefits? What are the disadvantages?
Solution 1:
An intrusive data structure is one that requires help from the elements it intends to store in order to store them.
Let me reword that. When you put something into that data structure, that "something" becomes aware of the fact that it is in that data structure, in some way. Adding the element to the data structure changes the element.
For instance, you can build a non-intrusive binary tree, where each node have a reference to the left and right sub-trees, and a reference to the element value of that node.
Or, you can build an intrusive one where the references to those sub-trees are embedded into the value itself.
An example of an intrusive data structure would be an ordered list of elements that are mutable. If the element changes, the list needs to be reordered, so the list object has to intrude on the privacy of the elements in order to get their cooperation. ie. the element has to know about the list it is in, and inform it of changes.
ORM-systems usually revolve around intrusive data structures, to minimize iteration over large lists of objects. For instance, if you retrieve a list of all the employees in the database, then change the name of one of them, and want to save it back to the database, the intrusive list of employees would be told when the employee object changed because that object knows which list it is in.
A non-intrusive list would not be told, and would have to figure out what changed and how it changed by itself.
Solution 2:
In a intrusive container the data itself is responsible for storing the necessary information for the container. That means that on the one side the data type needs to be specialized depending on how it will be stored, on the other side it means that the data "knows" how it is stored and thus can be optimized slightly better.
Non-intrusive:
template<typename T>
class LinkedList
{
struct ListItem
{
T Value;
ListItem* Prev;
ListItem* Next;
};
ListItem* FirstItem;
ListItem* LastItem;
[...]
ListItem* append(T&& val)
{
LastItem = LastItem.Next = new ListItem{val, LastItem, nullptr};
};
};
LinkedList<int> IntList;
Intrusive:
template<typename T>
class LinkedList
{
T* FirstItem;
T* LastItem;
[...]
T* append(T&& val)
{
T* newValue = new T(val);
newValue.Next = nullptr;
newValue.Prev = LastItem;
LastItem.Next = newValue;
LastItem = newValue;
};
};
struct IntListItem
{
int Value;
IntListItem* Prev;
IntListItem* Next;
};
LinkedList<IntListItem> IntList;
Personally I prefer intrusive design for it's transparency.