离散数学实验报告

合集下载

离散数学 实验报告

离散数学 实验报告

离散数学实验报告离散数学实验报告引言:离散数学是一门研究离散结构的数学学科,它对于计算机科学、信息技术等领域具有重要的应用价值。

本实验报告旨在通过实际案例,探讨离散数学在现实生活中的应用。

一、图论在社交网络中的应用社交网络已成为人们日常生活中不可或缺的一部分。

图论作为离散数学的重要分支,对于分析和研究社交网络具有重要意义。

以微信为例,我们可以通过图论的方法,分析微信中的好友关系、群组关系等。

通过构建好友关系图,我们可以计算某个人在社交网络中的影响力,进而预测他的行为模式。

二、布尔代数在电路设计中的应用布尔代数是离散数学中的重要内容,它在电路设计中扮演着重要的角色。

通过布尔代数的运算规则和定理,我们可以简化复杂的逻辑电路,提高电路的可靠性和效率。

例如,我们可以使用布尔代数中的与、或、非等逻辑运算符,设计出满足特定功能需求的逻辑电路。

三、排列组合在密码学中的应用密码学是离散数学的一个重要应用领域。

排列组合是密码学中常用的数学工具之一。

通过排列组合的方法,我们可以设计出强大的密码算法,保障信息的安全性。

例如,RSA加密算法中的大素数的选择,就涉及了排列组合的知识。

四、概率论在数据分析中的应用概率论是离散数学中的一门重要学科,它在数据分析中具有广泛的应用。

通过概率论的方法,我们可以对数据进行统计和分析,从而得出一些有意义的结论。

例如,在市场调研中,我们可以通过抽样调查的方法,利用概率论的知识,对整个市场的情况进行推断。

五、图论在物流规划中的应用物流规划是现代物流管理中的一个重要环节。

图论作为离散数学的重要分支,可以帮助我们解决物流规划中的一些问题。

例如,我们可以通过构建物流网络图,分析货物的流动路径,优化物流的运输效率,降低物流成本。

结论:离散数学作为一门重要的数学学科,在现实生活中具有广泛的应用。

通过对离散数学的学习和应用,我们可以解决实际问题,提高工作效率,推动社会的发展。

希望通过本实验报告的介绍,能够增加对离散数学的兴趣,进一步挖掘离散数学在实际生活中的潜力。

离散实验报告_幂集

离散实验报告_幂集

一、实验目的1. 理解幂集的概念,掌握幂集的运算规则;2. 掌握幂集在实际问题中的应用;3. 培养逻辑思维能力和编程能力。

二、实验原理幂集是指一个集合中所有子集的集合,记作P(A)。

对于任意集合A,其幂集P(A)的元素个数等于2的A的元素个数次方。

设集合A={a1, a2, ..., an},则其幂集P(A)包含以下元素:1. 空集∅;2. 单元素集合{a1},{a2},...,{an};3. 两个元素组成的集合,如{a1, a2},{a1, a3},...,{an-1, an};4. ...;5. n个元素组成的集合,即A本身。

幂集的运算规则如下:1. 交换律:P(A) = P(B);2. 结合律:(P(A) ∩ P(B)) ∩ P(C) = P(A ∩ B) ∩ P(C);3. 分配律:P(A) ∪ (P(B) ∩ P(C)) = (P(A) ∪ P(B)) ∩ (P(A) ∪ P(C))。

三、实验内容1. 定义一个集合A;2. 求集合A的幂集P(A);3. 分析幂集在实际问题中的应用。

四、实验步骤1. 定义集合A,例如:A = {1, 2, 3};2. 编写程序计算幂集P(A);3. 分析幂集P(A)的元素;4. 应用幂集解决问题。

五、实验结果以集合A = {1, 2, 3}为例,其幂集P(A)为:P(A) = {∅, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}}六、实验分析1. 幂集P(A)包含8个元素,即2^3 = 8,符合幂集的定义;2. 幂集P(A)的元素包括空集、单元素集合、两个元素组成的集合以及A本身;3. 幂集在实际问题中具有广泛的应用,例如:在计算机科学中,集合的幂集可以用于描述数据结构、算法设计等;在数学中,幂集可以用于研究集合论、拓扑学等。

七、实验总结通过本次实验,我们掌握了幂集的概念和运算规则,并了解了幂集在实际问题中的应用。

离散结构实验报告

离散结构实验报告

一、实验目的1. 理解离散结构的基本概念和特性。

2. 掌握常见离散结构的构建方法和应用。

3. 培养动手能力和团队协作精神。

二、实验原理离散结构是指由有限个元素组成的具有特定关系的集合。

常见的离散结构有图、树、序列等。

图是一种由顶点和边组成的集合,其中顶点表示实体,边表示实体之间的关系;树是一种特殊的图,具有层次结构,每个节点有且仅有一个父节点;序列是一种有序的元素集合,元素之间有先后顺序。

三、实验内容1. 图的构建与应用(1)构建一个无向图,包含5个顶点和5条边,表示5个城市之间的交通路线。

(2)利用邻接矩阵和邻接表表示该无向图。

(3)计算图中顶点的度、连通度和最小生成树。

2. 树的构建与应用(1)构建一个二叉树,包含5个节点,表示一个简单的组织结构。

(2)计算二叉树的高度、节点个数、叶子节点个数。

(3)判断二叉树是否为完全二叉树。

3. 序列的构建与应用(1)构建一个有序序列,包含10个整数。

(2)计算序列的逆序对个数。

(3)将序列进行排序,并分析排序算法的效率。

四、实验步骤1. 图的构建与应用(1)使用MATLAB或Python等编程语言,定义一个图类,包含顶点、边、邻接矩阵和邻接表等属性。

(2)添加顶点和边,构建无向图。

(3)使用图类中的方法计算顶点的度、连通度和最小生成树。

2. 树的构建与应用(1)使用MATLAB或Python等编程语言,定义一个树类,包含节点、父节点、左右子节点等属性。

(2)添加节点,构建二叉树。

(3)使用树类中的方法计算树的高度、节点个数、叶子节点个数,判断是否为完全二叉树。

3. 序列的构建与应用(1)使用MATLAB或Python等编程语言,定义一个序列类,包含元素、大小、逆序对个数等属性。

(2)添加元素,构建有序序列。

(3)使用序列类中的方法计算逆序对个数,并使用排序算法对序列进行排序。

五、实验结果与分析1. 图的构建与应用实验结果:构建了一个包含5个顶点和5条边的无向图,计算出了顶点的度、连通度和最小生成树。

离散数学实验报告

离散数学实验报告

“离散数学”实验报告目录一、实验目的 (3)二、实验内容 (3)三、实验环境 (3)四、实验原理和实现过程(算法描述) (3)1、实验原理........................................................................................................2、实验过程.......................................................................................................五、实验数据及结果分析 (13)六、源程序清单 (24)源代码 (24)七、其他收获及体会 (45)一、实验目的实验一:熟悉掌握命题逻辑中的联接词、真值表、主范式等,进一步能用它们来解决实际问题。

实验二:掌握关系的概念与性质,基本的关系运算,关系的各种闭包的求法。

理解等价类的概念,掌握等价类的求解方法。

实验三:理解图论的基本概念,图的矩阵表示,图的连通性,图的遍历,以及求图的连通支方法。

二、实验内容实验一:1. 从键盘输入两个命题变元P和Q的真值,求它们的合取、析取、条件和双条件的真值。

(A)2. 求任意一个命题公式的真值表(B,并根据真值表求主范式(C))实验二:1.求有限集上给定关系的自反、对称和传递闭包。

(有两种求解方法,只做一种为A,两种都做为B)2. 求有限集上等价关系的数目。

(有两种求解方法,只做一种为A,两种都做为B)3. 求解商集,输入集合和等价关系,求相应的商集。

(C)实验三:以偶对的形式输入一个无向简单图的边,建立该图的邻接矩阵,判断图是否连通(A)。

并计算任意两个结点间的距离(B)。

对不连通的图输出其各个连通支(C)。

三、实验环境C或C++语言编程环境实现。

四、实验原理和实现过程(算法描述)实验一:1.实验原理(1)合取:二元命题联结词。

离散数学实验报告(两篇)

离散数学实验报告(两篇)

引言:离散数学是一门基础性的数学学科,广泛应用于计算机科学、电子信息等领域。

本文是《离散数学实验报告(二)》,通过对离散数学实验的深入研究和实践,总结了相关的理论知识和应用技巧,希望能够对读者对离散数学有更加深入的理解。

概述:本实验主要涉及离散数学中的集合、关系、图论等基本概念及其应用。

通过对离散数学的实验学习,深入掌握了这些概念和应用,对于在实际问题中的应用和拓展具有重要的意义。

正文内容:一、集合相关概念及应用1.定义:集合是由元素组成的无序的整体。

介绍了集合的基本概念、集合的表示法以及集合的运算。

2.集合的应用:介绍了集合在数学、计算机科学中的应用,如数据库的查询、关系代数等。

二、关系相关概念及应用1.定义:关系是一个元素与另一个元素之间的对应关系。

介绍了关系的基本概念、关系的表示方法及其运算。

2.关系的应用:介绍了关系在图像处理、社交网络分析等领域的应用,如图像中的像素点之间的关系、社交网络中用户之间的关系等。

三、图论基础知识及应用1.定义:图是由顶点和边组成的抽象的数学模型。

介绍了图的基本概念、图的表示方法和图的运算。

2.图论的应用:介绍了图论在路由算法、电子商务等领域的应用,如路由器的路由选择、电子商务中的商品推荐等。

四、布尔代数的概念及应用1.定义:布尔代数是一种基于集合论和逻辑学的代数系统。

介绍了布尔代数的基本概念、布尔表达式及其化简方法。

2.布尔代数的应用:介绍了布尔代数在电路设计、开关控制等方面的应用,如逻辑门电路的设计、开关控制系统的建模等。

五、递归的概念及应用1.定义:递归是一种通过调用自身来解决问题的方法。

介绍了递归的基本原理、递归的应用技巧。

2.递归的应用:介绍了递归在算法设计、树的遍历等方面的应用,如快速排序算法、树结构的遍历等。

总结:通过本次离散数学的实验学习,我深入掌握了集合、关系、图论等基本概念与应用。

集合的应用在数据库查询、关系代数等方面起到了重要的作用。

关系的应用在图像处理、社交网络分析等领域有广泛的应用。

离散数学实验报告

离散数学实验报告

离散数学实验报告一、实验目的离散数学是现代数学的一个重要分支,它在计算机科学、信息科学、人工智能等领域有着广泛的应用。

本次离散数学实验的目的在于通过实际操作和编程实现,深入理解离散数学中的基本概念、原理和算法,提高解决实际问题的能力,培养逻辑思维和创新能力。

二、实验环境本次实验使用的编程语言为 Python,开发环境为 PyCharm。

同时,还使用了一些相关的数学库和工具,如 sympy 库用于符号计算。

三、实验内容1、集合运算集合是离散数学中的基本概念之一。

在实验中,我们首先定义了两个集合 A 和 B,然后进行了并集、交集、差集等运算。

通过编程实现这些运算,加深了对集合运算定义和性质的理解。

```pythonA ={1, 2, 3, 4, 5}B ={4, 5, 6, 7, 8}并集union_set = Aunion(B)print("并集:", union_set)交集intersection_set = Aintersection(B)print("交集:", intersection_set)差集difference_set = Adifference(B)print("A 与 B 的差集:", difference_set)```2、关系的表示与性质判断关系是离散数学中的另一个重要概念。

我们使用矩阵来表示关系,并通过编程判断关系的自反性、对称性和传递性。

```pythonimport numpy as np定义关系矩阵relation_matrix = nparray(1, 0, 1, 0, 1, 0, 1, 0, 1)判断自反性is_reflexive = all(relation_matrixii == 1 for i inrange(len(relation_matrix)))print("自反性:", is_reflexive)判断对称性is_symmetric = all(relation_matrixij == relation_matrixji for i in range(len(relation_matrix)) for j in range(len(relation_matrix)))print("对称性:", is_symmetric)判断传递性is_transitive = Truefor i in range(len(relation_matrix)):for j in range(len(relation_matrix)):for k in range(len(relation_matrix)):if relation_matrixij == 1 and relation_matrixjk == 1 and relation_matrixik == 0:is_transitive = Falsebreakprint("传递性:", is_transitive)```3、图的遍历图是离散数学中的重要结构。

离散数学试验报告

离散数学试验报告

离散数学实验报告姓名:学号:班级:实验地点:实验时间:Word文档1实验目的和要求运用最小生成树思想和求最小生成树程序解决实际问题。

实际问题描述如下:八口海上油井相互间距离如下表,其中1号井离海岸最近,为5km。

问从海岸经1 号井铺设油管把各井连接起来,怎样连油管长度最短(为便于检修,油管只准在油井处分叉)?「到 2 3 4 5 6 7 81 1.3 2.1 0.9 0.7 1.8 2.0 1.820.9 1.8 1.2 2.8 2.3 1.13 2.6 1.7 2.5 1.9 1.040.7 1.6 1.5 0.950.9 1.1 0.860.6 1.070.52实验环境和工具实验环境:Windows 7旗舰版工具:Dev-C++ 5.8.33实验过程3.1算法流程1Word i=0;j=0;惠档exnum=8;结束3.2程序核心代码〃油管铺设问题Prim 算法实现#include <iostream> #include<iomanip> using namespace std; #define MAXV 10#define INF 32767 //INF 表示8 typedef int InfoType; typedef struct{int no; InfoType info; } VertexType;typedef struct{〃图的定义float edges[MAXV][MAXV]; 〃邻接矩阵 int vexnum;//顶点数 VertexType vexs[MAXV]; //存放顶点信息 } MGraph;//图的邻接矩阵类型〃顶点编号 //顶点其他信息 〃顶点类型Word文档/*输出邻接矩阵g*/void DispMat(MGraph g){int i,j;for (i=0;i<g.vexnum;i + +){for (j=0;j<g.vexnum;j + +)if (g.edges[i][j] = = INF)cout<<setw⑹<<“8";elsecout<<setw(6)<<g.edges[i][j];cout<<endl;))void prim(MGraph g,int v){ //从顶点V0 出发,按Prim 算法构造G的最小生成树//输出最小生成树的每条边及其权值float Vlength[MAXV];int i, j, k;int cloest[MAXV];float min;float sum = 0.0;Word文档for(i=0;i<g.vexnum;i ++){Vlength[i]=g.edges[v][i];cloest[i]=v;)for(i = 1;i<g.vexnum;i + +){min = INF; //min为其中最大的一条边二MAXVfor(j=0;j<g.vexnum;j + +){〃找n-1 条边if(Vlength[j]!=0&&Vlength[j]<min){min=Vlength[j];k=j;))cout<<" 连接油<”<<cloest[k] + 1<<”,”<<k+1<<">"<<“ 长度为:"<<min<<endl;sum + = min;Vlength[k]=0;Vlength[cloest[k]]=0;for(j=0;j<g.vexnum;j + +){ 〃选择当前代价最小的边if(g.edges[k][j]!=0&&g.edges[k][j]<Vlength[j]){Vlength[j]=g.edges[k][j];cloest[j]=k;Word文档)cout<<"管道总长度为:"<<sum<<endl;)int main()(int i,j,u=3;MGraph g;float A[MAXV][10];g.vexnum=8;for (i=0;i<g.vexnum;i + +)for (j=0;j<g.vexnum;j + +)A[i][j] = INF;A[0][1] = 1.3; A[0][2]=2.1; A[0][3]=0.9;A[0][4]=0.7; A[0][5] = 1.8; A[0][6]=2.0;A[0][7] = 1.8; A[1][2]=0.9; A[1][3] = 1.8;A[1][4] = 1.2; A[1][5]=2.8; A[1][6]=2.3;A[1][7] = 1.1; A[2][3]=2.6; A[2][4] = 1.7;A[2][5]=2.5; A[2][6] = 1.9; A[2][7] = 1.0;A[3][4]=0.7; A[3][5] = 1.6; A[3][6] = 1.5;A[3][7]=0.9; A[4][5]=0.9; A[4][6] = 1.1;Word文档A[4][7]=0.8; A[5][6]=0.6; A[5][7] = 1.0;A[6][7]=0.5;for (i=0;i<g.vexnum;i + +)for (j=0;j<g.vexnum;j + +)A[j][i]=A[i][j];for (i=0;i<g.vexnum;i + +) /*建立图的邻接矩阵*/ for (j=0;j<g.vexnum;j + +)g.edges[i][j]=A[i][j];cout<<endl;cout<<”各油井间距离:\n";DispMat(g);cout<<endl;cout<<"最优铺设方案:\n";prim(g,0);cout<<endl;return 0;)3.3运行结果Word文档exited after O.06836 seconds 3.4 运行结果分析程序实现了输出需要铺设管道的油井编号,并给出了每条管道长度以及总长度,基 本实现了题目要求。

离散实验报告一

离散实验报告一

离散数学实验报告(一)一、实验目的求命题公式的真值表及其主析取范式和主合取范式二、问题分析本程序最终的目的应是求命题公式的主析取范式和主合取范式,而在有命题真值表的情况下,主析取范式和主合取范式的求解将变得十分简单。

所以,该程序的关键问题应该是求解命题公式的真值表,此后在真值表的基础上完成主析取范式和主合取范式的求解。

(一)前期分析与部分变量准备规定前提,真值表中的T/F在该程序中用布尔类型的1/0来表达。

如此,可以方便程序的编写与运算。

首先,我们要确定各个联结词的符号表达,为了方便讨论,不妨在此先令各联结词表达如下:合取(*)、析取(/)、否定(-)、单条件(%)、双条件(@)。

接着,我们就需要明确各联结词所对应符号在程序中的功能。

具体来看,合取与析取可以分别使用c++自带的&&(且)和||(或)进行布尔运算,取否定也可以直接使用!(取非)运算;而对于单条件、双条件这两个联结词来看,在c++中并无已有的运算定义,所以我们要利用函数定义的方式重新明确其含义。

而后,定义char类型数组a[]用于存储命题公式,为了方便程序的实现,我们将命题变元与联结词分开存储于char类型数组b[]和c[]中。

(二)真值表输出算法以下,我们便进入了程序的核心部分——完成真值表的计算与输出。

碍于本人c++编程知识的局限,暂时只能实现输入三个变元、无否定情况下的命题公式的真值表输出。

为了完成真值表的输出,要解决以下几个问题1. 真值表的格式与指派控制对此,我们使用三层for语句嵌套完成真值表的每一行输出。

在循环的同时,我们还需要提前定义一个布尔数组p[],以根据每一行的输出完成三个变元的指派,并将其存储于数组p[]中。

2.真值表每一行结尾的结果计算首先,我们需要定义一个布尔类型的过程存储数组x[],利用switch语句的嵌套分别判断两个联结词,使用相应的运算符(&&、||、!)和已定义的两个布尔类型函数(imp、equ),一次计算,并且将每一次的计算结果存储至x[]中,运算直至最后一步完成结果的输出。

离散逻辑算法实验报告

离散逻辑算法实验报告

一、实验背景离散逻辑算法是离散数学的一个重要分支,它研究的是由有限个变量组成的逻辑表达式及其真值。

在计算机科学、人工智能、逻辑电路设计等领域有着广泛的应用。

本实验旨在通过编程实现离散逻辑算法,加深对逻辑运算规则和真值表的理解,并提高编程能力。

二、实验目的1. 熟悉掌握离散逻辑运算规则,包括合取、析取、条件、双条件等。

2. 利用C语言编程实现离散逻辑运算,包括逻辑非、合取、析取、蕴含、双条件等。

3. 理解真值表的概念,并能够根据真值表判断逻辑表达式的真假。

三、实验内容1. 实现逻辑非运算2. 实现合取运算3. 实现析取运算4. 实现蕴含运算5. 实现双条件运算6. 根据真值表判断逻辑表达式的真假四、实验步骤1. 逻辑非运算(1)输入一个命题变量P的真值(0或1);(2)根据逻辑非运算规则,输出P的逻辑非值(若P为0,则输出1;若P为1,则输出0)。

2. 合取运算(1)输入两个命题变量P和Q的真值(0或1);(2)根据合取运算规则,输出P和Q的合取值(若P和Q均为1,则输出1;否则输出0)。

3. 析取运算(1)输入两个命题变量P和Q的真值(0或1);(2)根据析取运算规则,输出P和Q的析取值(若P和Q至少有一个为1,则输出1;否则输出0)。

4. 蕴含运算(1)输入两个命题变量P和Q的真值(0或1);(2)根据蕴含运算规则,输出P蕴含Q的值(若P为1且Q为1,则输出1;否则输出0)。

5. 双条件运算(1)输入两个命题变量P和Q的真值(0或1);(2)根据双条件运算规则,输出P双条件Q的值(若P和Q的真值相同,则输出1;否则输出0)。

6. 根据真值表判断逻辑表达式的真假(1)输入一个逻辑表达式;(2)生成该逻辑表达式的真值表;(3)根据真值表判断逻辑表达式的真假。

五、实验结果与分析1. 通过编程实现离散逻辑运算,验证了逻辑运算规则的正确性;2. 理解了真值表的概念,并能够根据真值表判断逻辑表达式的真假;3. 提高了编程能力,熟悉了C语言的基本语法和逻辑运算。

离散数学实验报告

离散数学实验报告

实验一一实验内容(选作AB类)1. 从键盘输入两个命题变元P和Q的真值,求它们的合取、析取、条件和双条件的真值。

(A)2. 求任意一个命题公式的真值表(B,并根据真值表求主范式(C))二实验目的熟悉掌握命题逻辑中的联接词、真值表、主范式等,进一步能用它们来解决实际问题。

三实验环境C语言编程环境实现。

四 1、实现A类算法原理根据析取、合取的定义可用简单的算术运算求出结果,并将结果转换成逻辑值。

同样根据等价关系可将条件式及双条件式转换成析取和合取的运算。

此题较简单2、实现BC类算法原理算法逻辑如下:(1)将二进制加法模拟器赋初值0(2)计算模拟器中所对应的一组真值指派下合式公式的真值。

(3)输出真值表中对应于模拟器所给出的一组真值指派及这组真值指派所对应的一行真值。

(4)产生下一个二进制数值,若该数值等于2n-1,则结束,否则转(2)。

(5)在进行表达式求值的时候,可先将带括号的中缀表达式利用栈结构转换为不带括号的后缀表达式(逆波兰式),然后进行计算。

具体方法请参考数据结构中有关“栈”的知识。

五实验数据及结果分析1(A类)2(B类)从实验结果可以看到:当输入的数据不是逻辑值时须重新输入,当输入符合逻辑值才能继续下去。

从结果来看完全正确,由于界面有限没有把所有结果都贴上,根据运行情况来看没有错误六源程序清单1(A类)#include<stdio.h>//#include<string.h>main(){while(1) //输入符合逻辑值的命题变元P值{int a,b,c,d,e,f,g;while(1){printf("\ninput the logic value of the minti P(0 or 1):");scanf("%d",&a);if((a!=0)&&(a!=1)){printf("you have input the wrong value,please reinput");}else break;}while(1) //输入符合逻辑值的命题变元Q值{printf("\ninput the logic value of the minti Q(0 or 1):");scanf("%d",&b);if(b!=0&&b!=1)printf("you have input the wrong value,please reinput");else break;}c=a*b; //合取d=a+b; //析取e=(!a)+b; //条件式f=a*b+(!a)*(!b); //双条件式if(c==0) //化为逻辑值c=0;elsec=1;if(d==0)d=0;elsed=1;if(e=0)e=0;elsee=1;if(f==0)f=0;elsef=1;printf("\nthe logic value of hequ:%d\nthe logic value of xiqu:%d\nthe logic value of tiaojian:%d\nthe logic value of shuangtiaojian:%d\n",c,d,e,f);printf("do you want to continue?input 'y' continue");g=getch();{if(g=='y');else break;}}}2(B类)#include<stdio.h>#include<stdlib.h>#include<string.h>#include<malloc.h>typedef struct Node //二叉树节点结构体{char data; //存节点字符struct Node *leftchild;//左孩子指针struct Node *rightchild;//右孩子指针int temp;//判断该节点前是否有特别的字符类型}BeTreeNode;/*typedef struct{char stack[30];int top;}SeqStack;//账的结构体*/void print_char(BeTreeNode *root);void prints(BeTreeNode *p);char str[30]; //输入的字符串char S[16]; //仅存是字母的字符串int w,length,x=1; //分辨取哪一种真值赋值//SeqStack mystack;//定义一个栈BeTreeNode *pt[30];//定义指针数组int **S_num; //二维数组存真值的多种赋值情况int L=0;/*void StackInitiate(SeqStack *S) //初始化{S->top=0;}int StackNotEmpty(SeqStack S) //非空否{if(S.top<=0)return 0;else return 1;}int StackPush(SeqStack *S,char x)//入栈{if(S->top>=16){printf("堆栈已满无法插入!\n");return 0;}else{S->stack[S->top]=x;S->top++;return 1;}}*/BeTreeNode *MakeTree(int a,int b) //建立二叉树{int i,j=0,k=0,a1[10],b1[10];int L=0;BeTreeNode *p[10];BeTreeNode *pp,*sign=NULL;for(i=a;i<=b;i++)//若有括号的先渐入括号的最内层{if(str[i]=='('){//if(mystack.top==0)if(L==0)a1[j]=i;L++;}if(str[i]==')'){L--;if(L==0){b1[j]=i;p[j]=MakeTree(a1[j]+1,b1[j]-1);j++;} }}j=0;for(i=a;i<=b;i++,k++)//用指针来存储二叉树的每个节点{if(str[i]=='!'){if(str[i+1]=='('){ pt[k]=p[j];pt[k]->temp=2;i=b1[j];j=j+1;}else{pt[k]=(BeTreeNode *)malloc(sizeof(BeTreeNode)); pt[k]->data=str[i+1];pt[k]->leftchild=NULL;pt[k]->rightchild=NULL;pt[k]->temp=-1;i=i+1;}}else if(str[i]=='('){pt[k]=p[j];pt[k]->temp=1;i=b1[j];j=j+1;}else{ pt[k]=(BeTreeNode *)malloc(sizeof(BeTreeNode)); pt[k]->data=str[i];pt[k]->leftchild=NULL;pt[k]->rightchild=NULL;pt[k]->temp=0;}}pp=pt[0];for(i=1;i<k;i=i+2)//把各个二叉树的节点连接起来{if(pt[i]->data=='|'){pt[i]->leftchild=pp;pt[i]->rightchild=pt[i+1];pp=pt[i];}else{if(sign!=NULL){pt[i]->leftchild=sign;sign->rightchild=pp;pp=pt[i];sign=NULL;}else{pt[i]->leftchild=pp;pp=pt[i];}if(i+2<k){if(pt[i+2]->data=='|'){pp=pt[i+1];sign=pt[i];}else{pp->rightchild=pt[i+1];}}}}if(sign!=NULL){sign->rightchild=pp;pp=sign;}else pp->rightchild=pt[k-1];return pp;}void prints(BeTreeNode *p)//根据各个节点前的标记符的赋值确定应该要输出哪种字符{if(p->temp==2){printf("!(");print_char(p);printf(")");}else if(p->temp==1){printf("(");print_char(p);printf(")");}else if(p->temp==-1){printf("!");print_char(p);}elseprint_char(p);}void print_char(BeTreeNode *root)//输出某个节点下的树{if(root->leftchild==NULL&&root->rightchild==NULL){printf("%c",root->data);}else{prints(root->leftchild);printf("%c",root->data);prints(root->rightchild);}}void print(BeTreeNode *root)//利用二重循环来进行从最内层的子树开始输出,直到输出整棵树{if(root->leftchild->leftchild!=NULL)print(root->leftchild);if(root->rightchild->leftchild!=NULL)print(root->rightchild);if(root->leftchild->temp==-1)printf("!%c ",root->leftchild->data);if(root->rightchild->temp==-1)printf("!%c ",root->rightchild->data);print_char(root);if(root->temp==2){printf("");prints(root);}printf("");}int numre(char c)//输出叶节点{int i;for(i=0;i<length;i++){if(S[i]==c)return S_num[w][i];}}int Judge(int num1,char c,int num2)//判断最简单的表达式的返回值{if(c=='&'){if(num1==num2&&num1==1)return 1;else return 0;}if(c=='|'){if(num1==num2&&num1==0)return 0;else return 1;}}int print_num(BeTreeNode *root)//从最内层开始输出返回值{int num1,num2,num,i;char c;if(root->leftchild==NULL&&root->rightchild==NULL){num=numre(root->data);}else{num1=print_num(root->leftchild);c=root->data;num2=print_num(root->rightchild);if((root->leftchild->temp==2)||(root->leftchild->temp==-1)){ for(i=0;i<x;i++)printf("");printf(" %d",num1);}if((root->rightchild->temp==2)||(root->rightchild->temp==-1)){ for(i=0;i<x;i++)printf("");printf(" %d",num2);}num=Judge(num1,c,num2);for(i=0;i<x;i++)printf("");printf(" %d",num);x=x+3;}if((root->temp==2)||(root->temp==-1)){if(num==1)num=0;else num=1;}return num;}int fac(int t)//计算出2的n次方的结果{if(t==0)return 1;if(t==1)return 2;return 2*fac(t-1);}void S_numf(int n)//开辟一个二维数组存储真值表的各种赋值情况{int row,col,i,j,k,p;row=fac(n);col=n;S_num=(int *)malloc(sizeof(int)*row);for(i=0;i<row;i++){S_num[i]=(int *)malloc(sizeof(int)*col);}for(i=0;i<row;i++)for(j=0;j<col;j++)S_num[i][j]=0;for(i=0;i<col;i++)for(k=0,j=fac(i);k<fac(i);j++,k++){for(p=col-1;p>col-1-i;p--)S_num[j][p]=S_num[k][p];S_num[j][p]=1;}}main(){int i,j,LEN,t=0,temp=1;BeTreeNode *root;//定义根节点//StackInitiate(&mystack);printf("请输入一个符合命题公式(仅支持非'!',析取'|',合取'&',优先级:!,|,&)\n:");gets(str);LEN=strlen(str);for(i=0;i<LEN;i++){ for(j=0;j<t;j++)if(S[j]==str[i])temp=0;if((str[i]>='a'&&str[i]<='z'||str[i]>='A'&&str[i]<='Z')&&temp){S[j]=str[i];t++; }temp=1;}length=strlen(S);S_numf(length);root=MakeTree(0,LEN-1);printf("该复合命题公式的真值表是:\n");for(i=0;i<length;i++)printf("%c ",S[i]);print(root);printf("\n");for(w=0;w<fac(length);w++){for(i=0;i<length;i++)printf("%d ",S_num[w][i]);print_num(root);printf("\n");x=1;}}七收获与体会通过这次实验使我了解了一些数理逻辑问题可以通过用计算机编程的方法来解决,一些定理的证明同样也可以用计算机通过将命题符号化来编程解决。

离散数学实验报告

离散数学实验报告

实验一命题逻辑推理1.实验用例根据下面的命题,试用逻辑推理方法确定谁是作案者,写出推理过程。

(1)营业员A或B偷了手表;(2)若A作案,则作案不在营业时间;(3)若B提供的证据正确,则货柜末上锁;(4)若B提供的证据不正确,则作案发生在营业时间;(5)货柜上了锁。

2.实验目的加深对命题逻辑推理方法的理解。

3.实验内容用命题逻辑推理的方法解决逻辑推理问题。

4.实验原理和方法(1)符号化上面的命题,将它们作为条件,营业员A偷了手表作为结论,得一个复合命题。

(2)将复合命题中要用到的联结词定义成C语言中的函数,用变量表示相应的命题变元。

将复合命题写成一个函数表达式。

(3)函数表达式中的变量赋初值1。

如果函数表达式的值为1,则结论有效,A偷了手表,否则是B偷了手表。

用命题题变元表示:A:营业员A偷了手表B:营业员B偷了手表C:作案不在营业时间D:B提供的证据正确E:货柜末上锁则上面的命题符号化为 (A||B) && (!A||C) && (!D||E) && (D||!C) && !E 要求找到满足上面式子的变元A,B的指派便是结果。

5.实验代码6.实验结果B偷了手表实验二关系的运用1.实验原理和方法在三种闭包中自反和对称闭包的求解很容易,对矩阵表示的关系,其自反闭包只要将矩阵的主对角线全部置为1就可;对称闭包则加上关系的转置矩阵(逻辑加法)2.实验代码5.实验结果1.自反闭包2.传递闭包3.对称闭包实验三图论1.实验用例如下图所示的赋权图表示某七个城市及预先算出它们之间的一些直接通信成路造价(单位:万元),试给出一个设计方案,使得各城市之间既能够通信又使总造价最小并计算其最小值.2实验原理和方法为了求解最小代价,使花费的总代价最小,这是数学中经典的求解最小耗费生成树的算法。

其核心思想是寻找每一步的最优解继而求得全局最优解。

为了求得最小耗费生成树,我们运用数学中经典的Krusal算法,此算法的核心思想是:1、假设该图G是不连通的,对该图的边以非降序权重新排列2、对于排序表中的每条边,如果现在把它放入T不会形成回路的话,则把它加入到生成树T中;否则丢弃3、输出最小生成树的结果,得到我们想要的答案因而最后求得的最小耗费是:此时的最小耗费是:23+1+4+9+3+17=57(万元)实验四最优二叉树在通信编码中的应用1.实验内容输入一组通信符号的使用频率,求各通信符号对应的前缀码。

离散数学教学实践活动(3篇)

离散数学教学实践活动(3篇)

第1篇一、前言离散数学是计算机科学、信息科学、数学等学科的基础课程,对于培养学生的逻辑思维、抽象思维和算法设计能力具有重要意义。

为了提高离散数学的教学效果,我们开展了一系列教学实践活动,旨在通过实践操作,让学生更加深入地理解和掌握离散数学的基本概念、方法和应用。

二、活动背景随着计算机科学的飞速发展,离散数学在各个领域中的应用越来越广泛。

为了让学生更好地适应未来社会的发展需求,我们决定开展离散数学教学实践活动,通过实际操作和项目实践,提升学生的综合素质。

三、活动目标1. 提高学生对离散数学基本概念的理解和掌握;2. 培养学生的逻辑思维和抽象思维能力;3. 提升学生的算法设计和编程能力;4. 拓展学生的知识面,激发学习兴趣。

四、活动内容1. 离散数学基本概念讲解与练习在活动开始阶段,我们首先对离散数学的基本概念进行了讲解,包括集合、关系、函数、图论、组合数学等。

通过课堂讲解、例题分析和练习,让学生对离散数学的基本概念有清晰的认识。

2. 算法设计与实现为了让学生更好地理解算法设计,我们选择了几个具有代表性的算法,如排序算法、查找算法、图搜索算法等。

在教师的指导下,学生分组进行算法设计,并使用编程语言实现算法。

通过这一环节,学生能够将理论知识与实际编程相结合,提高编程能力。

3. 项目实践为了让学生将离散数学知识应用于实际项目中,我们设计了几个项目实践任务。

例如,设计一个基于图的社交网络分析系统、实现一个基于组合数学的密码生成器等。

学生分组进行项目实践,通过讨论、分析和编程,完成项目任务。

4. 案例分析在活动过程中,我们选取了几个与离散数学相关的实际案例进行分析,如网络安全、人工智能、大数据等。

通过分析案例,让学生了解离散数学在各个领域的应用,激发学生的学习兴趣。

5. 交流与分享为了促进学生的交流与合作,我们组织了小组讨论和展示活动。

学生分组讨论各自在项目实践中的心得体会,并在全班进行展示。

通过交流与分享,学生能够互相学习、取长补短,共同提高。

离散实验报告

离散实验报告

离散实验报告离散实验报告概述:离散实验是一种基于离散数学原理的实验方法,旨在通过实际操作与观察,验证离散数学理论的正确性与应用性。

本报告将围绕离散实验的目的、方法、结果与分析展开,以期为读者提供一份全面的实验报告。

实验目的:离散实验的目的在于通过实际操作,验证离散数学理论在现实世界中的应用。

具体来说,本次实验旨在验证集合论、图论以及逻辑推理等离散数学的基本概念与原理在实际问题中的有效性。

实验方法:本次实验采用了多种实验方法,包括实地观察、数据收集与分析、计算机模拟等。

首先,我们选择了几个实际问题,如社交网络中的好友关系、物流网络中的最短路径问题等,以验证图论在解决网络问题中的可行性。

然后,我们进行了一系列数据收集,包括好友关系的网络拓扑结构、物流网络中各节点之间的距离等。

最后,我们利用计算机模拟工具,如Python编程语言,实现了离散数学中的算法,如Dijkstra算法、最小生成树算法等,来解决实际问题。

实验结果与分析:通过本次实验,我们得出了一系列实验结果,并对其进行了深入的分析。

首先,在社交网络中的好友关系实验中,我们发现图论中的邻接矩阵与邻接表等数据结构能够很好地表示好友关系,并且通过深度优先搜索与广度优先搜索等算法,能够高效地找到两个人之间的联系路径。

其次,在物流网络中的最短路径实验中,我们发现Dijkstra算法能够快速地找到两个节点之间的最短路径,并且通过最小生成树算法,能够有效地规划物流网络的布局,降低总体成本。

结论:通过本次离散实验,我们验证了离散数学理论在实际问题中的应用性与有效性。

图论、集合论以及逻辑推理等离散数学的基本概念与原理,为解决实际问题提供了有力的工具与方法。

通过实地观察、数据收集与分析、计算机模拟等实验方法,我们得出了一系列实验结果,并对其进行了深入的分析。

我们相信,离散实验的结果将为离散数学的研究与应用提供有力的支持与参考。

展望:离散实验作为一种验证离散数学理论的有效方法,具有广阔的发展前景。

离散数学 实验报告

离散数学 实验报告

离散数学实验报告离散数学实验报告一、引言离散数学是一门研究离散结构及其运算规则的数学学科,它在计算机科学、信息科学、通信工程等领域具有重要的应用价值。

本实验旨在通过实际案例,探索离散数学在现实生活中的应用。

二、实验目的本实验的目的是通过离散数学的理论知识,解决一个实际问题。

我们选择了图论中的最短路径问题作为案例,以展示离散数学在网络路由、物流规划等领域的应用。

三、实验过程1.问题描述我们的实验场景是一个城市的交通网络,其中各个交叉路口被看作是图的节点,而道路则是图的边。

我们需要找到两个给定节点之间的最短路径,以便规划出行路线。

2.建模为了解决这个问题,我们需要将实际情况抽象成数学模型。

我们将交通网络表示为一个有向图,每个节点代表一个交叉路口,每条边代表一条道路。

每条边上还需要标注距离或时间等权重。

3.算法选择在离散数学中,有多种算法可以解决最短路径问题,如迪杰斯特拉算法、弗洛伊德算法等。

根据实际情况和需求,我们选择了迪杰斯特拉算法。

4.算法实现我们使用编程语言实现了迪杰斯特拉算法,并将其应用于我们的交通网络模型。

算法的核心思想是通过不断更新节点之间的最短距离,逐步找到最短路径。

5.实验结果经过实验,我们成功找到了两个给定节点之间的最短路径,并计算出了最短距离。

这对于规划出行路线具有重要意义,可以帮助人们节省时间和资源。

四、实验总结通过这个实验,我们深入理解了离散数学在实际问题中的应用。

离散数学的概念和算法不仅仅是理论上的抽象,它们可以帮助我们解决现实生活中的复杂问题。

离散数学的应用远不止于此,它还可以用于密码学、数据压缩、人工智能等领域。

通过学习离散数学,我们能够培养出良好的抽象思维和问题解决能力,为未来的科学研究和工程实践打下坚实的基础。

总之,离散数学是一门具有广泛应用前景的学科,通过实验,我们对其应用领域有了更深入的了解。

希望未来能有更多的人关注和研究离散数学,为推动科学技术的发展做出贡献。

离散数学实验报告

离散数学实验报告

离散数学实验报告离散数学实验报告一、引言离散数学是现代数学的一个重要分支,它研究离散的数学结构和离散的数学对象。

本实验报告将介绍我对离散数学的学习和实践的一些心得体会。

二、集合论集合论是离散数学的基础,它研究集合及其运算。

在实验中,我学习了集合的表示方法和运算规则。

集合的表示方法有枚举法、描述法和图示法等。

集合的运算包括并、交、差和补等。

通过实践操作,我深刻理解了集合的概念和运算规则。

三、逻辑与命题逻辑是离散数学的另一个重要内容,它研究推理和思维的规律。

在实验中,我学习了逻辑的基本概念和符号表示法。

逻辑中的命题是逻辑推理的基本单位,它可以是真或假。

通过实践操作,我能够正确地分析和判断命题的真值,并进行逻辑推理。

四、关系与函数关系与函数是离散数学中的重要内容,它们描述了元素之间的联系。

在实验中,我学习了关系的定义和性质,包括自反性、对称性和传递性等。

函数是一种特殊的关系,它将一个集合的元素映射到另一个集合。

通过实践操作,我能够正确地定义和分析关系与函数。

五、图论图论是离散数学中的重要分支,它研究图及其性质。

在实验中,我学习了图的基本概念和表示方法。

图由顶点和边组成,可以分为有向图和无向图。

通过实践操作,我能够正确地定义和分析图的性质,如度、路径和连通性等。

六、组合数学组合数学是离散数学的另一个重要分支,它研究离散对象的组合和排列。

在实验中,我学习了组合数学的基本原理和方法。

组合数学中的排列和组合是常见的计数问题,通过实践操作,我能够正确地计算排列和组合的数量。

七、实践应用离散数学在计算机科学、通信工程和运筹学等领域有着广泛的应用。

在实验中,我了解了离散数学在实际问题中的应用。

例如,图论可以用于网络路由算法的设计,组合数学可以用于密码学中的加密算法设计。

通过实践操作,我能够将离散数学的知识应用到实际问题中,提高问题的解决效率。

八、总结通过本次离散数学实验,我深入了解了离散数学的基本概念和方法,并通过实践操作加深了对离散数学的理解。

中南大学离散数学实验报告(实验3ABC)

中南大学离散数学实验报告(实验3ABC)

“离散数学”实验报告(实验3ABC)专业班级学号姓名日期: 2011.12.19目录一、实验目的 (3)二、实验内容 (3)三、实验环境 (3)四、实验原理和实现过程(算法描述) (3)1实验原理 (3)2实验过程 (5)五、实验数据及结果分析 (6)六、源程序清单 (10)七、其他收获及体会 (16)一、实验目的理解图论的基本概念, 图的矩阵表示, 图的连通性, 图的遍历, 以及求图的连通支方法。

二、实验内容以偶对的形式输入一个无向简单图的边, 建立该图的邻接矩阵, 判断图是否连通(A)。

并计算任意两个结点间的距离(B)。

对不连通的图输出其各个连通支(C)。

三、实验环境C或C++语言编程环境实现。

四、实验原理和实现过程(算法描述)1.实验原理(1)建立图的邻接矩阵, 判断图是否连通根据图的矩阵表示法建立邻接矩阵A, 并利用矩阵的乘法和加法求出可达矩阵, 从而判断图的连通性。

连通图的定义: 在一个无向图G 中, 若从顶点vi到顶点vj有路径相连(当然从vj到vi也一定有路径), 则称vi和vj是连通的。

如果G 是有向图, 那么连接vi 和vj的路径中所有的边都必须同向。

如果图中任意两点都是连通的, 那么图被称作连通图。

判断连通图的实现:在图中, 从任意点出发在剩余的点中, 找到所有相邻点循环, 直到没有点可以加入为止, 如果有剩余的点就是不连通的, 否则就是连通的。

或者也可用WallShell算法, 由图的邻接矩阵判断图是否连通。

(2)计算任意两个结点间的距离图中两点i, j间的距离通过检验Al中使得aij为1的最小的l值求出。

路径P中所含边的条数称为路径P的长度。

在图G<V,E>中, 从结点Vi到Vj最短路径的长度叫从Vi到Vj的距离, 记为d<Vi, Vj>。

设图的邻接矩阵是A, 则所对应的aij的值表示, 点Vi到点Vj距离为n的路径有aij条。

若aij(1), aij(2), …, aij(n-1), 中至少有一个不为0, 则可断定Vi与Vj可达, 使aij(l)≠0的最小的l即为d(Vi, Vj)。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

“离散数学”实验报告(实验C)专业:自动化班级:0804班学号:000000姓名:何有*日期:2010年10月31日一、实验目的通过实验,帮助学生更好地掌握计算机科学技术常用的离散数学中的概念、性质和运算,包括联结词、真值表、主范式等,提高学生编写实验报告、总结实验结果的能力,培养学生的逻辑思维能力和算法设计的思想,能够独立完成简单的算法设计和分析,进一步用它们来解决实际问题,帮助学生学习掌握C/C++语言程序设计的基本方法和各种调试手段,使学生具备程序设计的能力。

二、实验内容求任意一个命题公式的真值表,并根据真值表求主范式。

三、实验环境C语言编程环境。

四、实验原理和实现过程(一)、关于命题公式的形式和运算符(即联结词)的运算首先根据离散数学的相关知识,命题公式由命题变元和运算符(即联结词)组成,命题变元用大写字母英文表示(本次试验没有定义命题常元T和F,即T、F都表示命题变元),每个命题变元都有两种真值指派0和1,对应于一种真值指派,命题公式有一个真值,由所有可能的指派和命题公式相应的真值按照一定的规范构成的表格称为真值表。

目前离散数学里用到的包括扩充联结词总共有九种,即析取(或)、合取(与)、非、蕴含、等值、与非、或非、异或、蕴含否定,常用的为前五种,其中除了非运算为一元运算以外,其它四种为二元运算。

所以本次实验设计时只定义了前五种运算符,同时用“/”表示非,用“*”表示合取,用“+”表示析取,用“>”表示蕴含,用“:”表示等值,且这五种运算符的优先级依次降低,如果需用括号改变运算优先级,则用小括号()改变。

以下为上述五种运算符运算时的一般真值表,用P和Q表示命题变元:1.非,用“/”表示2.合取(与),用“*”表示3.析取(或),用“+”表示4.蕴含,用“>”表示5.等值,用“:”表示(二)、命题公式真值的计算对于人来说,计算数学表达式时习惯于中缀表达式,例如a*b+c,a*(b+c)等等,而对于计算机来说,计算a*b+c还好,计算a*(b+c)则困难,因为括号的作用改变了运算的顺序,让计算机识别括号而改变计算顺序显得麻烦。

经理论和实践研究,用一种称之为后缀表达式(逆波兰式)的公式形式能让计算机更容易计算表达式的真值。

例如上面的a*(b+c),其后缀表达式为abc+*,计算时从左边开始寻找运算符,然后按照运算符的运算规则将与其相邻的前面的一个(非运算时为一个)或两个(其它四种运算为两个)操作数运算,运算结果取代原来的运算符和操作数的位置,然后重新从左边开始寻找运算符,开始下一次计算,比如上式,从左边开始寻找运算符,先找到+,则计算b+c,结果用d表示,这时后缀表达式变为ad*,又重新开始从左边开始寻找运算符,找到*,则计算a*d,运算结果保存在原来ad*所占的位置,即a位,也就是第一位。

下面是求取后缀表达式的规则:1.从中缀表达式左边起逐个字符判断,如果是命题变元,则直接输出;如果是运算符,则将其与当前有效栈顶字符(即非空,可能为运算符或左半括号;如果栈为空,则直接入栈)的优先级比较,如果大于栈顶字符优先级,则直接入栈,如果小于或等于栈顶字符优先级,则弹出栈中字符并输出,直到大于栈顶字符优先级;2.如果遇到左半括号,则直接入栈,也就是栈外左半括号的优先级最高,入栈以后,其优先级变为最低,也就是不管下一个字符是什么,该左半括号都不出栈,当且仅当遇到与其对应的右半括号时(遇到右半括号前,所有的字符按1中的规则或左半括号的入栈规则入栈或出栈),将栈中该左半括号以上的字符按照出栈规则弹出并输出,最后该左半括号出栈并和右半括号一起被丢掉(右半括号永不入栈),余下的字符不出栈;3.按照上述规则判断命题公式中的所有字符后,如果栈中还有有效字符,则依次弹出并输出。

以/A*(B+/C)为例,说明后缀表达式的求法:求得后缀表达式后再计算其真值,计算方法上面已叙述过,在此不再赘述。

(三)、程序流程框架按照实验要求的功能,本程序可分为命题公式输入模块、中缀表达式转化为后缀表达式模块、计算后缀表达式模块等几大模块,总体流程框架如下:1、输入命题公式本程序定义:命题变元用大写英文字母表示,“/”表示非,“*”表示与,“+”表示或,“>”表示蕴含,“:”表示等值,括号非汉字状态下的小括号,有几个括号时都用小括号表示。

定义函数char *getformula()完成合法命题公式的输入,无入口参数,返回合法命题公式的地址。

其流程图如下:2、将中缀表达式转化为后缀表达式本程序定义:栈外(、:、>、+、*、/的优先级依次升高,分别用1、2、3、4、5、6表示,栈中空字符优先级最低,为0。

3、计算后缀表达式真值后缀表达式的计算的流程图没有像上面所描述的那么简单(或者还有其他方法),比如二进制加法器、真值指派等问题上面没有详细写出,关于操作数的运算部分也没有具体给出,因为页面有限。

由于时间有限,还有其它一些模块也没有详细给出。

五、实验数据及结果分析1.程序界面程序界面如下:2.容错功能本程序尽可能地考虑了所有的错误形式,比如公式中出现字符串“A/”、“AB”、“*+”、“(+”、“)/”、“*)”、“()”、“)(”、“a+”等等类似形式均被认为输入错误,要求重新输入,还有开头第一个字符如果是+、*、>、:或者最后一个字符不是大写英文字母或者‘)’同样被认为错误。

本程序允许公式中出现空格,处理时会将空格去掉。

所以输入/、*、+、>、:、小括号、空格、大写英文字母、回车符以外的字符均会认为无效或者错误。

因此本程序的容错功能较强。

例子如下图:3.合法公式的计算本程序允许输入的命题公式字符数不超过100,所以有一定的限制。

命题变元可用二十六个大写英文字母表示。

相应的一些计算如下(部分截图未截取输入说明部分):(1)、非运算(2)、与运算(3)、或运算(4)、蕴含(5)、等值(6)综合公式由于截图面积有限,所以未截取输入说明部分:上面输入的每个命题公式都是随机输入的,其结果经过手工验证证明是正确的。

所以,本程序可以满足题目的要求。

六、其他收获和体会写这个程序花了不少时间,而且时间相对集中,除了上课外,在电脑前都是在做这个,连续做了几天。

刚开始时并没有完全按照软件设计的步骤去写,而是知道总体方框后,一个模块一个模块去求解,至于每个模块怎么写,则是在写的过程中逐步建立和完善的。

有些知识没有学到,比如如何求逆波兰式,只得借书回来看,上网找到的资料不够详细或者几乎没解释,难以理解。

当然了,程序是自己写的,自己看得懂就好多了,别人又不一定要看,所以我也没加多少注释。

求得逆波兰式后,不知自己怎么想的,好像知道怎么计算它的值,看书之后真是那样求解的,突然间有种莫名的喜悦。

刚开始也没有实现蕴含和等值的功能,因为对与、或、非更熟悉,所以只处理了这部分,实现这部分的功能后,才把蕴含和等值的功能加上去,这时就简单得多了,只是稍稍补充和改动就可以了。

而主析取范式和主合取范式也是这样的,刚开始并没有求这个部分,只是在最后时才加上去的。

只不过实现了前面的要求,后面的就显得简单多了。

本程序有个缺点就是,没有用动态分配内存的方法,只是定义了一般够用的数组容量,容量为100个字符,这样的话造成硬件资源的浪费,灵活性不够。

这次试验让我学到了一些新知识,也让我认识到自己在编程方面的一些不足。

以后继续努力!七、源程序清单后面是源程序清单,由于word软件与所用编程软件界面大小不一样,所以把代码复制过来可能出现一行变两行、不对齐等情况。

/*========================================================================*/ /* 求取任意命题公式的真值表及主范式 */ /*========================================================================*/#include <stdio.h>#include <stdlib.h>#include <string.h>/*-----------------------------------------------------------------------*/ // 读入命题公式,并判断其合法性,若非法则重新输入/*-----------------------------------------------------------------------*/ char *pp,formula[100]={0};int valid=1;char *getformula(){char temp[100]={0},tempsign[3]={0};int i,j,len,flag=0;printf("\n请输入命题公式\n");printf("\n\"/\"表示非,\"*\"表示合取,\"+\"表示析取,\">\"表示蕴含,\":\"表示等值\n");printf("\n括号均用\"()\"表示:\n");printf("\n命题变元用大写英文字母表示,以回车键结束输入:\n\n");while(flag==0){gets(temp);if(temp[0]=='\0'){valid=0;break;}for(j=0,i=0;*(temp+i);i++)if(*(temp+i)!=' '){*(formula+j)=*(temp+i);j++;}len=strlen(formula);if(!(formula[len-1]>=65&&formula[len-1]<=90||formula[len-1]==')')|| !((formula[0]>=65&&formula[0]<=90)||formula[0]=='('||formula[0]== '/'))flag=0;else{for(pp=formula;*pp!='\0';pp++){if(!((*pp>=65&&*pp<=90)||*pp=='/'||*pp=='*'||*pp=='+'||*pp=='>'||*pp==':'||*pp== '('||*pp==')')){flag=0;break;}else{tempsign[0]=*pp;tempsign[1]=*(pp+1);tempsign[2]='\0';if(strcmp(tempsign,"(+")==0||strcmp(tempsign,"(*")==0||strcmp(tempsign,"/)")==0| |strcmp(tempsign,"+)")==0||strcmp(tempsign,"*)")==0||strcmp(tempsign,")/")==0||strcmp(tempsign,"*+")==0||strcmp(tempsign,"/*")==0||strcmp(tempsign,")(")==0||strcmp(tempsign,"+*")==0||strcmp(tempsign,"/+")==0||strcmp(tempsign,"()")==0||strcmp(tempsign,">+")==0||strcmp(tempsign,"+>")==0||strcmp(tempsign,"*>")==0|| strcmp(tempsign,">*")==0||strcmp(tempsign,"(>")==0||strcmp(tempsign,">)")==0|| strcmp(tempsign,"/>")==0||strcmp(tempsign,"+:")==0||strcmp(tempsign,":+")==0|| strcmp(tempsign,"*:")==0||strcmp(tempsign,":*")==0||strcmp(tempsign,":>")==0||strcmp(tempsign,">:")==0||strcmp(tempsign,"/:")==0||strcmp(tempsign,"(:")==0|| strcmp(tempsign,":)")==0){flag=0;break;}if((tempsign[0]>=65&&tempsign[0]<=90)&&(tempsign[1]>=65&&tempsign[1]<=90)) {flag=0;break;}if(((tempsign[0]>=65&&tempsign[0]<=90)&&(tempsign[1]=='/'||tempsign[1]=='('))|| ((tempsign[1]>=65&&tempsign[1]<=90)&&tempsign[0]==')')) {flag=0;break;}elseflag=1;}}}if(flag==0){printf("表达式有误,请重新输入:\n");for(i=0;*(temp+i)!='\0';i++)*(temp+i)='\0';for(i=0;*(formula+i)!='\0';i++)*(formula+i)='\0';}}pp=formula;// if(flag!=0)printf("%s",pp);return pp;}/*-----------------------------------------------------------------------*/ // 将中缀表达式转化为后缀表达式/*-----------------------------------------------------------------------*/ char suf_formula[100]={0};char *convert_suffix(char *formula){// char plus,and,not,left,right;char stack[30],digit_stack[30];char *pt;int i=0,j=0,top=1,digit_top=1;pt=formula;for(i=0;*pt;pt++){if(*pt>=65&&*pt<=90)suf_formula[i++]=*pt;elseswitch(*pt) //优先级高低顺序,栈内(、:、>、+、*、/依次升高,分别用1、2、3、4、5、6表示{case ':':// if(stack[0]=='\0')// {// stack[top++]='+';// digit_stack[digit_top++]=2;// }// else{for(;2<=digit_stack[digit_top-1];top--,digit_top--){suf_formula[i++]=stack[top-1];stack[top-1]='\0';digit_stack[digit_top-1]=0;}stack[top++]=':';digit_stack[digit_top++]=2;}break;case '>':// if(stack[0]=='\0')// {// stack[top++]='+';// digit_stack[digit_top++]=2;// }// else{for(;3<=digit_stack[digit_top-1];top--,digit_top--){suf_formula[i++]=stack[top-1];stack[top-1]='\0';digit_stack[digit_top-1]=0;}stack[top++]='>';digit_stack[digit_top++]=3;}break;case '+':// if(stack[0]=='\0')// {// stack[top++]='+';// digit_stack[digit_top++]=2;// }// else{for(;4<=digit_stack[digit_top-1];top--,digit_top--){suf_formula[i++]=stack[top-1];stack[top-1]='\0';digit_stack[digit_top-1]=0;}stack[top++]='+';digit_stack[digit_top++]=4;}break;case '*': //if(stack[0]=='\0')// {// stack[top++]='+';// digit_stack[digit_top++]=3;// }//else{for(;5<=digit_stack[top-1];top--,digit_top--){suf_formula[i++]=stack[top-1];stack[top-1]='\0';digit_stack[digit_top-1]=0;}stack[top++]='*';digit_stack[digit_top++]=5;}break;case '/':// if(stack[0]=='\0')// {// stack[top++]='+';// digit_stack[digit_top++]=4;// }// else{for(;6<=digit_stack[top-1];top--,digit_top--){suf_formula[i++]=stack[top-1];stack[top-1]='\0';digit_stack[digit_top-1]=0;}stack[top++]='/';digit_stack[digit_top++]=6;}break;case '(': stack[top++]='(';digit_stack[digit_top++]=1;break;case ')': for(;stack[top-1]!='(';top--,digit_top--) {suf_formula[i++]=stack[top-1];stack[top-1]='\0';digit_stack[digit_top-1]=0;}stack[top-1]='\0';digit_stack[top-1]=0;top--;digit_top--;break;default:;}}for(;top>=1;i++,top--){if(stack[top-1])suf_formula[i]=stack[top-1];}printf("\n");// printf("%s\n",suf_formula);return suf_formula;}/*---------------------------------------------------------------------------*/// 统计后缀表达式中的变元/*---------------------------------------------------------------------------*/char var[16]={0};void variable(char *suf_formula){int i,j,len=0,flag=0;char temp;for(i=0;*(suf_formula+i);i++) //统计后缀表达式中的{ //变元if(suf_formula[i]>=65&&suf_formula[i]<=90) //{ //for(j=0;*(var+j);j++)if(suf_formula[i]==var[j]){flag=1;break;}if(flag!=1){len=strlen(var);var[len]=suf_formula[i];}flag=0;}}for(i=0;*(var+i);i++) //从小到大排列变元for(j=i+1;*(var+j);j++)if(var[i]>var[j]){temp=var[i];var[i]=var[j];var[j]=temp;}// return var;}/*-----------------------------------------------------------------------*/ // 计算后缀表达式的值/*-----------------------------------------------------------------------*/ char normal_form[100][16]={0};void calc(char *suf_formula){char bin_val[16]={0}; //指派真值char suf_val[100]={0}; //后缀表达式相应的变元真值、运算符构成的序列inti,j,end=0,sum,result=1,index,temp_index,flag=0,xiqu_num=0,hequ_num=0;char *p,temp;int xiqu[50]={0},hequ[50]={0};variable(suf_formula);index=strlen(var);temp_index=index;if(index==0) //根据变元数计算指派的真值的最大值 result=1;elsefor(;temp_index>0;temp_index--)result=result*2;printf("\n表达式真值表如下\n\n");for(i=0;*(var+i);i++)printf("%c ",*(var+i));printf("\t\t");printf("%s\n\n",formula);for(sum=0;sum<result;sum++){j=sum;for(i=0;i<16;i++)bin_val[i]=0+'0';for(i=0;j!=0;i++) //指派的真值以二进制字符串形式存储 {bin_val[i]=j%2+'0';j=j/2;}// printf("%s\n",formula);// for(i=0;*(var+i);i++) //输出公式中所含变元// printf("%c ",*(var+i));// printf("\n");for(j=index;j>0;j--) //输出指派的真值printf("%d ",bin_val[j-1]-'0');// printf("\n");strcpy(suf_val,suf_formula);for(i=0;i<index/2;i++) //因变元(大写英文字母)从小到大排列,以A为最高位,{ //而上面指派的真值刚好从bin_val低位(对应A位)开始,temp=bin_val[i]; //故需将真值序列反序bin_val[i]=bin_val[index-i-1];bin_val[index-i-1]=temp;}for(i=0;suf_formula[i];i++)for(j=0;var[j];j++)if(var[j]==suf_formula[i])suf_val[i]=bin_val[j];// printf("\n%s",suf_val);p=suf_val;for(i=0;*(p+i);) //计算由变元和运算符构成的后缀表达式 {switch(*(p+i)){case ':': if(*(p+i-1)==*(p+i-2)){*(p+i-2)='1';for(j=i+1;*(p+j);j++)*(p+j-2)=*(p+j);*(p+j-1)='\0';*(p+j-2)='\0';// printf("\n%s\n",suf_val);}else{*(p+i-2)='0';for(j=i+1;*(p+j);j++)*(p+j-2)=*(p+j);*(p+j-1)='\0';*(p+j-2)='\0';// printf("\n%s\n",suf_val);}i=0;break;case '>': if(*(p+i-1)=='0'&&*(p+i-2)=='1'){*(p+i-2)='0';for(j=i+1;*(p+j);j++)*(p+j-2)=*(p+j);*(p+j-1)='\0';*(p+j-2)='\0';// printf("\n%s\n",suf_val);}else{*(p+i-2)='1';for(j=i+1;*(p+j);j++)*(p+j-2)=*(p+j);*(p+j-1)='\0';*(p+j-2)='\0';// printf("\n%s\n",suf_val);}i=0;break;case '+': if(*(p+i-1)=='1'&&*(p+i-2)=='1'){*(p+i-2)='1';for(j=i+1;*(p+j);j++)*(p+j-2)=*(p+j);*(p+j-1)='\0';*(p+j-2)='\0';// printf("\n%s\n",suf_val);}else{*(p+i-2)=(*(p+i-2)-'0')+(*(p+i-1)-'0')+'0';for(j=i+1;*(p+j);j++)*(p+j-2)=*(p+j);*(p+j-1)='\0';*(p+j-2)='\0';// printf("\n%s\n",suf_val);}i=0;break;case '*': *(p+i-2)= (*(p+i-2)-'0')*(*(p+i-1)-'0')+'0'; for(j=i+1;*(p+j);j++)*(p+j-2)=*(p+j);*(p+j-1)='\0';*(p+j-2)='\0';// printf("\n%s\n",suf_val);i=0;break;case '/': *(p+i-1)=!(*(p+i-1)-'0')+'0';for(j=i+1;*(p+j);j++)*(p+j-1)=*(p+j);*(p+j-1)='\0';// printf("\n%s\n",suf_val);i=0;break;default: i++;if(*(suf_val+1)=='\0')end=1;}if(end==1)break;}end=0;printf("\t\t%d\n",*p-'0');if(*p-'0'==1)xiqu[xiqu_num++]=sum+1;elseif(*p-'0'==0)hequ[hequ_num++]=sum+1;}printf("\n主析取范式如下:\n\n");for(i=0;xiqu[i]!=0;i++){printf("M%d",xiqu[i]-1);if(xiqu[i+1]!=0)printf("+");// if((i+1)%6==0) printf("\n");}printf("\n\n主合取范式如下:\n\n");for(i=0;hequ[i]!=0;i++){printf("m%d",hequ[i]-1);if(hequ[i+1]!=0)printf("*");// if((i+1)%6==0) printf("\n");}}/*-----------------------------------------------------------------------*/ // 主函数/*-----------------------------------------------------------------------*/ int main(){char *formula;formula=getformula();if(valid==1) //输入的表达式非空才可继续执行(即第一个字符不是回车符){convert_suffix(formula); calc(suf_formula);}getchar();return 0;}。

相关文档
最新文档