精华内容
下载资源
问答
  • 三种方式实现 Python 中的集合的、补运算一 背景集合这个概念在我们高中阶段就有所了解,毕业已多年,我们一起回顾一下几个集合相关的基本概念吧?集合是指具有某种特定性质的具体的或抽象的对象汇总而成的...

    三种方式实现 Python 中的集合的交、并、补运算

    一 背景

    集合这个概念在我们高中阶段就有所了解,毕业已多年,我们一起回顾一下几个集合相关的基本概念吧?

    集合是指具有某种特定性质的具体的或抽象的对象汇总而成的集体。其中,构成集合的这些对象则称为该集合的元素。

    集合具有以下几种性质:

    确定性

    给定一个集合,任给一个元素,该元素或者属于或者不属于该集合,二者必居其一,不允许有模棱两可的情况出现。

    互异性

    一个集合中,任何两个元素都认为是不相同的,即每个元素只能出现一次。有时需要对同一元素出现多次的情形进行刻画,可以使用多重集,其中的元素允许出现多次。

    无序性

    一个集合中,每个元素的地位都是相同的,元素之间是无序的。集合上可以定义序关系,定义了序关系后,元素之间就可以按照序关系排序。但就集合本身的特性而言,元素之间没有必然的序。

    交集定义:由属于A且属于B的相同元素组成的集合,记作A∩B(或B∩A),读作“A交B”(或“B交A”),即A∩B={x|x∈A,且x∈B}, 如右图所示。注意交集越交越少。若A包含B,则A∩B=B,A∪B=A。

    并集定义:由所有属于集合A或属于集合B的元素所组成的集合,记作A∪B(或B∪A),读作“A并B”(或“B并A”),即A∪B={x|x∈A,或x∈B},注意并集越并越多,这与交集的情况正相反。

    补集

    补集又可分为相对补集和绝对补集。

    相对补集定义:由属于A而不属于B的元素组成的集合,称为B关于A的相对补集,记作A-B或AB,即A-B={x|x∈A,且x∉B'}。

    绝对补集定义:A关于全集合U的相对补集称作A的绝对补集,记作A'或∁u(A)或~A。有U'=Φ;Φ'=U。

    在日常工作中,集合的交并补运算最为常见。例如:多个文件夹下的文件合并到一个文件夹、找出两个文件夹内名称相同、相异的文件。以以下两个列表来进行实践(lst_a 简称为集合 A,lst_b 简称为集合 B):

    lst_a = [1,2,3,4,5]

    lst_b = [3,4,5,6,7]

    二 实践过程

    2.1 通过 Python 的推导式来实现

    求集合 A 与集合 B 的交集

    lst_a = [1,2,3,4,5]

    lst_b = [3,4,5,6,7]

    lst_c = [x for x in lst_b if x in lst_a]

    # lst_c = [x for x in lst_a if x in lst_b]

    print(lst_c)

    运行结果:

    [3, 4, 5]

    求集合 A 与集合 B 的并集

    lst_a = [1,2,3,4,5]

    lst_b = [3,4,5,6,7]

    lst_c = lst_a + [x for x in lst_b if x not in lst_a]

    print(lst_c)

    运行结果:

    [1, 2, 3, 4, 5, 6, 7]

    集合 A 关于集合 B 的补集(B - A)

    lst_a = [1,2,3,4,5]

    lst_b = [3,4,5,6,7]

    lst_c = [x for x in lst_b if x not in lst_a]

    print(lst_c)

    运行结果:

    [6, 7]

    集合 B 关于集合 A 的补集(A - B)

    lst_a = [1,2,3,4,5]

    lst_b = [3,4,5,6,7]

    lst_c = [x for x in lst_a if x not in lst_b]

    print(lst_c)

    运行结果:

    [1, 2]

    2.2 通过 Python 对集合的内置方法来实现

    需要将列表转换为集合才能使用集合内置方法。

    求集合 A 与集合 B 的交集

    lst_a = [1,2,3,4,5]

    lst_b = [3,4,5,6,7]

    set_a = set(lst_a)

    set_b = set(lst_b)

    set_c = set_a.intersection(lst_b)

    print(list(set_c))

    运行结果:

    [3, 4, 5]

    求集合 A 与集合 B 的并集

    lst_a = [1,2,3,4,5]

    lst_b = [3,4,5,6,7]

    set_a = set(lst_a)

    set_b = set(lst_b)

    set_c = set_a.union(set_b)

    print(list(set_c))

    运行结果:

    [1, 2, 3, 4, 5, 6, 7]

    集合 B 关于集合 A 的补集(A - B)

    lst_a = [1,2,3,4,5]

    lst_b = [3,4,5,6,7]

    set_a = set(lst_a)

    set_b = set(lst_b)

    set_c = set_a.difference(set_b)

    print(list(set_c))

    运行结果:

    [1, 2]

    集合 A 关于集合 B 的补集(B - A)

    lst_a = [1,2,3,4,5]

    lst_b = [3,4,5,6,7]

    set_a = set(lst_a)

    set_b = set(lst_b)

    set_c = set_b.difference(set_a)

    print(list(set_c))

    运行结果:

    [6, 7]

    2.3 通过 Python 按位运算来实现

    需要将列表转换为集合才能使用集合内置方法。

    求集合 A 与集合 B 的交集

    lst_a = [1,2,3,4,5]

    lst_b = [3,4,5,6,7]

    set_a = set(lst_a)

    set_b = set(lst_b)

    set_c = set_a & set_b

    print(list(set_c))

    运行结果:

    [3, 4, 5]

    求集合 A 与集合 B 的并集

    lst_a = [1,2,3,4,5]

    lst_b = [3,4,5,6,7]

    set_a = set(lst_a)

    set_b = set(lst_b)

    set_c = set_a | set_b

    print(list(set_c))

    运行结果:

    [1, 2, 3, 4, 5, 6, 7]

    集合 B 关于集合 A 的补集(A - B)

    lst_a = [1,2,3,4,5]

    lst_b = [3,4,5,6,7]

    set_a = set(lst_a)

    set_b = set(lst_b)

    set_c = set_a - set_b

    print(list(set_c))

    运行结果:

    [1, 2]

    集合 A 关于集合 B 的补集(B - A)

    lst_a = [1,2,3,4,5]

    lst_b = [3,4,5,6,7]

    set_a = set(lst_a)

    set_b = set(lst_b)

    set_c = set_b - set_a

    print(list(set_c))

    运行结果:

    [6, 7]

    集合 A 与集合 B 的全集除去交集

    lst_a = [1,2,3,4,5]

    lst_b = [3,4,5,6,7]

    set_a = set(lst_a)

    set_b = set(lst_b)

    set_c = set_b ^ set_a

    print(list(set_c))

    运行结果:

    [1, 2, 6, 7]

    三 总结

    3.1 在处理类似集合的数据时,需要注意集合与列表的相互转换,根据其特性,要会灵活使用;

    3.2 集合的内置方法平时较少使用,但是使用起来还是比较方便的;

    3.3 按位运算符在集合的运算中的应用简洁明了,建议平时稍加注意;

    3.4 Python 中的推导式在列表、集合、字典等多种数据结构中均适用,使用恰当时往往能事半功倍;

    3.5 由于列表在实际使用中较为常见,本文中的例子重点使用了列表来展示。

    展开全文
  • 这篇文章主要介绍了Python数组并集交集集代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下并集a = ["a", "b", "c", "d"]b = ["b", "e"]c = ["a", "b",...

    这篇文章主要介绍了Python数组并集交集补集代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    并集

    a = ["a", "b", "c", "d"]

    b = ["b", "e"]

    c = ["a", "b", "c", "d", "e"]

    # 并

    # 合并数组

    a.extend(b)

    # 去重

    array = list(set(a))

    print(array)

    # 第二种方法

    array = list(set(a)|set(b))

    print(array)

    打印结果:

    ['c', 'a', 'b', 'd', 'e']

    ['c', 'a', 'b', 'd', 'e']

    交集

    a = ["a", "b", "c", "d"]

    b = ["b", "e"]

    c = ["a", "b", "c", "d", "e"]

    # 交

    array = list(set(a) & set(b))

    print(array)

    打印结果:

    ['b', 'e']

    补集

    a = ["a", "b", "c", "d"]

    b = ["b", "e"]

    c = ["a", "b", "c", "d", "e"]

    # 补

    print(set(c))

    print(set(a))

    array = list(set(c)-set(a))

    print(array)

    打印结果:

    ['e']

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持聚米学院。

    展开全文
  • 集合符号在很多的数学领域都会用到,其基本的集合运算可以分为这三种。但是一些用户朋友们在编辑文档的时候想输入集合符号这个时候就需要用到数学公式编辑器MathType,但是很多人能够快速地编辑出交集与...

    集合符号在很多的数学领域都会用到,其基本的集合运算可以分为交、并、补这三种。但是一些用户朋友们在编辑文档的时候想输入集合符号这个时候就需要用到数学公式编辑器MathType,但是很多人能够快速地编辑出交集与并集的符号,补集符号却不能编辑出来。下面我们就针对这个问题来给大家分享一下怎么在MathType中输入补集符号。

    具体操作步骤如下:

    1.按照使用习惯打开MathType公式编辑器,进入到编辑公式界面。可以是从word中打开,也可以是直接双击桌面图标打开,都没有关系。

    2.打开MathType后,在工作界面进行相应的编辑的,将光标放在需要输入补集符号的地方,移动鼠标到MathType菜单栏中,选择“编辑”——“插入符号”命令。

    MathType插入符号 
    点击“编辑”——“插入符号”

    3.在弹出的“插入符号”对话框中,在“查看”的下拉菜单中选择“描述”,其它默认设置不需要改变,在下方的符号面板中拉动滚动条,找到补集符号,点击进行插入。

    MathType插入符号 
    在符号面板中拉动滚动条找到补集符号后点击插入

    4.回到MathType编辑界面中,在补集后面,在使用一个下标模板。在MathType工具栏模板中点击选择“上标下标模板”——“下标”。然后在下标的输入框中输入大写的u,这样一个完整的补集符号就输入完成了。

    MathType补集符号 
    在补集符号后面使用下标模板

    以上内容向大家介绍了MathType补集符号的编辑方法,这个编辑并不复杂,但是需要自己仔细地找一找,有些人可能直接就利用大写的C字母再加一个下脚标模板就算是完成了补集符号的输入,但是这样的符号是不符合规范的,也是不能被认可的一种输入方式。

    本文源自:http://www.mathtype.cn/jiqiao/buji-fuhao.html

    转载于:https://www.cnblogs.com/MathType/p/5755583.html

    展开全文
  • 集合的和差运算(C语言)

    千次阅读 多人点赞 2020-11-30 21:44:15
    编制一个能演示执行集合的和差运算的程序。 二、问题分析和任务定义 1. 需求分析(完成的任务、提供的功能) (1)集合的元素限定为小写字母字符 [‘a’…’z’] 。 (2)集合的元素判定和子集判定运算。 (3)求...

    这是我的课程设计,写了蛮久的了,当时搜好多都搜不到,既然已经完成了,就拿出来和大家一起分享讨论,这也是我的第一篇原创文章。(自己水平太有限了,无法跟这里的大佬们相比,但是可以一起交流学习嘛~ 有错误请多指出哦~)
    如果觉得有帮助一定要点赞哦~ ~ ~ ~ ~

    • 文章后面有代码哦~~

    一、课题的背景与意义

    编制一个能演示执行集合的并、交和差运算的程序。

    二、问题分析和任务定义

    1. 需求分析(完成的任务、提供的功能)

    (1)集合的元素限定为小写字母字符 [‘a’…’z’] 。
    (2)集合的元素判定和子集判定运算。
    (3)求集合的补集。
    (4)集合的混合运算表达式求值。
    (5)集合的元素类型推广到其他类型,甚至任意类型

    2. 重点和难点

    (1)如何将元素只限定于小写字母,不包括其它元素
    (2)输入的集合中含有空集,该如何判断
    (3)混合运算表达式的计算,当表达式中含有取反符号“~”时,该怎么处理
    (4)表达式中含有圆括号时该怎么处理
    (5)如何判断表达式的输入不符合规范,当不符合规范的时候该如何让其运行

    3. 测试数据

    (1)Set1=“magazine”,Set2=“paper”,
    Set1∪Set2=“aegimnprz”,Setl ∩Set2=“ae”,Set1-Set2=“gimnz”。
    (2) Set1= " 012oper4a6tion89",Set2=“error data”,
    Set1∪Set2=“adeinoprt”,Setl ∩Set2=“aeort”,Set1-Set2=“inp”。

    三、概要设计

    1. 系统的设计与分析(系统流程图)

    开始程序时,进行集合元素类型选择,当输入数字“1”时将进行小写字母集合运算,当输入数字“2”时将进行任意可显示元素的运算。选择结束之后,根据提示,输入两个集合,按下回车后即可进行相应的集合运算操作。当选择元素查找选项时,根据提示输入要寻找的元素,结构显示AB集合中是否含有。当选择混合运算选项时,按照表达式规则正确输入集合表达式,按下回车后,显示结果。
    图1 系统流程图

    2.数据结构的选择

    本实验使用的是链表结构。由于无法确定输入集合的长度,因此采用动态链表进行储存比较方便,由于运算中经常出现添加、删除的操作,使用链表将会将时间复杂度降低,不需要像顺序表影响其他元素的位置。链表的时间复杂度依据操作进行,当不进行排序时时间复杂度为0,空间复杂度也为0。
    排序使用的是简单选择排序,给每一个位置选择当前最小元素,由于集合中不存在重复的元素,因此在输入的时候,就将重复的元素剔除。时间复杂度为O(),空间复杂度则为0。
    在进行混合运算时采用堆栈操作,建立两个堆栈类型,一个存放数据,一个用于存放符号。堆栈是后进先出,符合表达式的运算顺序,即优先级高的后出,优先级低的先进行运算,并将结果存放在数据栈中。

    四、详细设计

    1.数据类型的定义
    1)集合的结构定义
    /*链表集合*/
    typedef struct PNode {
    	char data;
    	struct PNode* next;
    }PNode, * PLink;
    /* 顺序栈结构(符号栈) */
    
    2)顺序表的结构定义,方便之后进行混合运算表达式的求值
    typedef struct
    {
    	SElemType data[MAXSIZE];
    	int top; /* 用于栈顶指针 */
    }SqStack;
    /* 顺序栈结构(集合栈) */
    typedef struct
    {
    	PLink data[MAXSIZE];
    	int top; /* 用于栈顶指针 */
    }PLinkStack;
    
    2.核心算法的设计与实现
    1)集合的并

    对A集合进行调整,将不重复的内容放入集合C中,然后再对B集合进行调整,将补重复的内容放入到C集合中。主要通过while循环进行控制。采用含有头结点的链表以及头插法。如图 2所示
    图2 集合的并

    2)集合的交集

    对集合A和B同时进行遍历,以集合B为模板,将集合A中的一个元素与集合B中的所有元素进行比较,若有相同的元素则插入到集合C中,并在插入之前再判断一下集合C中是否已有该元素,如果已有即不尽兴插入,否则用头插法进行插入。如图 3所示图3 集合的交集

    3)集合的差集

    与集合的交集遍历类似,将集合A和集合B同时进行遍历,当两集合中含有相等的元素则跳出,让集合A的下一个元素一次和集合B进行遍历,只有当集合B全部遍历完了才说明有不同的元素,并最后再在集合C中进行判断,查看是否有重复的元素。如图 4所示。图4集合的差集

    4)集合的补集

    求集合的补集时需要分情况讨论,当限定元素只是小写字母的时候,其全集也就是‘a’~‘z’,但当其全集是任意类型的时候,全集的范围就会更大。而补集的求解则是利用ASCII码来进行判断,当元素不存在时,就调用函数进行元素的添加,也就是链表的增加。如图 5所示
    图5集合的补集

    5)排序

    采用的是简单排序算法,每一次递归都确定一个最小的元素。

    6)混合运算表达式

    在对混合运算的表达式的解析的过程中,需要使用到的是栈的应用。混合表达式的运算中需要对的输入的表达式进行规范性的判断,使用的是if-else语句进行判断。具体规则参照表 1运算式正确性的判断条件

    i i+1
    A B 只能是+、-、*、’\0’、)
    ~ 只能是A、B、(
    + - * 不能是+、-、*、’\0’、)
    ( 只能是A、B、~
    ) 只能是+、-、*、’\0’

    五、实验参考代码(核心代码及注释)

    1)集合的并
    void    and (PLink L1, PLink L2, PLink L3) {
    	if (L3->next != NULL)
    		clearList(L3);
    	PLink p, q, s;
    	//对空集的操作
    	if (!L1 || !L2) {
    		if (!L1) {
    			L3 = L2;
    		}
    		else if (!L2) {
    			L3 = L1;
    		}
    		else {
    			L3 = L1;
    		}
    	}
    	//对1号插入3中
    	p = L1->next;
    	while (p) {
    		q = L3->next;
    		while (q && (q->data != p->data)) {//C3号中不含有与1号相同的元素
    			q = q->next;
    		}
    		if (q == NULL) {
    			s = (PLink)malloc(sizeof(PNode));
    			s->data = p->data;
    			s->next = L3->next;
    			L3->next = s;
    		}
    		p = p->next;
    	}
    	//对2号插入3中
    	p = L2->next;
    	while (p) {
    		q = L3->next;
    		while (q && (q->data != p->data)) {//C3号中不含有与1号相同的元素
    			q = q->next;
    		}
    		if (q == NULL) {// //当q遍历完一次都没有找到的话,即q的最后为空时就可以将1中的一个元素插入3中
    			s = (PLink)malloc(sizeof(PNode));
    			s->data = p->data;
    			s->next = L3->next;
    			L3->next = s;
    		}
    		p = p->next;
    	}
    
    }
    
    2)集合的交集
    void intersection(PLink L1, PLink L2, PLink L3) {
    	if (L3->next != NULL)
    		clearList(L3);
    	PLink p, q, s, t;
    	//1
    	p = L1->next;//遍历1
    	while (p) {
    		q = L2->next;//遍历2
    		while (q) {
    	if (p->data == q->data)
    				
    break;//找到相同的就返回
    			else
    				q = q->next;
    		}
    if (q) {//查找3号中有没有相同元素
    			s = L3->next;
    	while (s) {
    	if (s->data == p->data)
    					break;
    				else
    				s = s->next;}
    			if (s == NULL) {
    				t = (PLink)malloc(sizeof(PNode));
    				t->data = p->data;
    				t->next = L3->next;
    				L3->next = t;
    			}
    		}
    		p = p->next;}
    
    3)集合的差集
    void difference(PLink L1, PLink L2, PLink L3) {
    	if (L3->next != NULL)
    		clearList(L3);
    	PLink p, q, s, t;
    	//1
    	p = L1->next;//遍历1
    	while (p) {
    		q = L2->next;
    		while (q) {
    			if (q->data == p->data)
    				break;
    			else
    				q = q->next;
    		}
    		if (q == NULL) {//说明2号遍历完了,并且有不一样的
    			s = L3->next;
    			while (s) {//3号中也没有的话就插入进去
    				if (s->data == p->data)
    					break;
    				else
    					s = s->next;
    			}
    			if (s == NULL) {
    				t = (PLink)malloc(sizeof(PNode));
    				t->data = p->data;
    				t->next = L3->next;
    				L3->next = t;
    			}
    		}
    		p = p->next;
    	}
    }
    
    
    4)集合的补集
    void Neg(PLink L, PLink L3) {
    	if (L3->next != NULL)
    		clearList(L3);
    	PLink p = L;
    
    	int i = 0;
    	while (i < 26) {
    		if (!checkElem(p, i + 97))
    			addElem(L3, i + 97);
    		i++;
    	}
    }
    //任意类型的补集
    void Negany(PLink L, PLink L3) {
    	if (L3->next != NULL)
    		clearList(L3);
    	PLink p = L;
    
    	int i = 0;
    	while (i < 95) {
    		if (!checkElem(p, i + 32))
    			addElem(L3, i + 32);
    		i++;
    	}}
    
    
    5)混合运算表达式

    这是我认为最麻烦的部分,网上搜都搜不到,对于我这种技术不太行的人来说。。。着实有点难。硬写的,不知道对不对,反正目前都能实现(写得有点乱)

    while (str[i] != '\0')
    	{
    		if (str[i] == '+' || str[i] == '-' || str[i] == '*') {
    			if (StackEmpty(s) == TRUE || GetTop(s) == '(' || PStackEmpty(p) == TRUE) {
    				if (StackEmpty(s) == TRUE || GetTop(s) == '(') {
    					Push(&s, str[i]);
    				}
    				if (PStackEmpty(p) == TRUE || GetTop(s) == '(') {
    					PPush(&p, temp);}}
    			else {
    				temp = choose(temp, PGetTop(p), GetTop(s));
    				PPop(&p);
    				PPush(&p, temp);
    				Pop(&s);
    				Push(&s, str[i]);
    }
    			i++;}
    		else if (str[i] == '(') {
    			Push(&s, str[i]);
    			i++;
    			k = 1;}
    		else if (str[i] == ')') {
    			while (GetTop(s) != '(') {
    				temp = choose(temp, PGetTop(p), GetTop(s));
    				PPop(&p);
    				Pop(&s);
    }
    			Pop(&s);//让"("出栈
    			if (GetTop(s) == '~') {
    				Neg(temp, temp2);
    				temp = temp2;
    				Pop(&s);//让"~"出栈
    }
    			k = 0;
    			//temp[0] = temp[1];
    			i++;}
    		else if (str[i] == '~') {
    			if (str[i + 1] == 'A') {
    				if (IsAny == 0) {
    					Neg(A, temp);
    				}
    				else {
    					Negany(A, temp);
    				}
    				i = i + 2;}
    			else if (str[i + 1] == 'B') {
    				if (IsAny == 0) {
    					Neg(B, temp);}
    				else {
    					Negany(B, temp);}
    				i = i + 2;
    			}//当~(A+B)时
    			else if (str[i + 1] == '(') {
    				Push(&s, str[i]);
    				i++;
    			}
    			else {
    				printf("输入有误!“~”后面要有集合");
    				break;}}
    		//输入是集合的情况
    		else if (str[i] == 'A') {
    			temp = A;
    			i++;
    		}
    		else if (str[i] == 'B') {
    			temp = B;
    			i++;}}
    	while (StackEmpty(s) != TRUE)//符号栈不为空
    	{
    		temp = choose(PGetTop(p), temp, GetTop(s));
    		Pop(&s);
    		PPop(&p);
    	}
    	PClearStack(&p);
    	ClearStack(&s);
    	out(temp);
    
    

    六、测试与分析

    1.测试结果

    限定小写元素的集合
    限定小写元素的集合

    加括号的混合运算
    加括号的混合运算

    任意类型元素的集合
    任意类型元素的集合

    混合运算
    混合运算

    附录

    #include<stdio.h>
    #include<stdlib.h>
    
    #define OK 1
    #define ERROR 0
    #define TRUE 1
    #define FALSE 0
    #define MAXSIZE 30 /* 存储空间初始分配量 */
    int IsAny = 0;
    typedef char SElemType; /* SElemType类型根据实际情况而定 */
    /*链表*/
    typedef struct PNode {
    	char data;
    	struct PNode* next;
    }PNode, * PLink;
    
    //链表的初始化
    int Init(PLink L) {
    	if (!L) {
    		return 0;
    	}
    	L->next = NULL;
    	return 1;
    }
    /*******************************************************************/
    /* 顺序栈结构 */
    typedef struct
    {
    	SElemType data[MAXSIZE];
    	int top; /* 用于栈顶指针 */
    }SqStack;
    /*  构造一个空栈S */
    int InitStack(SqStack* S)
    {
    
    	S->top = -1;
    	return OK;
    }
    /* 把S置为空栈 */
    int ClearStack(SqStack* S)
    {
    	S->top = -1;
    	return OK;
    }
    /* 若栈S为空栈,则返回TRUE,否则返回FALSE */
    int StackEmpty(SqStack S)
    {
    	if (S.top == -1)
    		return TRUE;
    	else
    		return FALSE;
    }
    /* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */
    SElemType GetTop(SqStack S)
    {
    	if (S.top == -1)
    		return 0;
    
    	return S.data[S.top];
    }
    /* 插入元素e为新的栈顶元素 */
    int Push(SqStack* S, SElemType e)
    {
    	if (S->top == MAXSIZE - 1) /* 栈满 */
    	{
    		return ERROR;
    	}
    	S->top++;				/* 栈顶指针增加一 */
    	S->data[S->top] = e;  /* 将新插入元素赋值给栈顶空间 */
    	return OK;
    }
    /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
    int Pop(SqStack* S)
    {
    	if (S->top == -1)
    		return ERROR;
    	// *e = S->data[S->top];	/* 将要删除的栈顶元素赋值给e */
    	S->top--;				/* 栈顶指针减一 */
    	return OK;
    }
    /*******************************************************************************/
    /* 顺序栈结构 */
    typedef struct
    {
    	PLink data[MAXSIZE];
    	int top; /* 用于栈顶指针 */
    }PLinkStack;
    int PInitStack(PLinkStack* S)
    {
    	S->top = -1;
    	return OK;
    }
    /* 若栈S为空栈,则返回TRUE,否则返回FALSE */
    int PStackEmpty(PLinkStack S)
    {
    	if (S.top == -1)
    		return TRUE;
    	else
    		return FALSE;
    }
    /*清空栈*/
    int PClearStack(PLinkStack* S)
    {
    	S->top = -1;
    	return OK;
    }
    /* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */
    PLink PGetTop(PLinkStack S)
    {
    	if (S.top == -1)
    		return 0;
    
    	return S.data[S.top];
    }
    /* 插入元素e为新的栈顶元素 */
    int PPush(PLinkStack* S, PLink e)
    {
    	if (S->top == MAXSIZE - 1) /* 栈满 */
    	{
    		return ERROR;
    	}
    	S->top++;				/* 栈顶指针增加一 */
    	S->data[S->top] = e;  /* 将新插入元素赋值给栈顶空间 */
    	return OK;
    }
    /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
    int PPop(PLinkStack* S)
    {
    	if (S->top == -1)
    		return ERROR;
    	//	*e = S->data[S->top];	/* 将要删除的栈顶元素赋值给e */
    	S->top--;				/* 栈顶指针减一 */
    	return OK;
    }
    /**************************************************************************/
    //输入操作
    void input(PNode* head) {
    	PNode* p;
    	char t;
    	scanf("%c", &t);
    	while (t != '\n') {
    		if (t >= 97 && t <= 122) {
    			p = (PNode*)malloc(sizeof(PNode));
    			p->data = t;
    			p->next = head->next;
    			head->next = p;
    		}
    		scanf("%c", &t);
    
    	}
    }
    //任意类型的输入
    void inputany(PNode* head) {
    	PNode* p;
    	char t;
    	scanf("%c", &t);
    	while (t != '\n') {
    		if (t >= 32 && t <= 126) {//ASCII可显示字符
    			p = (PNode*)malloc(sizeof(PNode));
    			p->data = t;
    			p->next = head->next;
    			head->next = p;
    			//	scanf("%c", &t);
    		}
    		scanf("%c", &t);
    
    	}
    }
    void Swap(PNode* p, PNode* q) {
    	PNode temp = *p;
    	temp.next = q->next;
    	q->next = p->next;
    	*p = *q;
    	*q = temp;
    }
    //排序
    void Sort(PNode* head) {
    	PNode* p, * q, * min;
    	if (!head) {
    		printf("空集");
    		return;
    	}
    	p = head->next;
    	min = p;
    	while (p)
    	{
    		min = p;
    		q = p;
    		while (q) {
    			if (q->data < min->data) {
    				min = q;
    			}
    			q = q->next;
    		}
    		Swap(p, min);
    		p = p->next;
    	}
    }
    //输出操作
    void out(PNode* head) {
    	Sort(head);
    	PNode* p;
    	if (!head) {
    		printf("空集");
    		return;
    	}
    	p = head->next;
    	while (p != NULL)
    	{
    		printf("%c", p->data);
    		p = p->next;
    	}
    	printf("\n");
    }
    //链表的清空
    int clearList(PLink L) {
    	PLink p, q;
    	p = L->next;
    	if (p == NULL) {
    		return 1;//为空
    	}
    	while (p) {
    		q = p;
    		p = p->next;
    		free(q);
    	}
    	L->next = NULL;
    	return 1;
    }
    
    //集合的并
    void and (PLink L1, PLink L2, PLink L3) {
    	if (L3->next != NULL)
    		clearList(L3);
    	PLink p, q, s;
    	//对空集的操作
    	if (!L1 || !L2) {
    		if (!L1) {
    			L3 = L2;
    		}
    		else if (!L2) {
    			L3 = L1;
    		}
    		else {
    			L3 = L1;
    		}
    	}
    	//对1号插入3中
    	p = L1->next;
    	while (p) {
    		q = L3->next;
    		while (q && (q->data != p->data)) {//C3号中不含有与1号相同的元素
    			q = q->next;
    		}
    		if (q == NULL) {
    			s = (PLink)malloc(sizeof(PNode));
    			s->data = p->data;
    			s->next = L3->next;
    			L3->next = s;
    		}
    		p = p->next;
    	}
    	//对2号插入3中
    	p = L2->next;
    	while (p) {
    		q = L3->next;
    		while (q && (q->data != p->data)) {//C3号中不含有与1号相同的元素
    			q = q->next;
    		}
    		if (q == NULL) {// //当q遍历完一次都没有找到的话,即q的最后为空时就可以将1中的一个元素插入3中
    			s = (PLink)malloc(sizeof(PNode));
    			s->data = p->data;
    			s->next = L3->next;
    			L3->next = s;
    		}
    		p = p->next;
    	}
    }
    //交集
    void intersection(PLink L1, PLink L2, PLink L3) {
    	if (L3->next != NULL)
    		clearList(L3);
    	PLink p, q, s, t;
    	//1
    	p = L1->next;//遍历1
    	while (p) {
    		q = L2->next;//遍历2
    		while (q) {
    			if (p->data == q->data)
    				break;//找到相同的就返回
    			else
    				q = q->next;
    		}
    		if (q) {//查找3号中有没有相同元素
    			s = L3->next;
    			while (s) {
    				if (s->data == p->data)
    					break;
    				else
    					s = s->next;
    			}
    			if (s == NULL) {
    				t = (PLink)malloc(sizeof(PNode));
    				t->data = p->data;
    				t->next = L3->next;
    				L3->next = t;
    			}
    		}
    		p = p->next;
    	}
    }
    //差集
    void difference(PLink L1, PLink L2, PLink L3) {
    	if (L3->next != NULL)
    		clearList(L3);
    	PLink p, q, s, t;
    	//1
    	p = L1->next;//遍历1
    	while (p) {
    		q = L2->next;
    		while (q) {
    			if (q->data == p->data)
    				break;
    			else
    				q = q->next;
    		}
    		if (q == NULL) {//说明2号遍历完了,并且有不一样的
    			s = L3->next;
    			while (s) {//3号中也没有的话就插入进去
    				if (s->data == p->data)
    					break;
    				else
    					s = s->next;
    			}
    			if (s == NULL) {
    				t = (PLink)malloc(sizeof(PNode));
    				t->data = p->data;
    				t->next = L3->next;
    				L3->next = t;
    			}
    		}
    		p = p->next;
    	}
    }
    //元素判定
    int checkElem(PLink L1, char c) {
    	PLink p;
    	p = L1->next;
    	while (p) {
    		if (p->data == c)
    			return 1;
    		p = p->next;
    	}
    	return 0;//此元素没有
    }
    //链表的添加
    void addElem(PLink L, char c) {
    	PLink t, p = L;
    	while (p->next)
    		p = p->next;
    	t = (PLink)malloc(sizeof(PNode));
    	t->data = c;
    	t->next = NULL;
    	p->next = t;
    }
    //补集
    void Neg(PLink L, PLink L3) {
    	if (L3->next != NULL)
    		clearList(L3);
    	PLink p = L;
    
    	int i = 0;
    	while (i < 26) {
    		if (!checkElem(p, i + 97))
    			addElem(L3, i + 97);
    		i++;
    	}
    }
    //任意类型的补集
    void Negany(PLink L, PLink L3) {
    	if (L3->next != NULL)
    		clearList(L3);
    	PLink p = L;
    
    	int i = 0;
    	while (i < 95) {
    		if (!checkElem(p, i + 32))
    			addElem(L3, i + 32);
    		i++;
    	}
    }
    //优先级判断
    int firstcheck(char a) {
    	if (a == '~') {
    		return 4;
    	}
    	else if (a == '*') {
    		return 3;
    	}
    	else if (a == '+' || a == '-') {
    		return 2;
    	}
    	else if (a == '(') {
    		return 1;
    	}
    	return 0;
    }
    //运算
    PLink choose(PLink A, PLink B, char a) {
    	PLink L3;
    	L3 = (PNode*)malloc(sizeof(PNode));
    	Init(L3);
    	switch (a)
    	{
    	case '+':
    		and (A, B, L3);
    		break;
    	case '-':
    		difference(A, B, L3);
    		break;
    	case '*':
    		intersection(A, B, L3);
    		break;
    	default:
    		break;
    	}
    	return L3;
    }
    //判断输入格式是否正确
    int IsInput(char str[]) {
    	int i = 0;
    	if (str[0] == '+' || str[0] == '-' || str[0] == '*'|| str[0] == ')') {
    		return 0;
    	}
    		
    	while (str[i] != '\0') {
    		if (str[i] == 'A' || str[i] == 'B') {//当是集合的时候,后面只能接运算符号“+,-,*”或回车符
    			if (str[i + 1] != '+' && str[i + 1] != '-' && str[i + 1] != '*'&&str[i+1]!='\0'&&str[i+1]!=')') {
    				return 0;
    			}
    		}
    		else if (str[i] == ')') {
    			if (str[i + 1] == '+' && str[i + 1] == '-' && str[i + 1] == '*' && str[i + 1] == '\0') {
    				return 0;
    			}
    		}
    		else if (str[i] == '~') {
    			if (str[i + 1] != 'A' && str[i + 1] != 'B' && str[i + 1] != '(') {
    				return 0;
    			}
    		}
    		else if (str[i] == '(') {
    			if (str[i + 1] != 'A' && str[i + 1] != 'B' && str[i + 1] != '~') {
    				return 0;
    			}
    		}
    		else if (str[i] == '+' || str[i] == '-' || str[i] == '*') {
    			if (str[i + 1] == '+' || str[i + 1] == '-' ||str[i + 1] == '*' || str[i + 1] == '\0' || str[i + 1] == ')') {
    				return 0;
    			}
    		}
    		i++;
    	}
    	return 1;
    }
    //混合运算
    void Mixed(PLink A, PLink B) {
    	SqStack s;//符号栈
    	PLinkStack p;//集合栈
    	//初始栈
    	InitStack(&s);
    	PInitStack(&p);
    	PLink temp, temp2;//作为中间栈储存链表
    	temp = (PNode*)malloc(sizeof(PNode));
    	Init(temp);
    	temp2 = (PNode*)malloc(sizeof(PNode));
    	Init(temp2);
    	SElemType c;
    	int i = 0, flag = 0;//代表没有括号
    	char str[MAXSIZE];
    	printf("请输入运算式:\n");
    	scanf("%s", &str);
    	while (!IsInput(str))
    	{
    		printf("输入格式错误,请重新输入运算式:\n");
    		scanf("%s", &str);
    
    	}
    
    	printf("输入结束\n");
    	int k = 0;
    	i = 0;
    	while (str[i] != '\0')
    	{
    		if (str[i] == '+' || str[i] == '-' || str[i] == '*') {
    			if (StackEmpty(s) == TRUE || GetTop(s) == '(' || PStackEmpty(p) == TRUE) {
    				if (StackEmpty(s) == TRUE || GetTop(s) == '(') {
    					Push(&s, str[i]);
    				}
    				if (PStackEmpty(p) == TRUE || GetTop(s) == '(') {
    					PPush(&p, temp);
    				}
    			}
    			else {
    				temp = choose(temp, PGetTop(p), GetTop(s));
    				PPop(&p);
    				PPush(&p, temp);
    				Pop(&s);
    				Push(&s, str[i]);
    			}
    			i++;
    		}
    		else if (str[i] == '(') {
    			Push(&s, str[i]);
    			i++;
    			k = 1;
    		}
    		else if (str[i] == ')') {
    			while (GetTop(s) != '(') {
    				temp = choose(temp, PGetTop(p), GetTop(s));
    				PPop(&p);
    				Pop(&s);
    			}
    			Pop(&s);//让"("出栈
    			if (GetTop(s) == '~') {
    				Neg(temp, temp2);
    				temp = temp2;
    				Pop(&s);//让"~"出栈
    			}
    			k = 0;
    			//temp[0] = temp[1];
    			i++;
    		}
    		else if (str[i] == '~') {
    			if (str[i + 1] == 'A') {
    				if (IsAny == 0) {
    					Neg(A, temp);
    				}
    				else {
    					Negany(A, temp);
    				}
    				i = i + 2;
    			}
    			else if (str[i + 1] == 'B') {
    				if (IsAny == 0) {
    					Neg(B, temp);
    				}
    				else {
    					Negany(B, temp);
    				}
    				i = i + 2;
    			}//当~(A+B)时
    			else if (str[i + 1] == '(') {
    				Push(&s, str[i]);
    				i++;
    			}
    			else {
    				printf("输入有误!“~”后面要有集合");
    				break;
    			}
    		}
    		//输入是集合的情况
    		else if (str[i] == 'A') {
    			temp = A;
    			i++;
    		}
    		else if (str[i] == 'B') {
    			temp = B;
    			i++;
    		}
    	}
    	while (StackEmpty(s) != TRUE)//符号栈不为空
    	{
    		temp = choose(PGetTop(p), temp, GetTop(s));
    		Pop(&s);
    		PPop(&p);
    	}
    	PClearStack(&p);
    	ClearStack(&s);
    	out(temp);
    }
    
    
    int main() {
    	/*FILE stream;
    	freopen_s(&stream, "in.txt", "r", stdin);*/
    	PLink L1, L2, L3;
    	L1 = (PLink)malloc(sizeof(PNode));
    	L2 = (PLink)malloc(sizeof(PNode));
    	L3 = (PLink)malloc(sizeof(PNode));
    	Init(L1);
    	Init(L2);
    	Init(L3);
    	printf("请选择\n1---限定元素:[‘a’..’z’]\n2---任意可显示类型\n");
    	char n[10];
    	do {
    		scanf("%s", &n);
    		getchar();
    		switch (n[0])
    		{
    		case '1':
    			printf("请输入集合Set1  ");
    			input(L1);
    			printf("请输入集合Set2  ");
    			input(L2);
    			IsAny = 0;
    			break;
    		case '2':
    			printf("请输入集合Set1  ");
    			inputany(L1);
    			printf("请输入集合Set2  ");
    			inputany(L2);
    			IsAny = 1;
    			break;
    		default:
    			printf("请检查是否输入错误\n");
    			break;
    		}
    	} while (n[0] != '1' && n[0] != '2');
    
    
    	printf("0----退出程序\n1---并集运算\n2---交集运算\n3---差集运算\n4---元素查找\n5---补集运算\n6---混合运算\n");
    	char i[10];
    	int flag = 1;
    	while (flag)
    	{
    		printf("请选择\n");
    		scanf("%s", &i);
    		switch (i[0]) {
    		case '0':
    			flag = 0;
    			break;
    		case '1':
    			and (L1, L2, L3);
    			printf("并集是:");
    			out(L3);
    			break;
    		case '2':
    			intersection(L1, L2, L3);
    			printf("交集是:");
    			out(L3);
    			break;
    		case '3':
    			difference(L1, L2, L3);
    			printf("(A-B)差集是:");
    			out(L3);
    			printf("(B-A)差集是:");
    			difference(L2, L1, L3);
    			out(L3);
    			break;
    		case '4':
    			printf("请输入查找的元素:  ");
    			char c;
    			scanf("%c", &c);
    			scanf("%c", &c);
    			if (checkElem(L1, c) && checkElem(L2, c)) {
    				printf("AB集合中存在%c\n", c);
    			}
    			else
    			{
    				if (checkElem(L1, c)) {
    					printf("A集合中存在%c\n", c);
    				}
    				else if (checkElem(L2, c)) {
    					printf("B集合中存在%c\n", c);
    				}
    				else {
    					printf("两个集合中都不存在%c\n", c);
    				}
    			}
    			break;
    		case '5':
    			printf("A集合的补集\n");
    			if (IsAny == 0) {
    				Neg(L1, L3);
    			}
    			else {
    				Negany(L1, L3);
    			}
    			out(L3);
    			printf("B集合的补集\n");
    			if (IsAny == 0) {
    				Neg(L2, L3);
    			}
    			else {
    				Negany(L2, L3);
    			}
    			out(L3);
    			break;
    		case '6':
    			Mixed(L1, L2);
    			break;
    		default:
    			printf("没这个选项,选错啦!");
    			continue;
    		}
    	}
    	return 0;
    }
    //测试数据
    //(A - B)* B
    //(~A - B)* B
    //(~A + B) - B
    //(~A + B) * B
    //~(A + B)
    
    展开全文
  • 异或

    2016-11-15 00:09:00
    并交补,计算机中都是指按二进制位操作。 可以辅助以数学中的集合来理解。 并交补异或等等,都是属于数理逻辑的范畴。 布尔代数,也就是逻辑代数,可以说是集合代数在数理逻辑中的应用。 是另一套符号系统。 ...
  • 第一部分 命题符号化(联结词的准确...集合的运算(、对称差、广义、广义) 有穷集计数(包含排斥原理) 二元关系的表示(集合、关系图、关系矩阵) 关系的运算(域、逆、复合、限制、像)及运算满足
  • 在Python3中,、差的符号分别为:&、|、^、- 二、集合处理方法 这里的集合用S表示,元素用x表示 ①S.add(x):若x元素不在集合S中,则将x添加到S中 ②S.remove(x):若x在集合S中,则将x移除;若x不在...
  • 集合 set&frozenset

    2018-11-15 15:11:32
    ∩() &amp;amp; ∪() 竖线 - 或 \ (差) - △(异或,不同时属于两个集合) ^ 内建函数 面向所有集合 说明 s.issubset(t) s是否是t的子集 ...
  • 在数学的操作之中存在、差、的概念,而在数据的查询中也存在此概念,有如下几个连接符号:UNION:连接两个查询,相同的部分不显示; UNION ALL:连接两个查询,相同的部分显示; INTERSECT:返回两个查询中...
  • 在数学的操作之中存在、差、的概念,而在数据的查询中也存在此概念,有如下几个连接符号: UNION:连接两个查询,相同的部分不显示; UNION ALL:连接两个查询,相同的部分显示; INTERSECT:返回两个...
  • 集合、序列

    2017-08-17 13:58:00
    在数学的操作之中存在、差、的概念,而在数据的查询中也存在此概念,有如下几个连接符号: UNION:连接两个查询,相同的部分不显示; UNION ALL:连接两个查询,相同的部分显示; INTERSECT...
  • Oracle笔记(十二) 集合、序列一、集合在数学的操作之中存在、差、的概念,而在数据的查询中也存在此概念,有如下几个连接符号:UNION:连接两个查询,相同的部分不显示;UNION ALL:连接两个查询,相同的...
  • Oracle集合、序列

    2018-06-08 16:15:00
    在数学的操作之中存在、差、的概念,而在数据的查询中也存在此概念,有如下几个连接符号: UNION:连接两个查询,相同的部分不显示; UNION ALL:连接两个查询,相同的部分显示; INTERSECT:返回两个...
  • 在数学的操作之中存在、差、的概念,而在数据的查询中也存在此概念,有如下几个连接符号: UNION:连接两个查询,相同的部分不显示;UNION ALL:连接两个查询,相同的部分显示;INTERSECT:返回两个查询...
  • 在数学的操作之中存在、差、的概念,而在数据的查询中也存在此概念,有如下几个连接符号: UNION:连接两个查询,相同的部分不显示; UNION ALL:连接两个查询,相同的部分显示; INTERSECT:返回两...
  • 第一部分:数理逻辑 第一章:基础:逻辑和证明 知识点:命题、简单命题、复合命题、五个联结词(否定、合取、析取、条件...知识点:集合、子集、幂集、笛卡尔积、文氏图、集合的运算(、差、、对称差),集合的
  • 以及两个字典的合并运算,包括、差、积等运算功能。 操作说明: (一)制作模式 1.生日密码: (1)日期选择:可以选择一个或一段日期 (2)日期格式:包括常用的日期格式 (3)自定义格式:可以自由选择...
  • digits 符号计算中设置符号数值的精度 dir 目录列表 disp 显示数组 display 显示对象内容的重载函数 dlinmod 离散系统的线性化模型 dmperm 矩阵Dulmage-Mendelsohn 分解 dos 执行DOS 指令返回结果 double ...
  • 以及两个字典的合并运算,包括、差、积等运算功能。 操作说明: (一)制作模式 1.生日密码: (1)日期选择:可以选择一个或一段日期 (2)日期格式:包括常用的日期格式 (3)自定义格式:可以自由选择...

空空如也

空空如也

1 2 3
收藏数 60
精华内容 24
关键字:

交并补符号