使用 Sentry 節點進行設計
設計連結串列時,可以使用 sentry 節點避免所有特殊情況(空列表,第一個節點,最後一個節點等)。讓我們看看如何做到這一點:
struct Node
{
Node* next;
Node* prev;
T data;
};
// helper function to link 2 nodes
void Link(Node* n1, Node* n2)
{
n1->next = n2;
n2->prev = n1;
}
// this inserts new data before 'here'
Node* Insert(Node* here, const T& data)
{
Node* item = new Node{0,0,data}; // create new item. use T's copy-constructor
Link(here->prev, item); // link in new node. item comes before here,
Link(item, here); // so in-between `here->prev´ and `here´
size += 1; // update size
return item;
}
// erase one item
Node* Erase(Node* here)
{
Node* nxt = here->next; // save next item for return value
Link(here->prev, here->next); // unlink item. no special cases needed when using sentry
delete here; // delete item. this will call T's destructor
size -= 1; // update size
return nxt;
}
例如,這似乎對於空列表會失敗,但是對於一個哨兵節點,列表永遠不會真正為空,它總是包含哨兵節點,如果沒有資料節點則連線到自身。哨兵節點也是過去最後一個標記的兩倍。
Node* sentry;
void Init()
{
sentry = (Node*)your_preferred_allocator();
Link(sentry, sentry);
size = 0;
}
可以在 https://pastebin.com/DXunz58Q 上找到更全面的教程