数据结构与算法基础(王卓)(8):线性表的应用(并集:无需有序,不能重复)

目录

并集集合:线性表的合并(无需有序,不能重复)

线性表:

链表:


PPT:第二章P173;


并集集合:线性表的合并(无需有序,不能重复)

线性表:

Status Union(Sqlist& A, Sqlist& B)//并集
{
    int len_A = A.length;
    int len_B = B.length;
    for (int i = 1; i <= len_B; i++)
    {
        Poly e=*A.elem;
        //这里只是给我们设定的元素e赋一个任意初值
        //只要保证e在初始化时由初值不为空即可
        //至于该e元素的内容是什么其实并没有什么所谓
        //因为后面我们总归是会改的
        GetElem(B, i, e);
        if (LocateElem(A, e))
            return ERROR;
        else
            ListInsert(A, ++len_A, e);
        //注意插入函数中输入的是位序,不是数组下标
    }
    return true;
}

该算法的时间复杂度:O(ListLenth(La) * ListLength(Lb))

最后A表为合并以后的新表


链表:

Status Union(Lnode& A, Lnode& B)
{
    for (int i = 1; i <= 求表长(&B); i++)
    {
        int len_A = 求表长(&A);
        Elemtype e;
        取第i个元素(&A, i, e);
        if (!LocateELem(&B, e))
            Listlnsert(&A, ++len_A, e);
    }
    return true;
}

结果:(默认在(7):小结:关于链表和线性表的定义及操作当中预设的前置语句之下运行) 

而产生该结果的原因,和前置语句中,定义插入函数的语句有关:

Status Listlnsert(LinkList& L, int i, Elemtype e)

更准确的来说:问题源于我们给出的 “&A”和定义中的“LinkList& L”类型匹配不上

这里,我们对LinkList &A等格式进行一个系统性的总结:

 &A代表的到底是什么??

Sqlist  A:线性表结点类型的变量A


Sqlist &A:还是表示线性表结点类型的变量A,但是(只是)表示采用引用传值的传值方式


LinkList A:指向目标对象为 线性表结点类型的指针变量A

LinkList &A:还是表示指向目标对象为 线性表结点类型的指针变量A

只是
表示采用引用传值的传值方式传达(递)这个地址 


想要程序能够正常运行,改动的方法有两种:

1:

修改<插入>函数的函数体:(此时<合并>函数无需修改)

把合并函数的“声明”(函数体之外)部分改为:

Status Listlnsert(LinkList L, int i, Elemtype e)

此时,该合并函数所需要的前置条件(最简单版本)为:

//链表的定义及其基础操作
#include<iostream>
using namespace std;
#include<stdlib.h>//存放exit

#define TRUE        1
#define FALSE       0
#define OK          1
#define ERROR       0
#define INFEASIBLE  -1
#define OVERFLOW   -2   

#define MAXlength 100  //初始大小为100,可按需修改

typedef int Status;         //函数调用状态

struct K
{
    float a;
    int b;
    string c;
    bool operator==(K& t)
    {
        return t.a == a && t.b == b;
        //&& t.c = c;
    }
    bool operator!=(K& t)
    {
        return t.a != a || t.b != b;
        //|| t.c = c;
    }
};
typedef K Elemtype;         //函数调用状态

struct Lnode
    //node:结; 结点;
{
    Elemtype data;
    Lnode* next;
};
typedef Lnode* LinkList;

Status 链表是否为空(LinkList L)
{
    if (L->next)
        return true;
    else
        return false;
}
Status 求表长(LinkList L)
{
    if (链表是否为空(L))
        cerr << "链表为空" << endl;
    LinkList p = L->next;
    //特别注意:因为这里从首元结点开始算起(计算)
    //所以:L->next;
    int i = 0;
    while (p)//不要写成if
    {
        p = p->next;
        i++;
    }
    //cout << "表长为:  " << i << endl;
    return i;
}

Status 取第i个元素(LinkList L, int i, Elemtype e)
{// GetElem“i”
    LinkList p;
    p = L->next;
    int j = 1;
    while (p && i > j)
    {
        p = p->next;
        j++;
    }
    if (i < 0 || i < j || !p)
        return false;
    e = p->data;
    return true;
}

Status LocateELem(LinkList L, Elemtype e)
{
    //在线性表L中查找值为e的数据元素
    //找到,则返回L中值为e的数据元素的地址,查找失败返回NULL
    auto p = L->next; int i = 1;
    while (p && p->data != e)
    {
        i++;
        if (e == p->data)
        {
            cout << "地址为:  " << p << ";" << endl;
            cout << "位置序号为:  " << i << ";" << endl;
        }
        p = p->next;
    }
    if (p == NULL)
        return NULL;
    return true;
}

Status Listlnsert(LinkList L, int i, Elemtype e)
{//插入(把元素e插到第i个位置结点上)
    auto p = L; int j = 0;
    while (p && j < i - 1)
    {
        p = p->next; ++j;
    }
    if (!p || j > i - 1)
        return false;
    auto s = new Lnode;
    s->data = e;
    s->next = p->next;
    p->next = s;
    return true;
}//Listlnsert_L


2:
修改<合并>函数的函数体:(在前置语句保持不变,不必改动的情况下)

Status Union(Lnode& A, Lnode& B)
{
    for (int i = 1; i <= 求表长(&B); i++)
    {
        int len_A = 求表长(&A);
        Elemtype e;
        LinkList p = &A;
        取第i个元素(&A, i, e);
        if (!LocateELem(&B, e))
            Listlnsert(p, ++len_A, e);
    }
    return true;
}

那么此时,一个让我觉得很有意思(很奇怪)的现象(情况)就发生了

问题:

为什么在前面“&A”和定义中的“LinkList& L”类型匹配不上

但是只要我们把“&A”放到一个新的该类型的变量当中,让该信息以变量的形式在程序中执行

放进去的明明都是同一个东西(&A),凭什么(怎么)原来的时候程序就可以运行了呢???

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值