[英]Need help in understanding linked list code in C
typedef struct list_entry {
int val;
struct list_entry *next;
} list_entry;
list_entry **pp = &head; /* pointer to a pointer */
list_entry *entry = head;
while (entry) {
if (entry->val == to_remove)
*pp = entry->next; //6
pp = &entry->next; //8
entry = entry->next;
}
有人可以幫助您理解第6行和第8行嗎? 如果entry-> val == to_remove,則評估第6行,並且* pp成為移除后的下一個條目,那么第8行在那之后做什么? 當前條目已被刪除,如何在第8行中重復使用該條目?
另外,我知道* pp表示指針pp的值,&entry-> next表示pp的地址,我總是對何時應使用*和何時應使用*感到困惑。 具體來說,第6行可以是:
pp = &entry->next;
第8行是:
*pp= entry->next;
如果沒有,為什么?
更新:
博客中的代碼不完整,並假定將僅刪除一個元素,並且不需要免費。 如果要刪除兩個或多個連續元素,則序列中的第二個元素將不會刪除。
正確的代碼是,它還假定不必釋放節點:
while (entry) {
if (entry->val == to_remove)
*pp = entry->next;
else
pp = &entry->next;
entry = entry->next;
}
如果必須釋放節點:
while (entry)
{
if(entry->value == to_remove )
{
*pp = entry->next;
free( entry ) ;
entry = *pp ;
}
else
{
pp = &entry->next;
entry = entry->next;
}
}
編寫整個結構確實有助於理解這一點。
struct Node
{
int val ;
struct Node* next ; //hint, this has an address too.
} ;
訣竅在聲明中
pp = &entry->next ;
看起來您正在指向next
節點,但實際上,您僅使用當前節點的指針地址。 巨大差距!
所以pp = &entry->next ;
幾乎等同於prev = entry;
與第一個示例相比,唯一的區別是您指向當前struct Node
next
的成員的地址,而不是指向整個當前struct Node
。
在此示例代碼中,pp存儲前一個鏈的“下一個”成員的地址,以便在標記當前鏈為要刪除的情況下,可以修改前一個鏈的“下一個”成員以指向現在要刪除的鏈的“下一個”。 間接修改是通過應用*運算符完成的。
不能根據您的問題修改第6行和第8行,因為這樣代碼將無法達到預期的效果。
保留上一個(或頭)鏈的“下一個”成員的地址。
檢查當前鏈條是否標記為要移除。
如果使用pp引用間接操縱前一個鏈的“ next”成員指向當前鏈的“ next”,則實際上,鏈表將跳過當前鏈,同時保持其完整性。
這里發生了什么:
list_entry **pp = &head; /* pointer to a pointer */
list_entry *entry = head;
// we start with entry being head and pp being an address of head
while (entry) {
// while there is a list_entry which is not NULL...
if (entry->val == to_remove)
// if entry points to value that should be removed,
// then store the address of the next entry in whatever pp points to now
// (which effectively means removing that entry)
*pp = entry->next; //6
// pp is now an address of the next entry
pp = &entry->next; //8
// move to the next entry to start the next iteration
entry = entry->next;
}
這段代碼的作用:遍歷列表並消除所有標記為已刪除的條目。
怎么做的:
pp
最初指向頭部。
它從頭開始遍歷列表。
只要當前條目指向的值被標記為“已刪除”, pp
在當前列表條目的地址中存儲下一個列表條目的地址。 如果pp
指向head,則意味着head被丟棄,它開始指向下一個元素。 如果pp
指向列表中間的元素,則意味着該元素已刪除(因為現在,上一個元素將指向被刪除元素之后的元素)。
完成之后,它將移動entry
點以檢查列表中的下一個值。
&
表示返回某物的地址。 *
表示訪問指針所指向的變量。
所以這行:
pp = &entry->next;
*pp= entry->next;
是不同的。
第一個將指針設置為包含entry->next
的地址,第二個將pp
指向的變量的值設置為等於entry->next
。
“刪除” entry->next
之后可以引用entry->next
的原因是,當它從鏈接列表中刪除時,它仍然存在於內存中並且仍然可以訪問。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.