集合抽象数据类型的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);
}
集合抽象数据类型的C语言实现的更多相关文章
- 数据结构 集合_集合(数学)抽象数据类型的C语言实现
链表是实现集合的一种理想的方式.将List以typedef的方式重命名为Set.这样做能保留链表简洁的特性,还能使集合具有了一些多态的特性. 使用这种方法的最大好处就是可以使用list_next来遍历 ...
- C语言泛型编程--抽象数据类型
一.数据类型: 在任何编程语言中,数据类型作为一个整体,ANSI-C包含的类型为:int.double.char……,程序员很少满意语言本身提供的数据类型,一个简单的办法就是构造类似:array.st ...
- 采用C/C++语言如何实现复数抽象数据类型Complex
记录一下! 采用C/C++语言如何实现复数抽象数据类型Complex #include <stdio.h> typedef struct Complex { double e1; // 实 ...
- C语言抽象数据类型ADT
根据编程的问题匹配合适的数据类型.数据项连接构成了链表,定义了一个结构代表单独的项.设计了一些方法把一系列结构构成一个链表.本质上,我们使用C语言的功能设计了一种符合程序要求的新的数据类型.但是上述的 ...
- ORACLE抽象数据类型
ORACLE抽象数据类型 *抽象数据类型*/1,抽象数据类型 概念包含一个或多个子类型的数据类型不局限于ORACLE的标准数据类型可以用于其他数据类型中 2,创建抽象数据类型 的语法(必须用NOT F ...
- 【Python&数据结构】 抽象数据类型 Python类机制和异常
这篇是<数据结构与算法Python语言描述>的笔记,但是大头在Python类机制和面向对象编程的说明上面.我也不知道该放什么分类了..总之之前也没怎么认真接触过基于类而不是独立函数的Pyt ...
- 抽象数据类型ADT
ADT(Abstract Data Type) 类型由什么组成? 一个类型(type)指定两类信息,一个属性集和一个操作集. 假设要定义一个新的数据类型.首先,要提供存储数据的方式,可能是通过设计一个 ...
- ADT(abstract data types)抽象数据类型
1.What is it? An abstract data type is a set of objects together with a set of operations. 抽象数据类型是带有 ...
- Week1绪论--抽象数据类型
一.作业题目 1.构造有理数T,元素e1,e2分别被赋以分子.分母值 2.销毁有理数T 3.用e(引用类型参数)返回有理数T的分子或分母,当入参i为1时返回分子, i为2是返回分母. 4.将有理数T的 ...
随机推荐
- SpringMVC入门学习三
今天是Springmvc学习的第三天,今天我将主要介绍一下: 常用注解的使用 关于非post.get请求的处理 文件上传与下载 拦截器 常用注解的使用 老大在此 @Controller @Cont ...
- Perl分片技术
分片(slice) 在perl中,如果想要取得一部分变量.一部分列表内容.一部分hash内容,可以采用分片(切片)的方式. 注意,perl并未提供字符串的切片方式,但可以使用内置函数substr()来 ...
- React Fiber源码分析 第一篇
先附上流程图一张 先由babel编译, 调用reactDOM.render,入参为element, container, callback, 打印出来可以看到element,container,cal ...
- 第一册:lesson twenty-one.
原文:Which book? A:Give me a book please,B. B:Which book? This one? A:No,not that one. The red one. B: ...
- 【转载】SQL语句用一个表的数据更新另一个表
在Sqlserver的维护更新操作中,有时候涉及到Update操作,其中有一种情况是根据特定的条件,以一个表中的数据更新另一个表的数据,此时涉及到两个表之间的关系以及操作,此处介绍2种更新方法. (1 ...
- Windows server 2008 R2端口转发
查询配置了转发的端口 netsh interface portproxy show v4tov4 配置转发(所有ip访问192.168.0.99的1001端口均指向1953端口) netsh inte ...
- element UI Cascader 级联选择器 编辑 修改 数组 路径 问题(转载)
来源:https://segmentfault.com/a/1190000014827485 element UI的Cascader级联选择器编辑时 vue.js element-ui 2 eleme ...
- git 创建本地分支与远程分支
早上抽空整理了下git常用操作,偶尔看看加深下印象吧: 如果github上已经有master分支 和dev分支 在本地 git checkout -b dev 新建并切换到本地dev分支 git pu ...
- Mybatis foreach标签含义
背景 考虑以下场景: InfoTable(信息表): Name Gender Age Score 张三 男 21 90 李四 女 20 87 王五 男 22 92 赵六 女 19 94 孙七 女 23 ...
- Codeforces Round #309 (Div. 2)
A. Kyoya and Photobooks Kyoya Ootori is selling photobooks of the Ouran High School Host Club. He ha ...