两个集合用单链表存储,分别求出集合的差集和并集(单链表求差集并集)

20 篇文章 0 订阅
6 篇文章 0 订阅

一、集合求差集

题目:已知集合A和B的元素分别用不含头结点的单链表存储,函数difference()用于求解集合A与B的差集,并将结果保存在集合A的单链表中。
例如,若集合A = { 5,10,20,15,25,30 },集合B = { 5,15,35,25 },完成计算后A = { 10,20,30 }。
链表结点的结构类型定义如下:
struct node
{
int elem;
node* next;
};
请完成函数void difference(node** LA, node* LB);
如图所示,题目要求求出差集,即是把相同元素去掉,结果保存在A单链表内即可。
这里写图片描述

方法:
我们选择用两个while循环遍历这两个单链表,用prev和del存储相应的保存删除后节点能连接起来的结点(防止删除结点后找不到它下一个结点)和待删除的结点,pA和pB分别用来遍历这两个单链表,所以根据思路我们写下如下代码。

代码如下:

void difference(node** LA, node* LB)
{
    if (NULL == LB&&NULL == LA&&*LA == NULL)
        return;
    node* pA = *LA;
    node* pB = LB;
    node* prev = NULL;
    node* del = NULL;
    while (pA)
    {
        pB = LB;
        while (pB&&pA->elem != pB->elem)
            pB = pB->next;
        if (pB)//pB->elem==pA->elem
        {
            if (!prev)
                *LA = pA->next;
            else//第一个结点一定相等,程序走的是上面步骤,此时prev==NULL
                prev->next = pA->next;
            del = pA;
            pA = pA->next;
            delete del;
        }
        else//pB为空或者不相等
        {
            prev = pA;
            pA = pA->next;
        }
    }   
}

测试代码与运行结果:

void My_Printf(node* L)
{
    cout << "链表为:";
    node*cur = L;
    while (cur)
    {
        cout << cur->elem << ",";
        cur = cur->next;
    }
    cout << endl;
}
int main()
{
    node*n1 = new node(5);
    node*n2 = new node(10);
    node*n3 = new node(20);
    node*n4 = new node(15);
    node*n5 = new node(25);
    node*n6 = new node(30);
    node*m1 = new node(5);
    node*m2 = new node(15);
    node*m3 = new node(35);
    node*m4 = new node(25);
    n1->next = n2;
    n2->next = n3;
    n3->next = n4;
    n4->next = n5;
    n5->next = n6;
    My_Printf(n1);
    m1->next = m2;
    m2->next = m3;
    m3->next = m4;
    My_Printf(m1);
    difference(&n1, m1);
    My_Printf(n1);
    return 0;
}


二、集合求并集

根据以上代码我们便想到本题的一个变形,两个集合用链表存储,求出这两个集合的并集。

方法既是用一个node存储需要插入的结点再用两个循环遍历即可。
但要保证两个链表有序,为了简便,我在测试的时候直接用有序的方法插入结点,没有写排序函数。

代码如下:

void same(node** LA, node* LB)
{
    if (*LA == NULL)
    {
        *LA = LB;
        return;
    }
    if (LB == NULL)
    {
        return;
    }

    //进行插入节点
    node dummy(-1);
    node* pre = &dummy;

    node* pA = *LA;
    node* pB = LB;

    while (pA&&pB)
    {
        while (pA->elem == pB->elem)
        {
            pre = pA;
            pA = pA->next;
            pB = pB->next;
        }
        if (pA&&pB&&pA->elem < pB->elem)
        {
            pre = pA;
            pA = pA->next;
        }
        else if (pA&&pB)
        {
            //插入操作
            node * temp = new node(pB->elem);
            temp->next = pA;
            pre->next = temp;
            pB = pB->next;
        }
    }
    if (pA == NULL)
    {
        pre->next = pB;
    }
    //死循环,这样写有问题
    //if (*LA == NULL&&LB == NULL&&LA == NULL)
    //  return;
    //node* pA = *LA;
    //node* pB = LB;
    //node* prev = new node(0);
    //while (pA)
    //{
    //  while (pB->elem == pA->elem&&pB)
    //      pB = pB->next;
    //  if (pB)//pB存在,不相等
    //  {
    //      prev = pB;
    //      prev->next = NULL;
    //      prev->next = pA->next;
    //      pA->next = prev;
    //      //prev = pA->next;
    //      //prev->next = NULL;
    //      //pB->next = prev;

    //  }
    //  pB = LB;
    //  pA = pA->next;
    //}
}

测试代码及运行结果

#include <iostream>
using namespace std;
struct node
{
    int elem;
    node* next;
    node(int data)
        :elem(data)
        ,next(NULL)
    {};
};
void My_Printf(node* L)
{
    cout << "链表为:";
    node*cur = L;
    while (cur)
    {
        cout << cur->elem << ",";
        cur = cur->next;
    }
    cout << endl;
}

int main()
{
    node*n1 = new node(5);
    node*n2 = new node(10);
    node*n3 = new node(15);
    node*n4 = new node(20);
    node*n5 = new node(25);
    node*n6 = new node(30);
    node*m1 = new node(5);
    node*m2 = new node(15);
    node*m3 = new node(25);
    node*m4 = new node(35);

    n1->next = n2;
    n2->next = n3;
    n3->next = n4;
    n4->next = n5;
    n5->next = n6;
    My_Printf(n1);
    m1->next = m2;
    m2->next = m3;
    m3->next = m4;
    My_Printf(m1);
    same(&n1, m1);
    My_Printf(n1);
    return 0;
}

这里写图片描述

  • 5
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值