爲了插入到僅存儲頭部的列表的背面,無尾(這將意味着一個小列表,其中線性時間插入是可接受的),可以通過將額外的指針間接消除做到這一點特殊情況:
簡易版(指向指針的指針到節點)
void List::push_back(int value)
{
// Point to the node link (pointer to pointer to node),
// not to the node.
Node** link = &head;
// While the link is not null, point to the next link.
while (*link)
link = &(*link)->next;
// Set the link to the new node.
*link = new Node(value, nullptr);
}
...這可以減少只是:
void List::push_back(int value)
{
Node** link = &head;
for (; *link; link = &(*link)->next) {}
*link = new Node(value, nullptr);
}
至於反對,說:
複雜的版本(指向節點)
void List::push_back(int value)
{
if (head)
{
// If the list is not empty, walk to the back and
// insert there.
Node* node = head;
while (node->next)
node = node->next;
node->next = new Node(value, nullptr);
}
else
{
// If the list is empty, set the head to the new node.
head = new Node(value, nullptr);
}
}
還是要公平,刪除註釋:
void List::push_back(int value)
{
if (head)
{
Node* node = head;
for (; node->next; node = node->next) {}
node->next = new Node(value, nullptr);
}
else
head = new Node(value, nullptr);
}
沒有特定的情況簡單版
主要的原因第一個版本沒有特殊情況下,空列表是因爲如果我們想象head
爲空:
Node** link = &head; // pointer to pointer to null
for (; *link; link = &(*link)->next) {}
*link = new Node(value, nullptr);
然後for
循環條件是立即假的,然後我們分配新節點head
。當我們使用指向指針的指針時,我們不必在循環外單獨檢查該情況。
插入排序
如果你想要做一個插入排序,而不是簡單地插入到後面,那麼這樣的:
void List::insert_sorted(int value)
{
Node** link = &head;
for (; *link && (*link)->value < value; link = &(*link)->next) {}
// New node will be inserted to the back of the list
// or before the first node whose value >= 'value'.
*link = new Node(value, *link);
}
性能
至於性能,不確保消除額外的分支會有很大的區別,但它確實使代碼更緊密並減少了複雜度。 Linus認爲這種風格是「好品味」的原因是因爲在C語言中,經常需要編寫鏈表列表邏輯,因爲它不是那麼容易,而且一定值得推廣鏈表,因爲我們在那裏沒有類模板,所以它就是方便地支持更小,更優雅,更不容易出錯的方式來編寫這些東西。再加上它表明你很好地理解指針。
你能鏈接程序代碼嗎? – Thomas
@Thomas不,請不要鏈接到代碼。 OP應該在他們的問題中提供一個[MCVE]。 –
是的,我添加了一個示例代碼請現在檢查 –