题目:有一个非空单链表list,每个结点中存放一个整型数据。 指针q指向链表中某一个结点,编写函数delLink,删除q指向的结点。本文讨论的链表不带头结点。
链表定义如下:
typedef struct node
{
ElemType data; //数据域
struct node *next; //指针域
}LNode, *LinkList;
分析:要删除单链表中的结点,最重要的是获取其前驱结点的指针。但此题中只给出了要删除的结点指针q,并不知道其前驱结点的指针,因此无法直接删除q指向的结点。因此需要通过一个循环来遍历链表,找到q的前驱结点,完成删除操作。算法代码描述如下:
/*这里应该是LinkList *list,而不是LinkList list,否则下面第6行对*list的修改无法在主函数中生效(LinkList list应该也是指针,修改为什么无法在主函数生效,暂时不理解)*/
void delLink(LinkList *list, LinkList q)
{
LinkList r;
if (q == *list)
{
*list = q->next; /*如果q指向的结点即为第1个结点,则需要修改list的值*/
free(q); /*释放被删除结点的空间*/
}
else
{
r = *list;
while ((r->next != q)&&(r->next != NULL))
{
r = r->next; /*通过循环找到q所指结点的前驱结点*/
}
if (r->next != NULL)
{
r->next = q->next; /*删除q所指向的结点*/
free(q); /*释放被删除结点的空间*/
}
}
}
该算法时间复杂度为O(n),算法测试用例如下:
#include <stdio.h>
#include <malloc.h>
typedef struct node
{
int data;
struct node *next;
}LNode,*LinkList;
LinkList GreatLinkList(int n)
{
/*建立一个长度为n的链表*/
LinkList p, r, list = NULL;
int e;
int i;
for (i=1;i<=n;i++)
{
scanf("%d",&e); /*获取链表结点中的数据元素*/
p=(LinkList)malloc(sizeof(LNode)); /*分配一个新的链表结点*/
p->data=e;
p->next=NULL;
if (list == NULL)
{
list = p; /*list指向第一个结点,list是头指针*/
}
else
{
r->next = p; /*将新结点连接到链表的尾部*/
}
r = p; /*指针r始终指向链表的最后一个结点*/
}
return list; /*返回链表的头指针*/
}
void delLink(LinkList *list, LinkList q)
{
LinkList r;
if (q == *list)
{
*list = q->next; /*如果q指向的结点即为第1个结点,则需要修改list的值*/
free(q); /*释放被删除结点的空间*/
}
else
{
r = *list;
while ((r->next != q)&&(r->next != NULL))
{
r = r->next; /*通过循环找到q所指结点的前驱结点*/
}
if (r->next != NULL)
{
r->next = q->next; /*删除q所指向的结点*/
free(q); /*释放被删除结点的空间*/
}
}
}
void printLink(LinkList list)
{
while (list != NULL)
{
printf("%3d",list->data); /*打印出每个结点中的数据data*/
list = list->next;
}
printf("\n");
}
main()
{
LinkList list, q;
int i;
q = list = GreatLinkList(10); /*创建包含10个元素的单链表,并初始化该链表*/
delLink(&list, q); /*删除q指向的结点*/
printLink(list); /*打印出链表中的内容*/
q = list;
for (i=0; i<4; i++)
{
q = q->next; /*指针q指向链表中第5个元素*/
}
delLink(&list, q); /*删除q指向的结点*/
printLink(list); /*打印出链表中的内容*/
getchar();
getchar();
}