I think the best approach in this case is to use a pre-distributed doubly linked list ...
// Untested code... just to give the idea struct Node { int data; Node *prev, *next; static Node *first, *last, *free; // Allocates a new node before the specified node or // at the end of the list if before is NULL static Node *alloc(int data, Node *before) { // Check the free list first Node *n = free; if (!n) { // There are no free nodes... allocate a bunch of them Node *page = new Node[1000]; for (int i=0; i<999; i++) { page[i].next = &page[i+1]; } page[999].next = NULL; n = free = &page[0]; } // Update the free list free = n->next; // Link the new node to neighbors n->next = before; n->prev = before ? before->prev : last; if (n->prev) n->prev->next = n; else first = n; if (n->next) n->next->prev = n; else last = n; // Initialize it n->data = data; return n; } // Deallocates a node, placing it in the free list for reuse static dealloc(Node *n) { if (n) { // Remove from double chain if (n->next) n->next->prev = n->prev; else last = n->prev; if (n->prev) n->prev->next = n->next; else first = n->next; // Add to free list n->next = free; free = n; } } };
If you need to select node only call Node::alloc , passing the data and where to put the node. When you need to free it, just call node dealloc.
Nodes are highlighted on the "pages" and reused after release. This minimizes the number of calls in the memory manager and can significantly speed up the work.
In a doubly connected structure, you will never need to move an existing node while it is in memory (so no pointers will need to be configured). It is also easy to change the order of elements, for example, add the Node::moveTo(Node *before) method.
The disadvantage of this approach is that to access the nth element, this index is an O (n) operation.
source share