[数据结构]集合的操作(链表)

本文介绍了一种基于链表的集合操作算法,包括排序、合并、减法和元素查询等核心功能。通过一系列步骤,如升序排序、合并、删除重复元素、减法操作以及查询和更新集合A,实现了对集合的有效管理和数据处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

集合的操作

问题描述 :

输入A、B、C、D四个集合(集合中无重复元素,且元素值都大于0),分别存储在不带头结点的链表中。

本程序先将四个集合执行以下操作:

1.对A、B、C、D分别进行升序排序;(该功能已实现,见函数sort)。

2.做A=A+B操作:先执行两个有序链表A和B的合并,并仍然保持有序,结果存储在A中,然后删除重复元素;(该功能已实现,见函数merge和purge)。

3.做A=A-C操作:将C中出现的元素从A中删除;(该功能已实现,见函数subtract)。

4.对D中出现的元素,逐一到A中查询:

如果在A中存在,则从A中删除

如果在A中不存在,则将元素添加到A中,并保持链表A有序。

请编写函数fun的函数体实现本功能。

5.输出集合A中的元素。(该功能已实现,见函数displayLink)。

需要编写的函数的原型如下:

struct student* fun(struct student* L1, struct student* L2)

输入说明 :

首先输入一行,包含一个整数N,表示共测试N组数据。

后面接着输入4*N行,每行为一个集合的元素。

每组数据的第1行为集合A的元素,第2行为集合B的元素,第3行为集合C的元素,第4行为集合D的元素。

每个集合的元素值都为大于0的整数,输入时,-1表示结束。

输出说明 :

输出的信息以head开头,以tail结尾,以“–>”分隔。如果是空链表,则直接输出“head–>tail”。具体见输出范例。

输入范例 :

2
3 5 8 10 15 9 -1
2 5 8 11 14 -1
2 5 10 -1
3 1 9 -1
3 5 8 10 15 9 -1
2 5 8 11 14 -1
2 5 10 -1
2 3 8 -1

输出范例 :

head–>1–>8–>11–>14–>15–>tail
head–>2–>9–>11–>14–>15–>tail

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
struct student
{
	int  num;
	struct student  *next;
};
struct student *createByTail()
{
	struct student *head;
	struct student *p1,*p2;
	int n;
	n=0;
	p1=p2=(struct student*)malloc(sizeof(struct student));
	scanf("%d",&p1->num);
	head=NULL;  //首先置链表为空链表
	while(p1->num!=-1)    //num为-1,意味着用户输入结束
	{
		n=n+1;
		if(n==1)            //创建第一个结点
			head=p1;
		else
			p2->next=p1;
		p2=p1;            //p2始终指向最后一个结点(即尾指针)
		p1=(struct student*)malloc(sizeof(struct student)); //p1指向新结点
        scanf("%d",&p1->num);
	}
	p2->next=NULL;  //切记:最后一个结点的next赋值为NULL
	return head;
}
//输出链表中的信息(num)
void  displayLink(struct student *head)
{
	struct student *p;
    p=head;
	printf("head-->");
	while(p!= NULL)
	{
		printf("%d-->",p->num);
		p=p->next;
	}
	printf("tail\n");
}
struct student *insertNodeInOrder(struct student *head,struct student *stu)
{
	struct student *p0,*p1,*p2;
	p1=head;
	p0=stu;
	if(head== NULL) //目前还是空链表
	{
        p0->next=head;
        head=p0;
	}
	else
	{
		while((p0->num>p1->num)&&(p1->next!= NULL))
		{//查找插入位置,p2指向p1的前驱
			p2=p1;
			p1=p1->next;
		}
		//while循环的结束条件有两个,下面需要判断是由哪个条件退出循环
		if(p0->num<=p1->num)
		{//由while循环条件的第一个条件退出循环,因此可插在p1结点之前
            if(head==p1)     head=p0;
            else   p2->next=p0;
            p0->next=p1;
		}
        else
        {//由while循环条件的第二个条件退出循环,因此p0->num最大,要插在最后
            p1->next=p0;
            p0->next= NULL;
        }
	}
	return head;
}
struct student *sort(struct student *head)
{
    struct student *p,*s;
    p=head;
    head= NULL;
    while(p)
    {
		s=p;
		p=p->next;
		head=insertNodeInOrder(head, s);
    }
    return head;
}
struct student * merge(struct student *LA, struct student *LB)
{
	struct student  *p,*s;
    p=LB;
    while(p)
    {
		s=p;
		p=p->next;
		LA=insertNodeInOrder(LA, s);
    }
    return LA;
}
struct student* subtract(struct student* LA, struct student* LB)
{
	struct student *q, * p=LB;
	struct student *pre=NULL;//pre指向q的前驱,所以最开始赋为NULL
    while(p!=NULL) //对LB链表遍历
     {
        q=LA;
        while (q!=NULL && q->num!=p->num)
        {
            pre=q;
            q=q->next; //在LA中查找是否有元素与p->num相同
        }
        if (q!=NULL) //找到了相同的元素,则删除q所指向结点
        {
            if (q==LA) //如果删除第一个结点
            {
                LA = LA -> next;
                free(q);
            }
            else
            {
                 pre->next=q->next;
                 free(q);
            }
        }
        p=p->next;
     }
     return LA;
}
void purge(struct student * head)
{
	struct student  *p,*q;
	if(head== NULL || head->next == NULL)
	   return;
	p=head;
	while(p->next!= NULL)
	{
		if(p->num == p->next->num)
		{
		    q=p->next;
		    p->next=q->next;
		    free(q);
		}
		else
		{
		   p=p->next;
	    }
	}
}
struct student* fun(struct student* L1, struct student* L2)
{
/*******************************编写本函数************************************/
    int flag=0;//记录不存在 
    struct student *p1,*p2;
    p2=L2;
    while(p2!=NULL){
        flag=0;
        p1=L1;
        while(p1!=NULL){
            
            if((p1->num) == (p2->num)){
                flag=1;
                break;
            }
            p1=p1->next;
        }
        struct student *temp;
        temp=p1;
        if(flag==1){//要删 
            struct student *q;
            if(temp==L1){
                L1=temp->next;
            }else{
                q=L1;
                while(q->next!=temp){
                    q=q->next;
                }
                q->next=temp->next;
            }
            delete temp;
        }else{//要插入 
            student *node=new student;//一定要new
            node->num=p2->num;
            L1=insertNodeInOrder(L1, node);
        }
        
        p2=p2->next;
    }
    
    return L1;
}
int main()
{
    struct student *headA, *headB, *headC, *headD;
    int i=0,n;
    scanf("%d", &n);
	while( i<n)
    {
        headA=createByTail();//创建链表A
        headB=createByTail();//创建链表B
        headC=createByTail();//创建链表C
        headD=createByTail();//创建链表D
        headA = sort(headA);//链表A排序
        headB = sort(headB);//链表B排序
        headC = sort(headC);//链表C排序
        headD = sort(headD);//链表D排序

        headA = merge(headA, headB);//将链表B合并到链表A中
        purge(headA);//删除链表A中重复元素
        headA = subtract(headA, headC);//从链表A中减去链表C中元素
        headA=fun(headA, headD);//对链表A和链表D调用fun函数
        displayLink(headA);//输出链表A中的元素
        i++;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值