[英]linked list adding to the tail, confusion
Visual Studio 2008 C
我無法理解的這個鏈表是在if語句的else部分添加尾部。
當分配頭部和尾部時,node_temp的內存地址同時指向tail和head都指向相同的內存位置。
但是,在else部分中,頭部實際上仍然指向尾部。 有些東西我無法解釋,也不了解其他部分?
我希望有人能為我解釋得更好。
static struct convert_temp
{
size_t cel;
size_t fah;
struct convert_temp *next;
} *head = NULL, *tail = NULL;
/** Add the new converted temperatures on the list */
void add(size_t cel, size_t fah)
{
struct convert_temp *node_temp = NULL; /* contain temp data */
node_temp = malloc(sizeof(*node_temp));
if(node_temp == NULL)
{
fprintf(stderr, "Cannot allocate memory [ %s ] : [ %d ]\n",
__FUNCTION__, __LINE__);
exit(0);
}
/* Assign data */
node_temp->cel = cel;
node_temp->fah = fah;
node_temp->next = NULL;
if(head == NULL)
{
/* The list is at the beginning */
head = node_temp; /* Head is the first node = same node */
tail = node_temp; /* Tail is also the last node = same node */
}
else
{
/* Append to the tail */
tail->next = node_temp;
/* Point the tail at the end */
tail = node_temp;
}
}
第一次將一個元素(讓我們稱之為A
)添加到列表中時, head
為null,然后通過if
部分。 這意味着在添加第一個元素時, head
和tail都設置為指向A
現在讓我們添加另一個元素B
這次, head
不為null,因此它通過else
部分,將tail
設置為指向B
但是將head
指向A
這是預期的,你現在有head
指向A
, A
指向B
, B
指向空(null), tail
指向B
讓我們一步一步來。
Initial state: head -+-> null
|
tail -+
Insert item A: head -+-> A ---> null
|
tail -+
Insert item B: head ---> A -+-> B ---> null
|
tail --------+
Insert item C: head ---> A ---> B -+-> C ---> null
|
tail ---------------+
您可以在每個階段(除了初始階段)看到當前尾部被設置為指向新節點(其下一個節點已經指向NULL),然后尾部指針被更新為指向新的最后一個節點。
事實上,讓我們更詳細地逐行添加C(逐行),這樣你就可以看到每行代碼在做什么(為了幫助格式化,我將node_temp
重node_temp
為node
):
Starting state: head ---> A -+-> B ---> null
|
tail --------+
node = malloc(sizeof(*node)); node ---> C ----------> ?
(allocate node C) head ---> A -+-> B ---> null
|
tail --------+
node->next = NULL; node ---> C --------+
(ignore payload cel/fah |
for now since it's not head ---> A -+-> B -+-> null
relevant to the list |
structure) tail --------+
tail->next = node; node ---------------+
(first in else clause) |
head ---> A -+-> B -+-> C ---> null
|
tail --------+
tail = node; node ---------------+
(second in else clause) |
head ---> A ---> B -+-> C ---> null
|
tail ---------------+
然后最終node
消失,因為它是一個局部變量,你有最終狀態:
head ---> A ---> B -+-> C ---> NULL
|
tail ---------------+
在單鏈表中維護tail
指針的優點是避免在嘗試將項添加到最后時遍歷整個列表以找到結尾。
遍歷整個列表使得最后插入O(n)
時間操作(所花費的時間取決於列表中的項目數)。 tail
指針的使用使得O(1)
時間操作(與列表大小無關的相同時間量)。
順便說一下,雙向鏈表對tail
指針有額外的用處 - 它能夠快速開始從列表末尾到開始的遍歷,使用tail
和代替head
的prev
指針和next
指針。
else-part只是更新列表的tail
,因為當你附加到鏈表時,head不會改變。
保持指向緩沖區尾部元素的指針是一種優化,因此您不必在每個追加頭上從頭部逐步執行整個列表。
並不是頭部仍指向尾巴。 頭指向前尾巴。 當列表只包含一個元素時,它既是頭部也是尾部。 附加新節點后,尾指針已更新。 頭指針仍然指向第一個節點,這是正確的。
在第一次調用add時,head和tail將指向新創建的內存塊。 所有后續的add調用都會通過else部分進行調整,這只會改變尾部指針,基本上修改舊的tail-> next指向新的內存塊,然后更新tail也指向這個新的內存塊。
這是一種有效的追加方式。 如果只使用了head,那么每次添加一個新的node_temp時,你必須從頭開始遍歷所有下一個指針,直到你到達之前添加的node_temp(其下一個指針為NULL),然后添加新節點。 這將是O(n)算法,而不是上面的O(1)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.