上一篇中我们提到了单链表头指针的创建
如果链表为空时,头指针为NULL。接下来要实现节点的插入和删除。
在链表头部插入新节点,因此头指针指向的地址也应发生改变,即指向新节点的地址,因为在此时新节点就是头节点。此时我们就该考虑传参的问题。
我们先来看头指针是如何创建的
#include<stdio.h>
typedef int SLTDateType;
typedef struct SListNode
{
SLTDateType data;
struct SListNode* next;
}SListNode;
int main() {
SListNode* plist = NULL;
return NULL;
}
此处的plist就是头指针,并且此时链表为空
在此时我们在主函数中创建一个新节点,data为1。如下图:
int main() {
SListNode* plist = NULL;
SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
newnode->data = 1;
return NULL;
}
这时我们需要想一想如何把新节点链接到链表中?
显而易见,我们需要把新节点的next,即newnode下一个指针的地址置为空,并且使plist的值改为新节点的地址就ok了。
int main() {
SListNode* plist = NULL;
SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
newnode->data = 1;
newnode->next=plist;
plist=newnode;
return NULL;
}
plist由NULL变为newnode
从上述代码中,我们可很明显的感觉到,plist的值发生了改变,它由NULL变为新节点的指针newnode;接下来我们要求一个函数来实现链表的头插,显然这个函数必须要传入头指针(因为只有知道链表的头指针,我们才能找到完整的链表,正像上一篇我们说到链表的头指针是无论如何也不能丢失的)和头插的数据。但是此时就需要我们好好想想-------如果把plist传过去,是否会达到预期的结果?认真想一想,假设我们把plist传过去,用p来接受,会不会达到预想的结果?
void SLFrontPush(SListNode* p, int x) {
}
我们在上一步的基础上,在SLFrontPush函数中把p置为NULL;看一看会不会对plist有什么影响?
void SLFrontPush(SListNode* p, int x) {
p == NULL;
}
int main() {
SListNode* plist = NULL;
SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
newnode->data = 1;
newnode->next = plist;
plist = newnode;
printf("%p\n", plist);
SLFrontPush(plist, 0);
printf("%p\n", plist);
return NULL;
}
对操作前和操作后的地址分别进行打印
结果是前后打印出的plist值没有发生改变。即把plist传到函数中,对形参p进行操作是不会对主函数中的plist值发生改变的。为什么会这样呢?我们知道函数的形参实际上是对实参的一份临时拷贝,拷贝的内容是实参的内容,只不过是把相同的内容放到了不同的地址上。
我们改变p时,把p置为NULL时,实际上是在SLFrontPush函数中在p开辟的空间上,对p的值进行改变,并不会影响到main函数中plist的值。我们也就无法使头指针指向新节点的地址。那我们该如何实现对plist的改变呢?
在开头时,我们实现了对头指针的成功改变。我们是怎么实现的呢?
对,我们是直接把plist拿过来进行操作的,也就是说如果我们能在函数中知道plist的地址,那么我们就可以通过它的地址,对它地址上存储的数据进行改变。而它地址上存储的数据正是头指针!
那么显而易见:我们需要传plist的地址即形参为SListNode**p,实参为&plist。
代码:
void SLFrontPush(SListNode** p, int x) {
*p = NULL;
}
int main() {
SListNode* plist = NULL;
printf("%p\n", &plist);
plist = (SListNode*)malloc(sizeof(SListNode));
printf("%p\n", plist);
SLFrontPush(&plist,0);
printf("%p\n", plist);
return NULL;
}
结果:
.