链表中的二级指针
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
指针是比较绕的东西,尤其是链表中的二级指针。
一、什么时候使用?
头插法建表、尾插法建表、链表的初始化操作、链表的销毁操作我们需要使用二级指针。
链表的销毁必须要用,那三种可用可不用,需要看你写啥代码。
二、详解
1.头插法
//头插法建表 正确代码
bool createListHead(LNode **list,ElemType content[],int len){
*list = (LNode *)malloc(sizeof(LNode));
(*list)->next = null;
for(int i = 0;i<len;i++){
LNode *s =(LNode *) malloc(sizeof(LNode));
s->data = content[i];
s->next = (*list)->next;
(*list)->next = s;
}
return true;
}
//这是错误代码
bool createListHead(LNode *list,ElemType content[],int len){
list = (LNode *)malloc(sizeof(LNode));
list->next = null;
for(int i = 0;i<len;i++){
LNode *s =(LNode *) malloc(sizeof(LNode));
s->data = content[i];
s->next = list->next;
list->next = s;
}
return true;
}
这个头插法建表使用了指针。为什么错误?请听我细细道来。
当一个函数执行时,临时变量(list)存在栈中,数值会存储在堆区中。执行完毕后,临时变量(list)会被释放掉。
这时你该想了?list被释放掉关我head什么事?确实不关head事,可是list后面接了那么多的节点,关head什么事?有点绕,不急,看不懂没关系。
首先,咱们传入head是用LNode *list接的。说白了就是地址拷贝,此时head(0x111)与list(0x111)地址一样。
然后,咱们给list用malloc申请内存,此时地址可变化了!list地址变成0x112
咱用变化后的地址(0x112)给它接上一群小可爱
,函数执行完后,这个地址(0x112)被释放掉,那群小可爱就群龙无首了,跟head(0x111)一点关系都没有。
LNode* ListCreateListByHead(int n, int* a) {
LNode* head = NULL, * vtx;
while (n--) {
vtx = ListCreateNode(a[n]);
vtx->next = head;
head = vtx;
}
return head;
}
这个代码是正确的,虽然没有使用双指针,它返回的是地址,不会出现群龙无首现象,这个代码好理解,自己好好看看吧!!!
2.链表删除
void ListDestroyList(Node ** pHead) { //这里必须用二级指针,因为删除后需要将链表头置空,普通传参无法影响外部变量;
Node*head = *pHead;
while(head) {
head = ListDeleteNode(head, 0);
}
*pHead = NULL;//不制空的话会变成野指针
cout << "释放成功!" << endl;
}
//一级指针,错误代码
void destoryList(LNode *head1){
if(head1 == null){
printf("该链表已经销毁,请勿重复销毁\n");
return;
}
while(head1->next!=null){
LNode *p = head1->next;
head1->next = p->next;
free(p);
}
free(head1);
head1 = null;
}
说一下一级指针为啥错哈!首先,确实能够删除节点哈。不过,删除节点后,head1是NULL,那么原来的head指向啥?head与head1是两个东西,你把head的儿子都放跑了,head此时啥也不指,此时变成了野指针。
双指针的目的就是把head指向NULL即可,其实双指针不难,不就在单指针的基础上多加一个*吗?
总结
没啥总结,有些东西找到网上的,如果侵权,请联系我。