第二章 线性表 —— 顺序表结构编程实现两集合交并补

顺序表结构编程实现两集合交并补

#include <iostream>
#include<stdio.h>
#include <stdlib.h>
using namespace std;

#define OK 1
#define ERROR 0
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
#define OVERFLOW -2
typedef struct
{
    int *elem;             //定义一个指针表示存储空间基址
    int  length;               //当前表长(特指元素个数)
    int listsize;
} SqList;

//初始化
int InitList_Sq(SqList &L)
{
    L.elem=(int *)malloc(LIST_INIT_SIZE*sizeof(int));//动态分配内存
    if(!L.elem)
        exit(OVERFLOW);
    L.length=0;
    L.listsize=LIST_INIT_SIZE;
    return OK;
}

//给顺序表赋值
void fuzhi(SqList &L)
{
    int n,m;
    cout<<"请输入集合的数据元素个数"<<endl;
    cin>>n;
    for(int i=0; i<n; i++)
    {
        cout<<"请输入第"<<i+1<<"的数据元素的值"<<endl;
        cin>>m;
        L.elem[i]=m;
        L.length++;
    }
    cout<<"赋值成功"<<endl;
}

void Get(SqList L)
//输出当前列表
{
    //cout<<"当前列表:"<<endl;
    for(int i=0; i<L.length; i++)
    {
        cout<<L.elem[i]<<" ";
    }
    cout<<endl;
}

int GetElem(SqList L,int i,int &e)
//用e返回L中第i个元素的值
{
    if(i<1||i>L.length)
        return ERROR;
    e=L.elem[i-1];
    return OK;
}

int equal_e(int a,int b)
{
    if(a==b)
        return OK;
    else
        return ERROR;
}

int LocateElem(SqList L,int e,int (*compare)(int,int))
//在表中查找第一个值与e满足compare()元素的位序
{
    int i=1;
    int *p=L.elem;
    while(i<=L.length&&!(*compare)(*p++,e))
        ++i;
    if(i<=L.length)
        return i;
    else
        return 0;
}

//在顺序表指定位置插入元素
int ListInsert_Sq(SqList &L,int i,int e)
{
    if(i<1||i>L.length+1)
        return ERROR;
    if(L.length>=L.listsize)
    {
        int *newbase;
        newbase=(int*)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(int));//扩充内存
        if(!newbase)
            exit(OVERFLOW);
        L.elem=newbase;
        L.listsize+=LISTINCREMENT;
    }
    int *p,*q;
    q=&(L.elem[i-1]);
    for(p=&(L.elem[L.length-1]); p>=q; p--)
        *(p+1)=*p;
    *q=e;
    ++L.length;
    return OK;
}

void union_set(SqList La,SqList Lb,SqList &Lc)
//a与b的并集放入c中
{
    int La_len=La.length;
    int Lb_len=Lb.length;
    int e;
    for(int i=1; i<=Lb_len; i++)
    {
        GetElem(Lb,i,e);
        if(!LocateElem(La,e,equal_e))
            ListInsert_Sq(La,++La_len,e);
    }

    for(int i=1; i<=La_len; i++)
    {
        GetElem(La,i,e);
        ListInsert_Sq(Lc,i,e);
    }
}

int mixture(SqList La,SqList Lb,SqList &Lc)
//a与b的交集
{
    int La_len=La.length;
    int Lb_len=Lb.length;
    int e;
    int index=0;
    //cout<<Lc.length<<endl;
    SqList p=La_len<=Lb_len?La:Lb;
    SqList q=La_len>Lb_len?La:Lb;
    for(int i=1; i<=p.length; i++)
    {
        GetElem(p,i,e);
        if(LocateElem(q,e,equal_e))
        {
            ListInsert_Sq(Lc,++index,e);
            //Get(Lc);
        }
    }
    if(Lc.length)
        return OK;
    else
        return ERROR;
}

int different(SqList La,SqList Lb,SqList &Lc)
//求a-b差集
{
    int La_len=La.length;
    int e;
    int index=0;
    for(int i=1; i<=La_len; i++)
    {
        GetElem(La,i,e);
        if(!LocateElem(Lb,e,equal_e))
            ListInsert_Sq(Lc,++index,e);
    }
    if(Lc.length)
        return OK;
    else
        return ERROR;
}

int main()
{

    SqList La,Lb;
    InitList_Sq(La);
    InitList_Sq(Lb);
    cout<<"集合A:"<<endl;
    fuzhi(La);
    cout<<"集合A中元素: ";
    Get(La);
    cout<<endl;
    cout<<"集合B:"<<endl;
    fuzhi(Lb);
    cout<<"集合B中元素: ";
    Get(Lb);
    cout<<endl;

    cout<<"A并B:"<<endl;
    SqList Lc1;
    InitList_Sq(Lc1);
    union_set(La,Lb,Lc1);
    Get(Lc1);
    cout<<endl;

    cout<<"A交B:"<<endl;
    SqList Lc2;
    InitList_Sq(Lc2);
    if(mixture(La,Lb,Lc2))
    {
        Get(Lc2);
        cout<<endl;
    }
    else
    {
        cout<<"null"<<endl;
        cout<<endl;
    }
    
    cout<<"A-B:"<<endl;
    SqList Lc3;
    InitList_Sq(Lc3);
    if(different(La,Lb,Lc3))
        Get(Lc3);
    else
        cout<<"null"<<endl;

    return 0;
}

剖析:
1.初始化

//初始化
int InitList_Sq(SqList &L)
{
    L.elem=(int *)malloc(LIST_INIT_SIZE*sizeof(int));//动态分配内存
    if(!L.elem)
        exit(OVERFLOW);
    L.length=0;
    L.listsize=LIST_INIT_SIZE;
    return OK;
}
  • malloc()为动态存储分配函数,需要头文件<stdlib.h>.
  • 这里我们从堆中动态分配了400个字节的内存空间(按照int 是4个字节计算,即100个int的大小)。然后将首地址返回给L.elem,若函数执行失败则返回null。
  • exit(n)就是退出,传入的参数n是程序退出时的状态码,0表示正常退出,其他表示非正常退出

2.往顺序表中插入元素

//在顺序表指定位置插入元素
int ListInsert_Sq(SqList &L,int i,int e)
{
    if(i<1||i>L.length+1)
        return ERROR;
    if(L.length>=L.listsize)
    {
        int *newbase;
        newbase=(int*)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(int));//扩充内存
        if(!newbase)
            exit(OVERFLOW);
        L.elem=newbase;
        L.listsize+=LISTINCREMENT;
    }
    int *p,*q;
    q=&(L.elem[i-1]);
    for(p=&(L.elem[L.length-1]); p>=q; p--)
        *(p+1)=*p;
    *q=e;
    ++L.length;
    return OK;
}
  • realloc(a,b)函数用来扩大动态分配区域,即当第二个参数b大于第一个参数a指向的动态内存大小时将重新申请一个大小为b的内存空间。
  • 添加时为防止覆盖要先把后面的向后移再插入。

3.构造一个按某种规则定位的函数

int equal_e(int a,int b)
{
    if(a==b)
        return OK;
    else
        return ERROR;
}

int LocateElem(SqList L,int e,int (*compare)(int,int))
//在表中查找第一个值与e满足compare()元素的位序
{
    int i=1;
    int *p=L.elem;
    while(i<=L.length&&!(*compare)(*p++,e))
        ++i;
    if(i<=L.length)
        return i;
    else
        return 0;
}
  • compare那个是把一个函数作为变量传入函数locateElem()中,本题中compare指向equal_e()函数。
  • 本题中函数locateElem()的功能是找到顺序表L中第一个和e相同的元素位置。

4.求两个集合的并集

void union_set(SqList La,SqList Lb,SqList &Lc)
//a与b的并集放入c中
{
    int La_len=La.length;
    int Lb_len=Lb.length;
    int e;
    for(int i=1; i<=Lb_len; i++)
    {
        GetElem(Lb,i,e);
        if(!LocateElem(La,e,equal_e))
            ListInsert_Sq(La,++La_len,e);
    }

    for(int i=1; i<=La_len; i++)
    {
        GetElem(La,i,e);
        ListInsert_Sq(Lc,i,e);
    }
}
  • 如果集合B中的元素在集合A中全找了一遍都没有相等的话,那LocateElem()函数中的i就会大于L.length。此时这里的if判断成真。我们把这个e添加到集合A的最后一位。

5.两个集合求交集

int mixture(SqList La,SqList Lb,SqList &Lc)
//a与b的交集
{
    int La_len=La.length;
    int Lb_len=Lb.length;
    int e;
    int index=0;
    //cout<<Lc.length<<endl;
    SqList p=La_len<=Lb_len?La:Lb;
    SqList q=La_len>Lb_len?La:Lb;
    for(int i=1; i<=p.length; i++)
    {
        GetElem(p,i,e);
        if(LocateElem(q,e,equal_e))
        {
            ListInsert_Sq(Lc,++index,e);
            //Get(Lc);
        }
    }
    if(Lc.length)
        return OK;
    else
        return ERROR;
}

  • 因为两集合的交集一定小于等于两集合中最小的那个,所以我们从小集合中取元素跟大集合比较,这样更快一点。
  • 如果对比成功的位置小于L.length说明集合A中存在这个元素,此时if判断成真,我们将它放入新的顺序表中表示交集。

6.两集合求差

int different(SqList La,SqList Lb,SqList &Lc)
//求A-B差集
{
    int La_len=La.length;
    int e;
    int index=0;
    for(int i=1; i<=La_len; i++)
    {
        GetElem(La,i,e);
        if(!LocateElem(Lb,e,equal_e))
            ListInsert_Sq(Lc,++index,e);
    }
    if(Lc.length)
        return OK;
    else
        return ERROR;
}

  • A B A - B B A B - A 可不一样,所以这里只能从A中拿元素和B里的元素进行比较。
  • 差集和交集规则相反,if里面加一个!就好。
原创文章 85 获赞 46 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Deam_swan_goose/article/details/104606556
今日推荐