总结来说,是因为当增删的元素位置在链表首位时,如果传入的实参是头指针,相当于是把实参指向的结构的位置传入进来,让形参指向这个位置,那么当形参的指针指向发生变化时,最终实参还是指向它原来指向的位置。
顺便想想为什么在变化的节点不位于首位时,传入头指针是没问题的呢?因为形参指针与实参指针开始时指向同一位置,之后操作时,形参指针向后遍历,改变的是实参指向的链表的结构,因此当操作完成后,并不需要改变实参指针的指向,他指向的链表就是实现了我们要求的链表。
那为什么传入指向头指针的指针就能解决链表表头元素的增删问题呢?因为此时对形参(**pHead)解引用得到的是头指针,我们可以为它赋值,来改变传入的头指针的指向(*pHead = pNew ,因为**pHead = &p,所以*pHead = p,因此*pHead = pNew 就让p和pNew指向了相同位置)。
#include <iostream>
using namespace std;
struct ListNode
{
int data;
ListNode* pnext;
};
void addtotail(ListNode** pHead, int value)
{
ListNode* pNew = new ListNode();
pNew->data = value;
pNew->pnext = NULL;
if (*pHead == NULL)
{
*pHead = pNew;
}
else
{
ListNode* pNode = *pHead;
while (pNode->pnext != NULL)
pNode = pNode->pnext;
pNode->pnext = pNew;
}
}
void removenode(ListNode** pHead, int value)
{
if (*pHead == NULL)
return;
ListNode *pNode = *pHead;
if (pNode->data == value)
{
*pHead = pNode->pnext;
return;
}
while (pNode->pnext != NULL) {
if (pNode->pnext->data == value) {
pNode->pnext = pNode->pnext->pnext;
delete pNode->pnext;
return;
}
pNode = pNode->pnext;
}
}
int main()
{
ListNode* p = NULL;
addtotail(&p, 1);
addtotail(&p, 1);
addtotail(&p, 2);
addtotail(&p, 3);
removenode(&p, 1);
while (p != NULL)
{
cout << p->data << endl;
p = p->pnext;
}
return 0;
}