美文网首页
集合运算(链表和移动语义)

集合运算(链表和移动语义)

作者: 板混DK | 来源:发表于2017-10-30 20:22 被阅读0次

题目描述:

请设计实现集合类,元素类型为整形, 集合采用带头结点单链表表示。该集合类支持集合元素增加、删除、查询;并支持集合并、交、差运算;利用你设计的集合类,实现本题要求。程序应体现面向对象程序设计思想,结构合理。为保证结果唯一,集合元素递增排列。如需用到拷贝构造和赋值应重载. 空间应正确释放. 要求使用移动复制和移动赋值,但本平台编译器不支持,所以,这部分代码以注解形式提供.

输入描述:

开始为两个正整数m,n;后续m个整数构成集合A,再后续n个整数构成集合B

输出描述:

集合A、B和他们的并、交、差集;每个集合元素间以,分隔;不同集合显示在不同行

输入样例:

3 5
1 2 3
3 5 8 2 1

输出样例:

{1,2,3}
{1,2,3,5,8}
{1,2,3,5,8}
{1,2,3}
{}
——————————————————————————————————————

代码:

#include <iostream>
using namespace std;

class CSet{
private:
    struct Node{
        int data;
        Node *next;
    } *m_pHead; // 集合采用递增排序单链表表示
public:
    //构造函数
    CSet();
    //析构函数,释放链表
    ~CSet();
    //增加元素
    bool Add(int x);
    //显示集合
    void Display();
    //结果为A、B并集
    CSet UnionBy(const CSet &rhs) const;
    //结果为A、B交集
    CSet IntersectionBy(const CSet &rhs) const;
    //结果为A、B差集
    CSet DifferentBy(const CSet &rhs) const;

    //下列成员函数本例未用,纯完整性考虑
    //拷贝构造函数
    CSet(const CSet &);
    //移动构造函数
    //CSet(CSet &&);
    //删除元素x
    bool Remove(int x);
    //是否包含元素x
    bool In(int x);
    //复制赋值
    CSet & operator = (const CSet &rhs);
    //移动赋值
    //CSet & operator = (CSet &&rhs);

private:
    //集合清空
    void    _Clear();
};


//构造函数
CSet::CSet()
{
    m_pHead = new Node;;
    m_pHead->next = NULL;
}
//析构函数,释放链表
CSet::~CSet()
{
    while (m_pHead) {
        Node *p = m_pHead;
        m_pHead = p->next;
        delete p;
    }
}

//集合清空
void    CSet::_Clear()
{
    while (m_pHead->next) {
        Node *p = m_pHead;
        m_pHead = p->next;
        delete p;
    }
}

//增加元素
bool CSet::Add(int x)
{
    Node *p = m_pHead;
    while (p->next && (p->next->data < x)) {
        p = p->next;
    }
    if (p->next && p->next->data == x)
        return false; //元素已在集合中
    Node *q = new Node;
    q->data = x;
    q->next = p->next;
    p->next = q;
    return true;

}

//显示集合
void CSet::Display()
{
    Node *p = m_pHead->next;
    cout << "{";
    while (p)
    {
        cout << p->data;
        p = p->next;
        if (p) cout << ",";
    }
    cout << "}" << endl;
}

//结果为A、B并集,为效率避免拷贝构造
//本例为简化逻辑直接调用Add成员函数,效率为O(M*N);实际应参考IntersectionBy展开,效率可为O(M+N)
CSet CSet::UnionBy(const CSet &rhs) const
{
    CSet  result;

    Node *p = m_pHead->next;
    Node *q = rhs.m_pHead->next;
    while (p && q) {
        if (p->data == q->data) {
            result.Add(p->data);
            p = p->next;
            q = q->next;
        }
        else if (p->data < q->data) {
            result.Add(p->data);
            p = p->next;
        }
        else {
            result.Add(q->data);
            q = q->next;
        }
    }
    while (p) {
        result.Add(p->data);
        p = p->next;
    }
    while (q) {
        result.Add(q->data);
        q = q->next;
    }
    return result;
}

//结果为A、B交集,为效率避免拷贝构造
CSet CSet::IntersectionBy(const CSet &rhs) const
{
    CSet  result;

    Node *last = result.m_pHead;

    Node *p = m_pHead->next;
    Node *q = rhs.m_pHead->next;
    while (p && q)  {
        if (p->data == q->data) {
            //          Add(p->data);
            Node * s = new Node;
            s->data = p->data;
            last->next = s;
            last = s;

            p = p->next;
            q = q->next;
        }
        else if (p->data  < q->data)
            p = p->next;
        else
            q = q->next;
    }
    last->next = NULL;
    return result;
}

//结果为A、B差集,为效率避免拷贝构造
//本例为简化逻辑直接调用Add成员函数,效率为O(M*N);实际应参考IntersectionBy展开,效率可为O(M+N)
CSet CSet::DifferentBy(const CSet &rhs) const
{
    CSet  result;

    Node *p = m_pHead->next;
    Node *q = rhs.m_pHead->next;
    while (p && q) {
        if (p->data == q->data) {
            p = p->next;
            q = q->next;
        }
        else if (p->data  < q->data) {
            result.Add(p->data);
            p = p->next;
        }
        else
            q = q->next;
    }
    while (p) {
        result.Add(p->data);
        p = p->next;
    }
    return result;
}

//删除元素
bool CSet::Remove(int x)
{
    Node *p = m_pHead;
    while (p->next && (p->next->data < x)) {
        p = p->next;
    }
    if (p->next == NULL || p->next->data != x)
        return false; //元素未在集合中
    Node *q = p->next;
    p->next = q->next;
    delete q;
    return true;
}

//是否包含元素x
bool CSet::In(int x)
{
    Node *p = m_pHead;
    while (p->next && (p->next->data < x)) {
        p = p->next;
    }
    if (p->next && p->next->data == x)
        return true;
    return false;
}

//拷贝构造函数
CSet::CSet(const CSet &rhs)
{
    //复制头结点
    m_pHead = new Node;
    Node *last = m_pHead; //最后结点

    Node *p = rhs.m_pHead->next;//不可修改rhs.m_pHead, 故引入临时变量p
    while (p) {
        Node *q = new Node;//申请一结点
        q->data = p->data; //复制元素
        //挂在最后
        last->next = q;
        last = q;
        //后移一结点
        p = p->next;
    }
    last->next = NULL;
}
//移动构造函数
/*
CSet::CSet(CSet &&rhs)
{
    //复制头结点
    m_pHead = rhs.m_pHead;
    rhs.m_pHead = NULL;
}
*/
//复制赋值
CSet & CSet::operator = (const CSet &rhs)
{
    this->_Clear();

    Node *last = m_pHead; //最后结点

    Node *p = rhs.m_pHead->next;//不可修改rhs.m_pHead, 故引入临时变量p
    while (p) {
        Node *q = new Node;//申请一结点
        q->data = p->data; //复制元素
        //挂在最后
        last->next = q;
        last = q;
        //后移一结点
        p = p->next;
    }
    last->next = NULL;

    return *this;
}
//移动赋值
/*
CSet & CSet::operator = (CSet &&rhs)
{
    Node *p = this->m_pHead;
    this->m_pHead = rhs.m_pHead;
    rhs.m_pHead = p;

    return *this;
}
*/
int main()
{
    CSet A, B, S;
    int i, m, n, x;
    cin >> m >> n;
    while ((m + n) >= 100) exit(-1);
    for (i = 0; i < m; i++)
    {
        cin >> x;
        A.Add(x);
    }
    for (i = m; i < n + m; i++)
    {
        cin >> x;
        B.Add(x);
    }
    A.Display();
    B.Display();


    S = A.UnionBy(B);
    S.Display();

    S = A.IntersectionBy(B);
    S.Display();

    S= A.DifferentBy(B);
    S.Display();

    return 0;
}

相关文章

  • 集合运算(链表和移动语义)

    题目描述: 请设计实现集合类,元素类型为整形, 集合采用带头结点单链表表示。该集合类支持集合元素增加、删除、查询;...

  • sql server集合运算

    集合运算包含四种:1.并集运算2.交集运算3.差集运算 为什么使用集合运算:1.在集合运算中比联接查询和EXIST...

  • 数组集合和链表集合

    声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权;凯哥学堂旨在促进VIP学员互...

  • 有序集合间的对位运算

    有序集合间的对位运算,包括比较运算(>,<, 等于)和四则运算(+,-,*,/,%,\)。本问中讨论的集合,都是有...

  • SQL进阶教程之1.7集合运算

    集合运算注意事项 需要保留重复项目的集合,用ALL 集合运算有优先级,intersect 比 union 和 ex...

  • 18/2

    移动语义与右值引用(只能在右边) 1.移动语义:实际文件还留在原来地方,而只是修改记录,移动语义实际上避免了移动原...

  • 第八章: 集合运算

    第八章: 集合运算 • 集合运算:是用来把两个或多个查询的结果集做并、交、差的集合运算,包含集合运算的查询称为复合...

  • redis底层数据组织方式

    底层数据结构 redis底层数据结构有:字典、双端链表、压缩链表、整数集合、跳跃表和字典、整数集合、embstr ...

  • 3.集合的运算(续)

    引入集合的运算(目的)——新集合 | 简化运算 运算规律&不同运算之间的规律 交的并=并的交

  • oracle学习笔记七——查询之集合运算

    七.集合运算 可以根据下图图示并文字理解集合运算集合运算示意图(1)union/union all 并集--uni...

网友评论

      本文标题:集合运算(链表和移动语义)

      本文链接:https://www.haomeiwen.com/subject/rcmmpxtx.html