利用二级指针快捷的删除单链表
单链表的删除
代码
#include<stdio.h>
#include<stdlib.h>
/* 单链表 */
typedef struct linkNode
{
int val;
struct linkNode *next;
} linkNode, *linkList;
linkList createLink(linkList head,int x)
{
if(head==NULL)
{
head=(linkNode*)malloc(sizeof(linkNode));
head->next=NULL;
head->val=x;
return head;
}
linkList tail=head;
while(tail->next)//链表尾插法
tail=tail->next;
linkList temp=(linkNode*)malloc(sizeof(linkNode));
temp->next=NULL;
temp->val=x;
tail->next=temp;
return head;
}
/*linkNode** getPtr(linkList head,int x)
{
linkList tail=head;
while(tail->val!=x&&tail!=NULL)
tail=tail->next;
return &(tail->next);
}*/
linkList deleteNode(linkList head,int x)
{
if(head==NULL)
return head;
if(head->val==x)
{
linkList temp=head;
head=head->next;
free(temp);
return head;
}
linkList temp=head;
while(temp->next->val!=x&&temp->next->next!=NULL)
temp=temp->next;
if(temp->next==NULL)
return head;
linkList cur=temp->next;
temp->next=cur->next;
free(cur);
return head;
}
void newDeleteNode(linkList *head,int x)
{
linkList cur=*head;
while(cur->val!=x&&cur!=NULL)
{
head=&(cur->next);
cur=*head;
}
if(cur!=NULL)
(*head)=(*head)->next;//(*head)=cur->next;
free(cur);
}
void printLink(linkList head)
{
while(head)
{
printf("%d ",head->val);
head=head->next;
}
printf("\n");
}
int main()
{
int i=0;
linkList head=NULL;
for(;i<10;i++)
{
head=createLink(head,i);
}
printLink(head);
deleteNode(head,4);
printLink(head);
newDeleteNode(&head,6);
printLink(head);
return 0;
}
分析
在上面我实现了两个单链表的删除函数deleteNode和newDeleteNode,deleteNode函数是最常见的单链表结点删除函数。
而newDeleteNode巧妙的应用了二级指针达到了删除结点的功能。
针对deleteNode函数想要删除一个结点,必须要知道结点的前驱A,结点本身B;如果B不是head结点,则A->next=B->next;free(B);
若B是head结点,则A=head;head=head->next;free(A);
函数有可能会改变head的指向,由于函数中改变的是传递的head的副本所以必须再次返回head;
而 newDeleteNode巧妙的利用地址传值的特点。首先传递给newDeleteNode的参数head是原链表head的地址(&head)。
删除结点遍历时,每次都有head=&(A->next);
。而我们删除结点是主要操作是A->next=B->next;
则A->next=(*head);B->next=(*head)->next;
则 (*head)=(*head)->next;
这样就可省去判断要删除的节点是否是头节点。而且由于是地址传值所以即使改变了头节点也无需重新返回。 最重要的是理解 在newDeleteNode函数中遍历的时候 head每次被赋予的值是当前结点中 next 指针变量的地址