前言:
为什么链表的插入操作头结点一定要用指向指针的指针?之前自己对这个问题总是一知半解,今天终于花了点时间彻底搞懂了。
总的来说这样做的目的是为了应对“空链表”的情况。为了防止往一个空链表中插入一个结点时,新插入的结点那就是链表的头指针,这时如果链表的结点是一级指针的话,那么出了链表插入函数的作用域后,头结点又回到了原来的空值。
比如下面的一段程序
1 // 链表的头指针为什么是指向指针的指针.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include<iostream> 6 using namespace std; 7 8 struct Link 9 { 10 int data; 11 Link * next; 12 }; 13 void insert(Link *Phead,int data) 14 { 15 Link *pnew=new Link(); 16 pnew->data=data; 17 pnew->next=NULL; 18 if(Phead==NULL) 19 { 20 Phead=pnew; 21 } 22 } 23 int _tmain(int argc, _TCHAR* argv[]) 24 { 25 Link *Phead=NULL; 26 insert(Phead,2); 27 cout<<Phead->data; 28 return 0; 29 }
这就是因为第20行直接将新节点的值赋值给Phead,导致出了insert函数后,Phead又变成了NULL结点,而没有达到想要的指向新结点的效果。所以要把Phead设置成二级指针来传递或者在子函数中返回值才可以。
如果还是不太明白的话,那就先看看“函数是按值传递”的这方面的东西,函数按值传递的时候会拷贝一份实参的副本到形参中,而不是直接把实参赋给形参的。
如果对上面红字还是不理解可以看下面程序
1 // 为什么链表的插入操作头结点一定要用指向指针的指针_延续.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include<iostream> 6 using namespace std; 7 void function(int p) 8 { 9 p=5; 10 } 11 12 int _tmain(int argc, _TCHAR* argv[]) 13 { 14 int p=2; 15 function(p); 16 cout<<p; 17 return 0; 18 }
运行结果将会是2,而不是5。但是如果将p改成*p来传输,然后子函数中*P=5,结果才会变成5.