<数据结构学习>线性表基本操作--集合合并

目录

题目描述

题目:

前置代码:

问题分析

代码头部:

 main函数:

各子函数: 

1、初始化线性表的函数

2、 输出线性表的函数:

3、判断两元素是否相等的函数

 4、合并两集合的函数

 5、寻找L中是否存在和e相同的元素

 6、输出集合元素的函数

解题方法

1、函数int  ListLength( SqList );

2、函数 Status GetElem(SqList L, int i, ElemType &e) ;

 3、函数Status ListInsert( SqList &L, int i, ElemType e );

总结


这篇文章是我开始系统学习算法时为记录学习过程写的,比较适合小白,大佬请跳过。不当之处请大家批评指正。

题目描述

题目:

有两个集合A和B分别用两个线性表LA和LB表示。求一个新的集合 A=A∪B。

输入:两个集合

输出:按照要求合并后的集合。

前置代码:

#include <stdio.h>  
#include <stdlib.h>  
#define LIST_MAX_SIZE  100  //空间初始大小  
#define OK 1  
#define ERROR 0  
  
typedef int ElemType;       //元素的数据类型  
typedef int Status;         //状态。函数返回值   
typedef struct {  
//  ElemType elem[ LIST_MAX_SIZE ]; // 存储空间  
    ElemType * elem;    // 存储空间  
    int  length;        // 当前元素个数  
    int  listsize;      // 能够保存的最大元素数量   
} SqList;  
  
// 以下为函数原型   
Status InitList( SqList & );  
Status ListInsert( SqList &, int, ElemType );   //这是需要你编写的基本操作   
Status GetElem( SqList, int, ElemType & );  //这是需要你编写的基本操作   
int    ListLength( SqList );        //这是需要你编写的基本操作  
Status ListTraverse( SqList &, void (*)( ElemType ) );  
void   ListUnion( SqList &, SqList );  
void   out( ElemType );  
int    equal(ElemType, ElemType );   
Status LocateElem(SqList, ElemType, Status (*)(ElemType,ElemType));  
  
// 以下为函数定义  
Status InitList( SqList & L )   // 建立一个空的线性表 L  
{  
    L.elem = (ElemType *)malloc(LIST_MAX_SIZE*sizeof(ElemType));  
//  if ( !L.elem )  exit(-1);   // 失败则终止程序   
    L.length    = 0;            // 空表长度为0  
    L.listsize  = LIST_MAX_SIZE;  
    return OK;  
}  
  
Status ListTraverse( SqList &L, void (*visit)( ElemType ) )  
{   // 依次对L的每个元素调用函数visit()。若visit()失败,则操作失败  
    int i, L_len = ListLength( L );  
    ElemType e;  
      
    for ( i = 1;  i <= L_len; i++ )  {  
        GetElem(L, i, e);  
        (*visit)( e );  
    }  
    return OK;  
}  
  
int equal(ElemType x, ElemType y)  
{   return x==y;  
}  
  
Status LocateElem( SqList L, ElemType e,  
                   Status (*compare)(ElemType,ElemType) )  
{   //在L中查找与元素 e 满足compare() 的第 1 个元素  
    //返回 L 中第 1 个与 e 满足关系compare( ) 的元素的位序  
    int i = 1;  
    ElemType * p;  
    while ( i<=L.length )  //  
        if  ( (*compare)(e,L.elem[i-1]) ) break;  
        else  i++;  
    if ( i <= L.length )  return i;  // 找到 e,返回位序i  
    else return 0;      //若没有找到,则返回0  
}  
  
void out( ElemType e )  
{   printf("%d,", e);  
}  
  
void ListUnion( SqList &La,  SqList Lb ) //求 A=A∪B  
{   int La_len, Lb_len, i;  
    ElemType e;  
   
    La_len = ListLength( La );       // 求线性表的长度  
    Lb_len = ListLength( Lb );  
    for ( i = 1;  i <= Lb_len;  i++ )  {  
        GetElem(Lb, i, e);  // 取Lb中第i个数据元素赋给e  
        if ( !LocateElem( La, e, equal ) )   
            ListInsert ( La, ++La_len, e ); // La中不存在和 e 相同的数据元素,则插入  
    }  
}  
  
int main()  
{   SqList La, Lb;  
    int n, i;  
    ElemType e;  
      
    InitList( La );  
    InitList( Lb );  
    scanf("%d", &n);        //读入集合A   
    for ( i=0; i<n; i++ )  
    {   scanf("%d", &e);  
        ListInsert( La, i+1, e );  
    }  
    scanf("%d", &n);        //读入集合B   
    for ( i=0; i<n; i++ )  
    {   scanf("%d", &e);  
        ListInsert( Lb, i+1, e );  
    }  
    printf("Output La:");  
    ListTraverse( La, out );  
    printf("\nOutput Lb:");  
    ListTraverse( Lb, out );  
    ListUnion( La, Lb );  
    printf("\nResult La:");  
    ListTraverse( La, out );  
    printf("\n");  
    return OK;  
}  

​

问题分析

首先分析一下前置代码:

代码头部:

我们先看一下代码头部的信息

#include <stdio.h>  
#include <stdlib.h>  
#define LIST_MAX_SIZE  100  //定义最大集合空间的大小  
#define OK 1  
#define ERROR 0  
  
typedef int ElemType;       //元素的数据类型  这里专门把int换一个名的目的是
                            //有些题的集合元素不是int类型,到时候可以一键更换类型。
typedef int Status;         //状态,函数返回值   

typedef struct    //结构体设置
{  
    ElemType * elem;    // 存储空间  
    int  length;        // 当前元素个数  
    int  listsize;      // 能够保存的最大元素数量   
} SqList;  

 main函数:

分析前置代码时,我们最好先读一下main函数,搞明白代码大体在做一件什么事情,把做事的流程搞清楚,再去读具体各部分怎么实现的代码。 

int main()  
{   SqList La, Lb;  //建立线性表La,Lb
    int n, i;  
    ElemType e;  
      
    InitList( La );  //初始化线性表La
    InitList( Lb );  //初始化线性表Lb
    scanf("%d", &n);        //读入集合A   
    for ( i=0; i<n; i++ )  
    {   scanf("%d", &e);  
        ListInsert( La, i+1, e );  //向线性表La中逐个插入元素
    }  
    scanf("%d", &n);        //读入集合B   
    for ( i=0; i<n; i++ )  
    {   scanf("%d", &e);  
        ListInsert( Lb, i+1, e );  //向线性表Lb中逐个插入元素
    }  
    printf("Output La:");  //输出线性表La
    ListTraverse( La, out ); 
    printf("\nOutput Lb:");  //输出线性表Lb
    ListTraverse( Lb, out );  
    ListUnion( La, Lb );  //合并线性表La,Lb
    printf("\nResult La:");  //输出合并后的线性表La
    ListTraverse( La, out );  
    printf("\n");  
    return OK;  
}  

各子函数: 

接着我们来看一下各个函数具体怎么实现:

1、初始化线性表的函数

Status InitList( SqList & L )   // 建立一个空的线性表 L  
{  
    L.elem = (ElemType *)malloc(LIST_MAX_SIZE*sizeof(ElemType));  //分配存储空间
//  if ( !L.elem )  exit(-1);   // 失败则终止程序   
    L.length    = 0;            // 空表长度置为0  
    L.listsize  = LIST_MAX_SIZE;  //设置表的最大容量
    return OK;  //成功建立
}

2、 输出线性表的函数:

void out( ElemType e )  
{   printf("%d,", e);  //输出表中所存元素
}  

3、判断两元素是否相等的函数

int equal(ElemType x, ElemType y)  
{   return x==y;  //若相等,返回1,否则返回0
} 

 4、合并两集合的函数

void ListUnion( SqList &La,  SqList Lb ) //求 A=A∪B  
{   int La_len, Lb_len, i;  
    ElemType e;  
   
    La_len = ListLength( La );       // 求线性表的长度  
    Lb_len = ListLength( Lb );  
    for ( i = 1;  i <= Lb_len;  i++ )  
    {  
        GetElem(Lb, i, e);  // 取Lb中第i个数据元素赋给e  
        if ( !LocateElem( La, e, equal ) )   //寻找La中是否存在和e相同的数据元素
            ListInsert ( La, ++La_len, e ); // 若不存在,则把e插入La中  
    }  
}  

 5、寻找L中是否存在和e相同的元素

Status LocateElem( SqList L, ElemType e,  Status (*compare)(ElemType,ElemType) )  
{ 
    int i = 1;  
    ElemType * p;  
    while ( i<=L.length )  //从头开始遍历L集合中的元素
        if  ( (*compare)(e,L.elem[i-1]) ) break;  //如果找到了和e相同的元素,立刻退出
        else  i++;  //否则继续遍历
    if ( i <= L.length )  return i;  // 若i小于集合容量,说明是找到了和e相同的元素后退出的,
                                     //此时返回位序i  
    else return 0;      //若没有找到,则返回0  
}  

 6、输出集合元素的函数

Status ListTraverse( SqList &L, void (*visit)( ElemType ) )  
{   // 其实相当于输出操作。可以看main函数里对此函数的使用,是和out函数结合了一下
    int i, L_len = ListLength( L );  
    ElemType e;  
      
    for ( i = 1;  i <= L_len; i++ )  //在 L集合的容量范围内遍历
    {  
        GetElem(L, i, e);  //得到每一个元素
        (*visit)( e );  //输出每一个元素
    }  
    return OK;  
}  

 下面我们需要考虑的是怎么编写空着的三个函数

解题方法

1、函数int  ListLength( SqList );

这个函数的编写是最简单的,因为定义结构体时已经设计了长度这个成员,所以直接用即可。

int ListLength(SqList L) //求集合容量
{    
    return L.length; //直接利用结构体里的length
}

2、函数 Status GetElem(SqList L, int i, ElemType &e) ;

我们可以看到,上述预置函数分析里的子函数6“输出集合元素的函数”里有用到这个函数。

它是从i=1遍历到i=L_len,逐个输出集合中的元素。

我们知道,结构体读入时是从i=0开始的,所以我们取用元素并将它赋给e时需要用下标[i-1]。

Status GetElem(SqList L, int i, ElemType &e) //将集合里的某元素赋给e
{
    e=L.elem[i-1]; //把集合里的某元素赋给e
} 

 3、函数Status ListInsert( SqList &L, int i, ElemType e );

往集合中插入元素的函数。插入时,把插入元素目标位置及之后的位置上的元素都往后移动1个,再把该元素插到目标位置。

注意位置和下标的关系。

Status ListInsert( SqList &L, int i, ElemType e ) 
{   //在顺序线性表L中第 i (1≤i≤L.length+1)个位置之前插入元素e
	int j;
 	for(j=L.length;j>=i;j--)  //把第i个元素及以后的元素逐一往后移动
 	{
 		L.elem[i]=L.elem[i-1];  //注意:元素从位置1开始,但下标从0开始
 	}
    L.elem[i-1]=e;  //在第i个位置插入该元素(下标比位置少1)
    L.length++;  //插入后集合容量增1
}

总结

1、通过这道题,我们学会了怎样读、分析前置代码。从总体功能入手,理清总体思路,再看具体实现。从包含函数最多的函数开始读,先抓函数的流程和功能。

2、解决要编写的函数时,我们从它的功能入手,对照着其他引用过他们的函数分析,从而完成编写。编写过程中一定要注意细节!!比如下标的问题。

3、我们可以多分析一下线性表的使用,把线性表常用函数的功能及实现代码熟记于心。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值