集合的操作

问题描述 :

 

输入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中查询:

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

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

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

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

 

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

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

形参:

L1:传入的第一个集合,程序中将传入A集合的链表头指针

L2:传入的第二个集合,程序中将传入D集合的链表头指针

返回值:

返回第一个集合的链表的头指针

 

程序部分代码如下:

#include <stdio.h>

#include <stdlib.h>

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 main()

{

    struct student *headA, *headB, *headC, *headD;

    int i,n;

    while(scanf("%d", &n)!= EOF)

    {

        i=0;

        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;

}

 

输入说明 :

 

首先输入一行,包含一个整数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>

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)

{
struct student *p,*pre,*q,*temp;
    q=L2;
    while(q!=NULL)
    {
        p=L1;
        pre=NULL;
        while(p && q->num > p->num)
        {
            pre=p;
            p=p->next;
        }
        //没有在L1链表中找到当前元素
        if(!p || (q->num!=p->num))
        {
            temp=(struct student*)malloc(sizeof(struct student));
            temp->num=q->num;
            L1=insertNodeInOrder(L1,temp);
        }
        //如果L1链表中出现该元素
        else
        {
            //如果是头结点
            if(p==L1)
            {
                temp=p;
                L1=p->next;
                free(temp);
            }
            //如果不是头结点
            else
            {
                temp=p;
                pre->next=p->next;
                free(temp);
            }
        }

        q=q->next;
    }
    return L1;
}
int main()

{

    struct student *headA, *headB, *headC, *headD;

    int i,n;

    while(scanf("%d", &n)!= EOF)

    {

        i=0;

        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、付费专栏及课程。

余额充值