链表结点的删除
结点的删除分为两种情况:
(1)删除头结点。(需要改变头指针位置)
(2)删除中间,尾结点。(带删除结点的前驱必须有指针,将带删除结点的前驱与带删除结点的后继连起来)
例题1
设head指向一个非空单项链表,且数据域的值不重复,在链表中删除关键字值为key的结点。
分析:
第一步:查找值为key的结点(分为能找到和不能找到两种情况)
方法:for(p=h;p&&p->datakey;q=p,p=p->next);
解释:运用空循环,在p指向不为空且p指向的值不为key是循环继续,反之则跳出循环。
第二步:删除该结点
//如果p指向为NULL,则p遍历链表,未找到key值
if(pNULL)
printf(“未找到。\n”);
//如果p指向不为NULL,则找到了key值
else
{
if(p==head) //删除头结点,注意要返回头指针
else // 删除中间,尾结点
}
具体代码:
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
#define N 10
typedef struct Node
{
int data;
struct Node *next;
}Elensn;
//链表的建立
Elensn *initLink(int *a,int n)
{
int i;
Elensn *h=NULL,*tail;
h=tail=(Elensn*)malloc(sizeof(Elensn));
h->data=a[0];
h->next=NULL;
for(i=1;i<n;i++)
{
tail=tail->next=(Elensn*)malloc(sizeof(Elensn));
tail->data=a[i];
tail->next=NULL;
}
return h;
}
//输出链表
void printLink(Elensn* head)
{
Elensn* p;
for(p=head;p!=NULL;p=p->next)
printf("%d\t",p->data);
}
//核心代码,查找并删除key
Elensn* delsinglenode(Elensn* h,int key)
{
Elensn *p,*q;
for(p=h;p&&p->data!=key;q=p,p=p->next);//查找待删结点
if(p==NULL)//如果p跑到了链表末尾
printf("未找到key。\n");
else//如果找到了key所在结点
{
if(p==h)//如果为头结点
h=h->next;
else//如果为中加,尾结点
q->next=p->next;
free(p);//释放被删元素key所在结点
p=NULL;
}
return(h);
}
int main()
{
int a[N]={1,2,3,4,5,6,7,8,9,10},key;
Elensn * head;
head=initLink(a,N);
printf("请输出要删除的内容key\n");
scanf("%d",&key);
head=delsinglenode(head,key);
printLink(head);
return 0;
}
实现效果:
(1)当找到要删除值key值时:
(2)当未找到要删除值key时:
例题2
设head指向一个非空单项链表,并且数据域的值不重复,删除链表中的最大值结点
方法一:
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
#define N 10
//数据结构
typedef struct Node
{
int data;
struct Node *next;
}Elensn;
//创建链表
Elensn *initLink(int *a,int n)
{
int i;
Elensn *h=NULL,*tail;
h=tail=(Elensn*)malloc(sizeof(Elensn));
h->data=a[0];
h->next=NULL;
for(i=1;i<n;i++)
{
tail=tail->next=(Elensn*)malloc(sizeof(Elensn));
tail->data=a[i];
tail->next=NULL;
}
return h;
}
//链表的输出
void printLink(Elensn* head)
{
Elensn* p;
for(p=head;p!=NULL;p=p->next)
printf("%d\t",p->data);
}
//核心代码,删除最大值结点
Elensn* delmax(Elensn* head)
{
Elensn *p,*q,*pmax;
//寻找最大值结点,将pamx指针指向链表中的最大值结点
for(p=head->next,pmax=head;p;p=p->next)
//如果p所在结点值大于pmax所指向结点的值,则将pamx指向p所在结点
if(p->data>pmax->data)
pmax=p;
//两指针联动跑,寻找pamx结点所对应的前驱指针q
for(p=head;p&&p->data!=pmax->data;q=p,p=p->next);
if(p==head)//如果最大值结点为头结点
head=head->next;
else//如果最大值结点为中加,尾结点
q->next=p->next;
free(p);//释放最大值结点
p=NULL;
return(head);
}
int main()
{
int a[N]={15,1,2,3,4,5,6,8,9,7};
Elensn * head;
head=initLink(a,N);
head=delmax(head);
printLink(head);
return 0;
}
方法二:
相较于第一种方法,第二种方法更为简便,不用再次遍历链表找到pmax的前驱指针,而是在找到pamx指针的同时,寻找它的钱去指针qmax。
核心代码:
Elensn* delmax(Elensn* head)
{
Elensn *p,*q,*pmax=head,*qmax=NULL;
for(q=head,p=head->next;p;q=p,p=p->next)//寻找最大值及pmax,qmax
if(p->data>pmax->data)
{
pmax=p;
qmax=q;
}
if(pmax==head)
head=head->next;
else
qmax->next=pmax->next;
free(pmax);
pmax=NULL;
return(head);
}
实现效果:
当数据域中的值为15,1,2,3,4,5,6,8,9,7时,所要删除的最大值为头结点,输出结果为:
当数据域为1,2,3,4,5,6,8,9,7,15时,所要删除的结点为中加,尾结点时,输出结果为: