用链表实现集合的交集并集差集运算


题目来自某NJU同学的程序设计基础作业

贴一下题目:

用链表建立两个整数集合A和B(从键盘键入集合的元素,以-1结束,集合中没有-1)。

分别编写三个函数计算这两个集合的。

  a.交集

  b.并集

  c.差集A-B

三个函数的计算结果为新的链表。

输出这三个新链表。

做题心得

其实这道题用数组直接能秒杀掉,难度就在对于单链表的理解与应用。对指针和结构体有挺高的掌握要求。

之前没好好学链表,总觉得数组能解决的事用数组,数组解决不了的用STL(stl永远的神不接受反驳)

补了三天的链表,总算学得明白了一点,简单把题过了一下。没有用函数分段,其实分段一下很简单。

P.S肥肠感谢鸡哥龙神的鼎力相助!

直接po代码,有错误或者其他更好的思路也希望dalao们可以带带

#include<stdio.h>
#include<stdlib.h>
struct node//链表结构体 
{
    int data;//数据域 
    struct node* next;//指向下一个结构体的指针 
};
node* create(int data)//新建链表项(新结构体) 
{
    node* newNode = (node*)malloc(sizeof(node));//给这个结构体开空间 
    newNode->data = data;//保存数据 
    newNode->next = NULL;//指针为空 
    return newNode;//返回新建的结构体 
}

int main()
{
    struct node *p,*q,*t,*h;//定义几个临时变量,会用到 
    int tmp;
    
    //输入集合A 
    scanf("%d", &tmp);
    struct node* head_a = create(tmp);//头节点 
    p = head_a;//p是临时变量 
    while (scanf("%d", &tmp) && tmp != -1)//输入数字,且当tmp=-1的时候结束 
    {
        struct node* a = create(tmp);//给链表A新建节点 
        p->next = a;//上一个节点的指针指向现在这个 
        p = a;//临时变量变成现在这个 
    }
    
    //输入集合A 
    scanf("%d", &tmp);
    struct node* head_b = create(tmp);//头节点 
    p = head_b;//p是临时变量 
    while (scanf("%d", &tmp) && tmp != -1)//输入数字,且当tmp=-1的时候结束
    {
        struct node* b = create(tmp);//给链表A新建节点
        p->next = b;//上一个节点的指针指向现在这个
        p = b;//临时变量变成现在这个 
    }
    
    struct node* head_jiao = create(-1);//定义交集的头结点 
    struct node* head_bing = create(-1);//定义并集的头结点 
    struct node* head_cha = create(-1);//定义差集的头结点 
    
    /*
    交集思路:
    遍历A,对A的每个元素 ,都与B中的元素进行一一对比
    类似于for循环中的
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            比较a和b
        }
    }
    */ 
     
    p=head_a;//p是临时变量,从A的头开始 
    t=head_jiao;//t是临时变量,用来存交集的链表 
    while(p!=NULL)//链表A非空 ,遍历A链表 
    {
        
        q=head_b;//q是临时变量 ,从B的头开始 
        while(q!=NULL)//链表B非空 ,遍历B链表 
        {
            if(q->data==p->data)//B元素=A元素 
            {
                //如果a和b中有相同元素,则存进交集链表中 
                //以下操作与输入A,B集合同原理 
                struct node* jiao = create(p->data);
                t->next = jiao;
                t = jiao;
                break;//因为找到了,所以break掉,去比较A的下一个元素 
            }
            q=q->next;//链表B的当前位置后移(q->next是下一个元素,让q=下一个元素 
        }
        p=p->next;//链表A的当前位置后移(p->next是下一个元素,让p=下一个元素 
    }
    /*
    输出交集
    因为head_jiao->data头节点的数据域中存的是-1(见上文定义交集头结点 
    故从head_jiao的下一个开始
    */
    t=head_jiao->next;
    while(t!=NULL)//遍历交集链表 
    {
        printf("%d ",t->data);//输出元素,记得加空格 
        t=t->next;//后移 
    }
    //Attention:这个-1不应该被放在链表中 
    printf("-1\n");//最后的元素以-1结尾,记得加换行 
    
    /*
    并集思路:
    先复制A的所有元素在并集bing里面
    然后遍历B,将B的每一个元素都与bing中元素比较
    若比较到最后都不一样,则当前元素不在bing中
    将这个元素添加进bing的末尾 
    */
    
    p=head_a;//p是临时变量,从A的头开始
    t=head_bing;//t是临时变量,用来存并集的链表
    while(p!=NULL)//遍历链表A 
    {
        //以下操作与输入A,B集合同理,使用链表A的数据 
        struct node* bing = create(p->data);
        t->next = bing;
        t = bing;
        p=p->next;//链表A的当前位置后移(p->next是下一个元素,让p=下一个元素 
    }
    q=head_b;//q是临时变量,从B的头开始 

    while(q!=NULL)//遍历链表B
    {
            h=head_bing;//h是临时变量,读取并集的链表
        int flag=0;//用flag来记录是否有相同元素 
        while(h!=NULL)//遍历并集
        {
            if(h->data==q->data)//存在相同元素
            { 
                flag=1;
                break;
            }
            h=h->next;//后移
        }
        if(!flag)//如果不存在相同元素
        {
            //以下操作与输入A,B集合同理,使用链表B的当前元素数据 
            //t还是上面复制的时候定义的那个,继续相同操作 
            struct node* bing = create(q->data);
            t->next = bing;
            t = bing;
        }
        q=q->next;//后移 
    }
    /*
    输出并集
    因为head_bing->data头节点的数据域中存的是-1(见上文定义并集头结点 
    故从head_bing的下一个开始
    */ 
    t=head_bing->next;
    while(t!=NULL)//遍历并集链表 
    {
        printf("%d ",t->data);//输出元素,记得加空格 
        t=t->next;//后移 
    }
    //Attention:这个-1不应该被放在链表中 
    printf("-1\n");//最后的元素以-1结尾,记得加换行
    
    /*
    差集思路:
    同并集,先复制链表A在链表cha里面
    再遍历链表bing,如果遇到元素在链表A中,则删除链表节点
    */
    p=head_a;//p是临时变量,从A的头开始
    t=head_cha;//t是临时变量,用来存差集的链表
    while(p!=NULL)//遍历链表A 
    {
        //以下操作与输入A,B集合同理,使用链表A的数据 
        struct node* cha = create(p->data);
        t->next = cha;
        t = cha;
        p=p->next;//链表A的当前位置后移(p->next是下一个元素,让p=下一个元素 
    }

    q=head_jiao;//q是临时变量,从jiao的头开始
    while(q!=NULL)//遍历链表jiao 
    {
        h=head_cha;//h是临时变量,从cha的第1个开始 
        t=head_cha->next;//t是临时变量,从cha的第2个开始 
        
        
        while(t!=NULL)//遍历cha差集,寻找当前数,然后把它删了 
        {
            if(t->data==q->data)//如果相等,删除 
            {
                h->next=t->next;//跳过t指向下一个 
                break;
            }
            //如果没删除,后移 
            h=h->next;
            t=t->next;
        }
        q=q->next;//后移 
    }
    
    /*
    输出差集
    因为head_cha->data头节点的数据域中存的是-1(见上文定义并集头结点 
    故从head_cha的下一个开始
    */ 
    t=head_cha->next;
    while(t!=NULL)//遍历差集链表 
    {
        printf("%d ",t->data);//输出元素,记得加空格 
        t=t->next;//后移 
    }
    //Attention:这个-1不应该被放在链表中 
    printf("-1\n");//最后的元素以-1结尾,记得加换行
    
    return 0;
}
代码与解析

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM