从链表a中找出与链表b相同的值并删除!

    算法:其实这和直接删除a链表中的某个节点类似,只是现在不是在删除一个节点,而是要与b链表先进行比较后再进行删除。首先先选取a中的第一个节点,从b中第一个开始找,找不到的话b就继续后移,b移到结尾还是未找到就说明b中任何一个没有与a中第一个节点相同,则a向后移动,以此类推。当有找到相同的节点时,情况1.此时a链表指向头结点,则只需要让头结点指向下一结点。情况2.不是头结点时只需要让a的前一个节点(pa2)的next指向pa1的next即可。情况3.如果是表尾,这个情况要考虑仔细了,假设现在b中找到了一个元素是与a中的最后一个节点相同,这时a中的指针情况应该是pa2指向倒数第二个节点(它始终是pa1的前驱,记录前一个走过的节点),而pa1指向末尾节点,则按照情况2的思路,有如下操作:pa2->next=pa1->next;而此时pa1->next为NULL(它是末尾么),所以还是满足情况2的,因此2,3情况可以合并,但是要注意循环的条件是while(pa1!=null),即pa1可以指向最后一个节点,但pa2不能指向最后一个节点,因为这时pa2的后继pa1就指向了下一个空节点了。

#include <stdio.h>
#include <string.h>
#define LA 5
#define LB 4
struct student 
{
	int num;
	char name[10];
	struct student *next;
}a[LA],b[LB];
void main()
{
	struct student a[LA]={{101,"zhang"},{102,"li"},{103,"wang"},{104,"niu"},{105,"liu"}};
	struct student b[LB]={{103,"zhu"},{105,"huang"},{106,"zhao"},{107,"qian"}};
	struct student *heada,*headb,*pa1,*pa2,*pb1;
	int i;
    heada=a;//指向a链表
	headb=b;//指向b链表
	//对链表a赋地址并且输出
	printf("a链表:\n");
	for (pa1=heada,i=1;i<=LA;i++)
	{	  
		if(i<LA)
		  pa1->next=a+i;
		else
			pa1->next=NULL;
		printf("%4d%8s\n",pa1->num,pa1->name);
		if(i<LA)
		pa1=pa1->next;
	}

	//对链表b赋地址并且输出
    printf("b链表:\n");
	for (pb1=headb,i=1;i<=LB;i++)
	{
		if(i==LB)
			pb1->next=NULL;
		else 
			pb1->next=b+i;
			printf("%4d%8s\n",pb1->num,pb1->name);
		if(i<LB)
			pb1=pb1->next;
	}
	//从a中找出与b相同的节点并且删除
	pa1=heada;//初始化指针
	while (pa1!=NULL)//只要链表a没有到结尾就执行
	{   pb1=headb;
		while((pa1->num != pb1->num) && (pb1->next!=NULL))//没有找到相等的值且b表没有到结尾
		{pb1=pb1->next;}//b表向后移动
		if (pa1->num==pb1->num)//找到了
		{
			if(pa1==heada)
			heada=pa1->next;//头结点直接指向下一结点
			else
			{
				pa2->next=pa1->next;//乍一看觉得pa2没有指向,但能进入这个else说明绝对有一次没有找到过,
				pa1=pa1->next;      //即pa1向后移动过,所以pa2是有所指的
			}
		}
		else
		{pa2=pa1;
         pa1=pa1->next;
		} 
	}
    //输出新表
	printf("现在a链表如下:\n");
	pa1=heada;
	while(pa1!=NULL)
	{
		printf("%4d%8s\n",pa1->num,pa1->name);
		pa1=pa1->next;
	}
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值