数据结构 集合_集合(数学)抽象数据类型的C语言实现

链表是实现集合的一种理想的方式。将List以typedef的方式重命名为Set。这样做能保留链表简洁的特性,还能使集合具有了一些多态的特性。

使用这种方法的最大好处就是可以使用list_next来遍历一个集合,使用list_rem_next来移除一个成员,而不用根据成员所存储的数据来标识它。

我们先来查看一下集合抽象数据类型头文件的内容:

示例1:集合(抽象数据类型)头文件

#ifndef SET_H
#define SET_H 

#include <stdlib.h>
#include "list.h"
/*将集合定义成List结构*/
typedef List Set;
/*集合的初始化*/
void set_init(Set *set,int (match*)(const void *key1,const void *key2),void(*destroy)(void *data));
/*集合销毁,定义成链表销毁函数*/
#define set_destroy List_destroy
/*向集合中插入元素*/
int set_insert(Set *set, const void *data);
/*从集合中移除元素*/
int set_remove(Set *set, void **data);
/*求集合的并集*/
int set_union(Set *setu, const Set *set1, const Set *set2);
/*求集合的交集*/
int set_intersection(Set *seti, const Set *set1,const Set *set2);
/*求集合的差集*/
int set_difference(Set *setd, const Set *set1,const Set *set2);
/*判断成员是否属于集合*/
int set_is_member(const Set *set, const void *data);
/*判断子集*/
int set_is_subset(const Set *set1, const Set *set2);
/*判断集合是否相等*/
int set_is_equal(const Set *set1, const Set *set2);
/*集合中元素的个数*/
#define set_size(set) ((set)->size)

#endif

下面是各种操作的具体实现:

示例2:集合抽象数据类型的实现

#include <stdlib.h>
#include <string.h>
#include "list.h"
#include "set.h"

/*set_init  初始化一个集合*/
void set_init(Set *set,int(*match)(const void *key1,const void *key2), void(*destroy)(void *data))
{
    /*调用list_init*/
    list_init(set,destroy);
    /*单独初始化match成员*/
    set->match = match;

    return;
}

/*set_insert  向集合中插入一个成员*/
int set_insert(Set *set,const void *data)
{
    /*不能向集合中插入已有成员*/    if(set_is_member(set,data))        return -1;    /*调用list_ins_next插入元素至尾端*/    return list_ins_next(set,list_tail(set),data);}

/*set_remove  移除元素*/int set_remove(Set *set,void **data){    ListElmt *member, *prev;    /*查找要移除的成员*/    prev=NULL;    /*遍历链表*/    for(member=list_head(set); member != NULL; member = list_next(member))    {        if(set->match(*data,(list_data(member)))            break;        prev=member;  /*prev刚好指向匹配成功的成员的前一个成员*/    }

/*没有找到成员则返回*/    if(member==NULL)        return -1;    /*移除成员*/    return list_rem_next(set,prev,data);}

/*set_union 求解两个集合的并集*/int set_union(Set *setu,const Set *set1,const Set *set2){    ListElmt *member;    void *data;

/*初始化一个并集集合*/    set_init(setu,set1->match,NULL);

/*将集合1的内容插入并集*/    for(member=list_head(set1);member!=NULL;member=list_next(member))    {        data=list_data(member);        if(list_ins_next(setu,list_tail(setu),data)!=0)            {                set_destroy(setu);                return -1;             }    }

/*插入集合2的成员*/    for(member=list_head(set2);member!=NULL;member=list_next(member))    {        if(set_is_member(set1,list_data(member)))        {            continue;        }        else        {            data=list_data(member);            if(list_ins_next(setu,list_tail(setu),data))!=0)            {                set_destroy(setu);                return -1;            }        }    }    return 0;}

/*set_intersection  求解两个集合的交集*/int set_intersection(Set *seti,const Set *set1,const Set *set2){    ListElmt *member;    void *data;

/*初始化交集集合*/    set_init(seti,set1->match,NULL);

/*同时在两个集合中出现的元素将被插入交集集合中*/    for(member=list_head(set1);member!=NULL;list_next(member))    {        if(set_is_member(set2,list_data(member))        {            data=list_data(member);            if(list_ins_next(seti,list_tail(seti),data))!=0)            {                set_destroy(seti);                return -1;            {        }    }return 0;}
/*set_difference  求解两个集合的差集*/int set_intersection(Set *setd,const Set *set1,const Set *set2){    ListElmt *member;    void *data;

/*初始化差集集合*/    set_init(setd,set1->match,NULL);

/*不同时在两个集合中出现的元素将被插入差集集合中*/    for(member=list_head(set1);member!=NULL;list_next(member))    {        if( ! set_is_member(set2,list_data(member))        {            data=list_data(member);            if(list_ins_next(setd,list_tail(setd),data))!=0)            {                set_destroy(setd);                return -1;            {        }    }return 0;}

/*set_is_member  判断由data指定的成员是否在由set指定的集合中*/int set_is_member(const Set *set,void *data){    ListElmt *member;

for(member=list_head(set);member!=NULL;list_next(member))    {        if(set->match(data,list_data(member))        return 1;    }    return 0;}

/*set_is_subset 判断集合set1是否是集合set2的子集*/int set_is_subset(const Set *set1,const Set *set2){    ListElmt *member;

/*首先排除集合1成员数量大于集合2成员数量的情况*/    if(set_size(set1)>set_size(set2))        return 0;

/*如果set1的成员不都在set2中,则判断不成立,除此成立*/    for(member=list_head(set1);member!=NULL;list_next(member))    {        if( !set_is_member(set2,list_data(member)))        {            return 0;        }    }    return 1;}

/*set_is_equal  判断两个集合是否相等*/int set_is_equal(const Set *set1,const Set *set2){    /*首先排除两个集合成员数量不相等的情况*/    if(set_size(set1) != set_size(set2))    return 0;

/*两个集合成员数量相等,且一个集合是另一个集合的子集时,这两个集合相等*/    return  set_is_subset(set1,set2);}
时间: 2024-08-03 14:55:20

数据结构 集合_集合(数学)抽象数据类型的C语言实现的相关文章

基本数据类型(字符串_数字_列表_元祖_字典_集合)

基本数据类型(字符串_数字_列表_元祖_字典_集合) 1.字符串 2.数字 除了布尔类型外,int.long.float和complex都可以使用的运算为:加.减.乘.除.整除.幂运算和取余 3.列表和元组 列表的内容可变,可以包含任意对象,使用中括号表示.元组的内容不可变,可以包含任意对象,使用圆括号表示.元组 1 l = [1, 2, 3, '4', '5'] # 列表 2 l = list((1, 2, 3, '4', '5')) 3 4 t = (1, 2, 3, '4', '5') #

【Python&amp;数据结构】 抽象数据类型 Python类机制和异常

这篇是<数据结构与算法Python语言描述>的笔记,但是大头在Python类机制和面向对象编程的说明上面.我也不知道该放什么分类了..总之之前也没怎么认真接触过基于类而不是独立函数的Python编程,借着本次机会仔细学习一下. 抽象数据类型 最开始的计算机语言,关注的都是如何更加有效率地计算,可以说其目的是计算层面的抽象.然而随着这个行业的不断发展,计算机不仅仅用于计算,开发也不仅只关注计算过程了,数据层面的抽象也变得同样重要.虽然计算机语言一开始就有对数据的抽象,但是那些都只是对一些最基本的

黑马程序员_集合

集合1.集合和对象数组的区别: 数组的长度不可变,集合的可变: 数组可以存储基本数据类型和对象,集合只能存储对象. 集合的框架图 集合派系的顶层接口Collection1.Collection集合存储对象的方法: add(E e)将元素存储到集合中 addAll(Collection c)将一个集合添加到另外的集合中2.Collection集合提取对象的方法: 通过迭代器iterator中的方法:hasNext()和next()来取出 Iterator it=new iterator(); wh

用js来实现那些数据结构09(集合01-集合的实现)

说到集合,第一个想到的就是中学学到的那个数学概念:集合.在我们开始集合相关的js实现前,我们有必要来了解一下什么是集合以及集合的数学概念. 好吧,我们一起来复习一下早就被我们遗忘的集合. 集合是由一组无序且唯一的项组成的.集合这个数据结构使用了与有限集合相同的数学概念.在数学中,集合是指具有某种特定性质的具体的或抽象的对象汇总成的集体,这些对象称为该集合的元素. 比如,一个包括0到9十个数字的集合表示为:N = {0,1,2,3,4,5,6,7,8,9}.集合中的对象列表用{}(大括号)包围.还

我的学习之路_第七章_list集合,set集合

[List集合] List集合存储数据的结构 堆栈:先进后出(先存进来的元素,最后取出) 例如:子弹压进弹夹 队列:先进先出(先存进来的元素,先取出来) 例如:排队 『ArrayList』 数组:查找元素快,增删元素慢 有索引 『LinkedList』 链表:查找元素慢,增删元素快 没有索引,连接的是节点 例如:手拉手 List接口方法_带索引的 add(int index ,E e) 在指定的索引上添加元素 remover(int index) 移除并返回指定索引上的元素 set(int in

Redis数据结构之整数集合

整数集合是Redis用于保存整数值的集合抽象数据结构,它可以保存类型为int16_t .int32_t或者int64_t的整数值,并且保证集合中不会出现重复元素. 一.整数集合数据结构定义 参数说明:contents:contents数组是整数集合的底层实现,整数集合的每个元素都是contents数组的一个数组项,各个项在数组中按值的大小从小到大有序地排列,并且数组中不包含任何重复项.length:记录了整数集合包含的元素数量,也即是contents数组的长度.encoding:决定了conte

20_集合_第20天(Map、可变参数、Collections)_讲义

今日内容介绍 1.Map接口 2.模拟斗地主洗牌发牌 01Map集合概述 A:Map集合概述: 我们通过查看Map接口描述,发现Map接口下的集合与Collection接口下的集合,它们存储数据的形式不同 ? a:Collection中的集合,元素是孤立存在的(理解为单身),向集合中存储元素采用一个个元素的方式存储. ? b:Map中的集合,元素是成对存在的(理解为夫妻).每个元素由键与值两部分组成,通过键可以找对所对应的值. ? Collection中的集合称为单列集合,Map中的集合称为双列

python基础操作_集合_三元运算

#使用操作文件的时候,可以使用with函数#with open('E:\info.txt','a+') as fr#fr这个值可以是任意值# :#for line in fr:'''with open('a.txt','r') as f: f.read()上下这两行代码是一样的原理f=open('a.txt','r')f.read()f.close()''''''f=open('a.txt','a')f.seek(0)移动文件指针到第一个f.truncate()清空文件的内容'''#同时打开两个

[redis数据结构] 之 set集合

在redis中,集合类型有两种,一种是无序.不重复的(set),另一种是有序的(zset):本文讲述无序集合的语法使用规则.理解redis中的集合类型,可以类比于数学中的集合,集合存在三种关系:交集.并集.差集,其中差集的概念有一点的出入,详细见语法使用描述. 1.添加元素 语法:sadd [set集合] [元素] 范例:sadd set1 one       sadd set1 one 阐述:创建set1结合,并添加one元素到集合中,如果set1已经存在,那么仅仅添加元素过程:第二次添加on