利用链表求集合的差集

  1. 内容:如果以单链表表示集合,假设集合A用单链表LA表示,集合B用单链表LB表示,设计算法求两集合的差,即A-B。用C语言实现程序解决问题。
  2. 算法分析:由集合运算的规则可知,集合的差A-B中包含所有属于集合A而不属于集合B的元素。具体做法是,对于集合A中的每一个元素,在集合B的链表LB中进行查找,若存在与A中元素相同的元素,则在LA中将其删除。

    首先需要定义链表结点的结构类型,然后选择使用两个while循环遍历这两个单链表,用pre和q存储相应的结点和待删除的节点,pa和pb分别用来遍历这两个单链表。

    编写测试代码,假设A集合为{1,2,3,4,5,6},B集合为{1,2,3,4},则A-B集合为{5,6}。

  3. 概要设计:使用C语言,其中设置了以下函数

  4. 程序运行流程图如下:

     

     

     

  5.  测试(设计测试用例或测试代码的设计与实现,测试结果截屏)测试案例如图

     

     

  6. 测试结果如图所示:

 

                                                                                                                                                                                                                                                                                                                                                                                                                  测试结果显示输入字母求差集存在问题,故进行调试代码。测试代码时,当输入字母形式的集合时,会出现错误,显示“a was not declared in this scope”,主要原因在于定义data的数据类型时,定义的是int型,当输入字符型常量时,程序就会报错,因此将int data;改为char data;这时当输入字母集合时,程序正常运行,输出的是字母的ASCII码值,调试成功如图所示

 

 

 

 

 

源代码如下:

#include<iostream>
#include<assert.h>
using namespace std;
//定义链表结点的结构类型 
struct Node
{
    int elem;
    Node*next;

    Node(char data)
        :elem(data)
        , next(NULL)
    {}
};
//利用函数完成集合的差运算 
void Different(Node**LA, Node*LB)
{
    Node*pa = *LA;  //遍历A链表
    //Node*pb = LB;//遍历B链表
    Node *pre = NULL;//用来保存删除后结点能连接起来
    Node*q;//待删除的结点 
    while (pa)
    {
        Node*pb = LB;
        while (pb&&pa->elem != pb->elem)
            pb = pb->next;//
        if (pb)//两个结点的值相等
        {
            if (!pre)
            {
                *LA = pa->next;//指向下一个结点 
            }
            else//第一个结点相等
            {
                pre->next = pa->next;//指向相等结点的后一个
            }
            q = pa;//释放结点 
            pa = pa->next;
            free(q);
        }
        //链表B已遍历完
        else
        {
            //更新结点的位置
            pre = pa;
            pa = pa->next;
        }
    }
}
void Printf(Node*L)
{
    Node*cur = L;
    while(cur)
    {
        cout << cur->elem << " ";
        cur = cur->next;
    }
    cout << endl;
}
//测试代码 
void Test()
{
    Node*n1 = new Node('a');
    Node*n2 = new Node('b');
    Node*n3 = new Node('c');
    Node*n4 = new Node('d');
    Node*n5 = new Node('e');
    Node*n6 = new Node('f');

    n1->next = n2;
    n2->next = n3;
    n3->next = n4;
    n4->next = n5;
    n5->next = n6;
    cout << "链表A" << endl;
    Printf(n1);

    Node*m1 = new Node('a');
    Node*m2 = new Node('e');
    Node*m3 = new Node('f');
    Node*m4 = new Node('g');

    m1->next = m2;
    m2->next = m3;
    m3->next = m4;
    cout << "链表B" << endl;

    Printf(m1);
    cout << "链表的差集" << endl;

    Different(&n1, m1);
    Printf(n1);
}

int main()
{
    Test();
    system("pause");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值