“邻接矩阵表示的带权有向图(网)”演示程序
- 格式:doc
- 大小:99.05 KB
- 文档页数:8
图-存储结构-数组表⽰法(邻接矩阵)⽂字描述 ⽤两个数组分别存储顶点信息和边/弧信息。
⽰意图算法分析 构造⼀个采⽤邻接矩阵作存储结构、具有n个顶点和e条边的⽆向⽹(图)G的时间复杂度是(n*n + e*n), 其中对邻接矩阵G.arcs的初始化耗费了n*n的时间。
借助于邻接矩阵容易判定两个顶点之间是否有边/弧相连,并容易求得各个顶点的度。
对于⽆向图,顶点vi的度是邻接矩阵地i⾏(或第i列)的元素之和;对于有向图,第i⾏的元素之和为顶点vi的出度;第j列的元素之和为顶点vj的⼊度;代码实现1/*2以数组表⽰法(邻接矩阵)作为图的存储结构创建图。
3*/4 #include <stdio.h>5 #include <stdlib.h>6 #include <string.h>78#define INFINITY 100000 //最⼤值9#define MAX_VERTEX_NUM 20 //最⼤顶点数10 typedef enum {DG, DN, UDG, UDN} GraphKind; //{有向图,有向⽹,⽆向图,⽆向⽹}11 typedef int VRType;12 typedef char VertexType;13 typedef struct{14char note[10];15 }InfoType;16 typedef struct ArcCell{17 VRType adj; //顶点关系类型:1)对⽆权图,⽤1或0表⽰相邻否;2)对带权图,则为权值类型18 InfoType *info; //该弧相关信息的指针19 }ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];20 typedef struct{21 VertexType vexs[MAX_VERTEX_NUM]; //顶点向量22 AdjMatrix arcs; //邻接矩阵23int vexnum, arcnum; //图的当前顶点数和弧数24 GraphKind kind; //图的种类标志25 }MGraph;2627/*28若G中存在顶点u,则返回该顶点在图中位置;否则返回-1。
邻接矩阵的有向图⼀、邻接矩阵有向图的介绍邻接矩阵有向图是指通过邻接矩阵表⽰的有向图。
待补充;上⾯的图G2包含了"A,B,C,D,E,F,G"共7个顶点,⽽且包含了"<A,B>,<B,C>,<B,E>,<B,F>,<C,E>,<D,C>,<E,B>,<E,D>,<F,G>"共9条边。
上图右边的矩阵是G2在内存中的邻接矩阵⽰意图。
A[i][j]=1表⽰第i个顶点到第j个顶点是⼀条边,A[i][j]=0则表⽰不是⼀条边;⽽A[i][j]表⽰的是第i⾏第j列的值;例如,A[1,2]=1,表⽰第1个顶点(即顶点B)到第2个顶点(C)是⼀条边。
⼆、邻接矩阵有向图的代码说明1. 基本定义#define MAX 100class MatrixDG {private:char mVexs[MAX]; // 顶点集合int mVexNum; // 顶点数int mEdgNum; // 边数int mMatrix[MAX][MAX]; // 邻接矩阵public:// 创建图(⾃⼰输⼊数据)MatrixDG();// 创建图(⽤已提供的矩阵)MatrixDG(char vexs[], int vlen, char edges[][2], int elen);~MatrixDG();// 打印矩阵队列图void print();private:// 读取⼀个输⼊字符char readChar();// 返回ch在mMatrix矩阵中的位置int getPosition(char ch);};MatrixDG是邻接矩阵有向图对应的结构体。
mVexs⽤于保存顶点,mVexNum是顶点数,mEdgNum是边数;mMatrix则是⽤于保存矩阵信息的⼆维数组。
例如,mMatrix[i][j]=1,则表⽰"顶点i(即mVexs[i])"和"顶点j(即mVexs[j])"是邻接点,且顶点i是起点,顶点j是终点。
一、判断题 (每题1分,共131分)1. 线性表的逻辑顺序总是与其物理顺序一致。
()【答案】错2. 线性表的顺序存储优于链式存储。
()【答案】错3. 在长度为n的顺序表中,求第i个元素的直接前驱算法的时间复杂度为0(1)。
()【答案】对4. 若一棵二叉树中的结点均无右孩子,则该二叉树的中根遍历和后根遍历序列正好相反。
()【答案】错5. 顺序表和一维数组一样,都可以按下标随机(或直接)访问。
()【答案】对6. 内部排序是指排序过程在内存中进行的排序。
()【答案】对7. 当待排序序列初始有序时,简单选择排序的时间复杂性为O(n)。
()【答案】错8. 用邻接矩阵存储一个图时,在不考虑压缩存储的情况下,所占用的存储空间大小只与图中的顶点个数有关,而与图的边数无关。
( )【答案】对9. 任何一棵二叉树的叶结点在三种遍历中的相对次序是不变的。
()【答案】对10. 若将一批杂乱无章的数据按堆结构组织起来, 则堆中数据必然按从小到大的顺序线性排列。
( )【答案】错11. 如果采用如下方法定义一维字符数组:int maxSize = 30;char * a = new char[maxSize];则这种数组在程序执行过程中不能扩充。
()【答案】错12. 使用三元组表示稀疏矩阵中的非零元素能节省存储空间。
()【答案】对13. 对稀疏矩阵进行压缩存储是为了节省存储空间。
()【答案】对14. 当向一个最小堆插入一个具有最小值的元素时,该元素需要逐层向上调整,直到被调整到堆顶位置为止。
( )【答案】对15. 哈希查找法中解决冲突问题的常用方法是除留余数法。
()【答案】错16. 对具有n个结点的堆进行插入一个元素运算的时间复杂度为O(n)。
( )【答案】错17. 堆排序是一种稳定的排序算法。
( )【答案】错18. 如果有向图中各个顶点的度都大于2,则该图中必有回路。
( )【答案】错19. 在一个顺序存储的循环队列中, 队头指针指向队头元素的后一个位置。
《数据科学与大数据通识导论》题库及答案1.数据科学的三大支柱与五大要素是什么?答:数据科学的三大主要支柱为:Datalogy (数据学):对应数据管理 (Data management)Analytics (分析学):对应统计方法 (Statistical method)Algorithmics (算法学):对应算法方法 (Algorithmic method)数据科学的五大要素:A-SATA模型分析思维 (Analytical Thinking)统计模型 (Statistical Model)算法计算 (Algorithmic Computing)数据技术 (Data Technology)综合应用 (Application)2.如何辨证看待“大数据”中的“大”和“数据”的关系?字面理解Large、vast和big都可以用于形容大小Big更强调的是相对大小的大,是抽象意义上的大大数据是抽象的大,是思维方式上的转变量变带来质变,思维方式,方法论都应该和以往不同计算机并不能很好解决人工智能中的诸多问题,利用大数据突破性解决了,其核心问题变成了数据问题。
3.怎么理解科学的范式?今天如何利用这些科学范式?科学的范式指的是常规科学所赖以运作的理论基础和实践规范,是从事某一科学的科学家群体所共同遵从的世界观和行为方式。
第一范式:经验科学第二范式:理论科学第三范式:计算科学第四范式:数据密集型科学今天,是数据科学,统一于理论、实验和模拟4.从人类整个文明的尺度上看,IT和DT对人类的发展有些什么样的影响和冲击?以控制为出发点的IT时代正在走向激活生产力为目的的DT(Data Technology)数据时代。
大数据驱动的DT时代由数据驱动的世界观大数据重新定义商业新模式大数据重新定义研发新路径大数据重新定义企业新思维5.大数据时代的思维方式有哪些?“大数据时代”和“智能时代”告诉我们:数据思维:讲故事→数据说话总体思维:样本数据→全局数据容错思维:精确性→混杂性、不确定性相关思维:因果关系→相关关系智能思维:人→人机协同(人 + 人工智能)6.请列举出六大典型思维方式;直线思维、逆向思维、跳跃思维、归纳思维、并行思维、科学思维7.大数据时代的思维方式有哪些?同58.二进制系统是如何实现的?计算机用0和1来表示和存储所有的数据,它的基数为2,进位规则是“逢二进一”,用1表示开,0表示关9.解释比特、字节和十六进制表示。
数据结构—统计有向图中每个顶点的出度和⼊度(以邻接矩阵和邻接表两种⼊式实现)⼊、邻接矩阵实现假设不带权有向图采⼊邻接矩阵 g 存储,设计实现以下功能的算法:(1)求出图中每个顶点的⼊度。
(2)求出图中每个顶点的出度。
(3)求出图中出度为 0 的顶点数。
#include#include#includeusing namespace std;#define INFINITY 65535#define MAX_VERTEX_NUM 100typedef char VertexType;typedef struct {VertexType vexs[MAX_VERTEX_NUM];顶点 //数组int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];邻接矩 //阵int v, e; 图顶点//和边的数量} MGraph;int num=0;全局变量负责统计出度为 0 的顶点个数void CreateMGraph(MGraph &G){int i,j,k,w;printf("输⼊顶点数和边数:\n");scanf("%d%d",&G.v,&G.e);//for(i=0;iG.arcs[i][j]=INFINITY;初始化邻接//矩阵for(k=0;k{printf("输⼊边(i,j)上的下标 i,j 和权 w\n");scanf("%d%d%d",&i,&j,&w);G.arcs[i][j]=w;}}void indu(MGraph G){int n=0;printf("⼊度:\n");for(int i=0;i//scanf("%c",G.vexs[i]);for(i=0;i{for(int j=0;j} if(n==0) num++; printf("%d ",n); n=0; } } int main() { MGraph G; CreateMGraph(G); { indu(G); if(G.arcs[j][i]!=INFINITY) printf("\n"); n++; outdu(G); } printf("\n"); printf("%d ",n); printf("出度为 0 的顶点个数:%d",num); n=0; return 0; } } } #include#include#includeusing namespace std;#define INFINITY 65535#define MAX_VERTEX_NUM 100typedef int VertexType;int num=0;n++;⼊、邻接表void outdu(MGraph G) 要 不 //要加引⼊,有时候需要仔细考虑⼊下 { 假设不带权有向图采⼊邻接表 G 存储,设计实现以下功能的算法: int n=0;(1) 求出图中每个顶点的⼊度。
图基本算法图的表⽰⽅法邻接矩阵邻接表 要表⽰⼀个图G=(V,E),有两种标准的表⽰⽅法,即邻接表和邻接矩阵。
这两种表⽰法既可⽤于有向图,也可⽤于⽆向图。
通常采⽤邻接表表⽰法,因为⽤这种⽅法表⽰稀疏图(图中边数远⼩于点个数)⽐较紧凑。
但当遇到稠密图(|E|接近于|V|^2)或必须很快判别两个给定顶点⼿否存在连接边时,通常采⽤邻接矩阵表⽰法,例如求最短路径算法中,就采⽤邻接矩阵表⽰。
图G=<V,E>的邻接表表⽰是由⼀个包含|V|个列表的数组Adj所组成,其中每个列表对应于V中的⼀个顶点。
对于每⼀个u∈V,邻接表Adj[u]包含所有满⾜条件(u,v)∈E的顶点v。
亦即,Adj[u]包含图G中所有和顶点u相邻的顶点。
每个邻接表中的顶点⼀般以任意顺序存储。
如果G是⼀个有向图,则所有邻接表的长度之和为|E|,这是因为⼀条形如(u,v)的边是通过让v出现在Adj[u]中来表⽰的。
如果G是⼀个⽆向图,则所有邻接表的长度之和为2|E|,因为如果(u,v)是⼀条⽆向边,那么u会出现在v的邻接表中,反之亦然。
邻接表需要的存储空间为O(V+E)。
邻接表稍作变动,即可⽤来表⽰加权图,即每条边都有着相应权值的图,权值通常由加权函数w:E→R给出。
例如,设G=<V,E>是⼀个加权函数为w的加权图。
对每⼀条边(u,v)∈E,权值w(u,v)和顶点v⼀起存储在u的邻接表中。
邻接表C++实现:1 #include <iostream>2 #include <cstdio>3using namespace std;45#define maxn 100 //最⼤顶点个数6int n, m; //顶点数,边数78struct arcnode //边结点9 {10int vertex; //与表头结点相邻的顶点编号11int weight = 0; //连接两顶点的边的权值12 arcnode * next; //指向下⼀相邻接点13 arcnode() {}14 arcnode(int v,int w):vertex(v),weight(w),next(NULL) {}15 arcnode(int v):vertex(v),next(NULL) {}16 };1718struct vernode //顶点结点,为每⼀条邻接表的表头结点19 {20int vex; //当前定点编号21 arcnode * firarc; //与该顶点相连的第⼀个顶点组成的边22 }Ver[maxn];2324void Init() //建⽴图的邻接表需要先初始化,建⽴顶点结点25 {26for(int i = 1; i <= n; i++)27 {28 Ver[i].vex = i;29 Ver[i].firarc = NULL;30 }31 }3233void Insert(int a, int b, int w) //尾插法,插⼊以a为起点,b为终点,权为w的边,效率不如头插,但是可以去重边34 {35 arcnode * q = new arcnode(b, w);36if(Ver[a].firarc == NULL)37 Ver[a].firarc = q;38else39 {40 arcnode * p = Ver[a].firarc;41if(p->vertex == b) //如果不要去重边,去掉这⼀段42 {43if(p->weight < w)44 p->weight = w;45return ;46 }47while(p->next != NULL)48 {49if(p->next->vertex == b) //如果不要去重边,去掉这⼀段50 {51if(p->next->weight < w);52 p->next->weight = w;53return ;54 }55 p = p->next;56 }57 p->next = q;58 }59 }60void Insert2(int a, int b, int w) //头插法,效率更⾼,但不能去重边61 {62 arcnode * q = new arcnode(b, w);63if(Ver[a].firarc == NULL)64 Ver[a].firarc = q;65else66 {67 arcnode * p = Ver[a].firarc;68 q->next = p;69 Ver[a].firarc = q;70 }71 }7273void Insert(int a, int b) //尾插法,插⼊以a为起点,b为终点,⽆权的边,效率不如头插,但是可以去重边74 {75 arcnode * q = new arcnode(b);76if(Ver[a].firarc == NULL)77 Ver[a].firarc = q;78else79 {80 arcnode * p = Ver[a].firarc;81if(p->vertex == b) return; //去重边,如果不要去重边,去掉这⼀句82while(p->next != NULL)83 {84if(p->next->vertex == b) //去重边,如果不要去重边,去掉这⼀句85return;86 p = p->next;87 }88 p->next = q;89 }90 }91void Insert2(int a, int b) //头插法,效率跟⾼,但不能去重边92 {93 arcnode * q = new arcnode(b);94if(Ver[a].firarc == NULL)95 Ver[a].firarc = q;96else97 {98 arcnode * p = Ver[a].firarc;99 q->next = p;100 Ver[a].firarc = q;101 }102 }103void Delete(int a, int b) //删除以a为起点,b为终点的边104 {105 arcnode * p = Ver[a].firarc;106if(p->vertex == b)107 {108 Ver[a].firarc = p->next;109 delete p;110return ;111 }112while(p->next != NULL)113if(p->next->vertex == b)114 {115 p->next = p->next->next;116 delete p->next;117return ;118 }119 }120121void Show() //打印图的邻接表(有权值)122 {123for(int i = 1; i <= n; i++)124 {125 cout << Ver[i].vex;126 arcnode * p = Ver[i].firarc;127while(p != NULL)128 {129 cout << "->(" << p->vertex << "," << p->weight << ")";130 p = p->next;131 }132 cout << "->NULL" << endl;133 }134 }135136void Show2() //打印图的邻接表(⽆权值)137 {138for(int i = 1; i <= n; i++)140 cout << Ver[i].vex;141 arcnode * p = Ver[i].firarc;142while(p != NULL)143 {144 cout << "->" << p->vertex;145 p = p->next;146 }147 cout << "->NULL" << endl;148 }149 }150int main()151 {152int a, b, w;153 cout << "Enter n and m:";154 cin >> n >> m;155 Init();156while(m--)157 {158 cin >> a >> b >> w; //输⼊起点、终点159 Insert(a, b, w); //插⼊操作160 Insert(b, a, w); //如果是⽆向图还需要反向插⼊161 }162 Show();163return0;164 }View Code 邻接表表⽰法也有潜在的不⾜之处,即如果要确定图中边(u,v)是否存在,只能在顶点u邻接表Adj[u]中搜索v,除此之外没有其他更快的办法。
数据结构与算法课程设计报告课程设计题目:图的算法实现专业班级:信息与计算科学1002班目录摘要 (1)1、引言 (1)2、需求分析 (1)3、概要设计 (2)4、详细设计 (4)5、程序设计 (10)6、运行结果 (18)7、总结体会 (19)摘要(题目): 图的算法实现实验内容图的算法实现问题描述:(1)将图的信息建立文件;(2)从文件读入图的信息,建立邻接矩阵和邻接表;(3)实现Prim、Kruskal、Dijkstra和拓扑排序算法。
关键字:邻接矩阵、Dijkstra和拓扑排序算法1.引言本次数据结构课程设计共完成图的存储结构的建立、Prim、Kruskal、Dijkstra 和拓扑排序算法等问题。
通过本次课程设计,可以巩固和加深对数据结构的理解,通过上机和程序调试,加深对课本知识的理解和熟练实践操作。
(1)通过本课程的学习,能够熟练掌握数据结构中图的几种基本操作;(2)能针对给定题目,选择相应的数据结构,分析并设计算法,进而给出问题的正确求解过程并编写代码实现。
使用语言:CPrim算法思想:从连通网N={V,E}中的某一顶点v0出发,选择与它关联的具有最小权值的边(v0,v),将其顶点加入到生成树的顶点集合V中。
以后每一步从一个顶点在V中,而另一个顶点不在V中的各条边中选择权值最小的边(u,v),把它的顶点加入到集合V中。
如此继续下去,直到网中的所有顶点都加入到生成树顶点集合V中为止。
拓扑排序算法思想:1、从有向图中选取一个没有前驱的顶点,并输出之;2、从有向图中删去此顶点以及所有以它为尾的弧;重复上述两步,直至图空,或者图不空但找不到无前驱的顶点为止。
没有前驱-- 入度为零,删除顶点及以它为尾的弧-- 弧头顶点的入度减1。
2.需求分析1、通过键盘输入建立一个新的有向带权图,建立相应的文件;2、对建立的有向带权图进行处理,要求具有如下功能:(1)用邻接矩阵和邻接表的存储结构输出该有向带权图,并生成相应的输出结果;(2)用Prim、Kruskal算法实现对图的最小生成树的求解,并输出相应的输出结果;(3)用Dijkstra算法实现对图中从某个源点到其余各顶点的最短路径的求解,并输出相应的输出结果;(4)实现该图的拓扑排序算法。
邻接矩阵检索-概述说明以及解释1.引言1.1 概述:邻接矩阵是图论中一种常见的数据结构,用于描述图中各个顶点之间的连接关系。
在邻接矩阵中,图的顶点通常用矩阵的行和列来表示,矩阵的元素则表示顶点之间是否相连或具有何种关系。
邻接矩阵在图论中有着广泛的应用,可以用来表示网络结构、社交关系、路线规划等各种场景。
通过邻接矩阵,我们可以方便地进行图的遍历、查找、最短路径等操作,为解决各类实际问题提供了便利。
本文将重点介绍邻接矩阵的定义与概念,探讨邻接矩阵在图论中的应用,并详细介绍邻接矩阵检索算法,希望能够为读者提供对邻接矩阵及其应用的深入理解。
1.2文章结构1.2 文章结构本文主要分为三个部分,即引言、正文和结论。
在引言部分,将会对邻接矩阵进行概述,介绍文章的结构和目的。
其中,概述部分将对邻接矩阵的基本定义和概念进行简要介绍,为后续的正文部分做铺垫;文章结构部分将给出整篇文章的框架和布局,方便读者快速了解文章内容;而目的部分则会说明本文撰写的目的和意义。
在正文部分,将围绕着邻接矩阵展开讨论。
具体而言,将首先介绍邻接矩阵的定义与概念,让读者对其有一个清晰和全面的认识;接着将探讨邻接矩阵在图论中的应用,以便读者更深入地理解这一概念;最后将重点讨论邻接矩阵的检索算法,为读者提供一种快速高效地检索邻接矩阵信息的方法。
在结论部分,将对全文进行总结,回顾本文所涉及的内容和观点;同时也将展望邻接矩阵在未来的应用和发展方向,为读者呈现一幅邻接矩阵所展现出的无限可能;最后提出结论,总结本文的主要观点和贡献,为本文画上一个完整的句号。
1.3 目的邻接矩阵是图论中一种重要的数据结构,用于表示图中各个顶点之间的连通关系。
邻接矩阵检索算法则是基于邻接矩阵的数据结构,用于实现对图的快速检索和查询操作。
本文旨在探讨邻接矩阵检索算法的原理和实现方法,通过深入分析算法的逻辑结构和实用性,帮助读者更好地理解和应用邻接矩阵在图论中的作用。
通过本文的阐述,读者将能够了解邻接矩阵在图论中的重要性和应用价值,掌握邻接矩阵检索算法的具体实现方式,从而提升对图的处理和分析能力。
高级英语(考研方向)邻接矩阵【原创实用版】目录1.邻接矩阵的定义2.邻接矩阵的应用3.邻接矩阵的举例4.邻接矩阵的计算方法正文一、邻接矩阵的定义邻接矩阵(Adjacency Matrix)是一种用来表示有向图或无向图中各个顶点间关系的矩阵。
在矩阵中,行和列都对应图中的顶点。
如果顶点 i 与顶点 j 之间存在一条边,则矩阵的第 i 行第 j 列(记作 aij)处的元素为 1(有向图)或者对应的边的权(带权图);如果顶点 i 与顶点 j 之间不存在边,则 aij 为 0。
二、邻接矩阵的应用邻接矩阵在图论中有着广泛的应用,主要体现在以下几个方面:1.表示图的结构:邻接矩阵可以简洁地表示有向图或无向图的结构,便于进行相关操作和分析。
2.存储图的信息:邻接矩阵可以用来存储图的顶点数、边数以及边的权等信息。
3.计算图的性质:邻接矩阵可以用来计算图的聚类系数、平均路径长度、最短路径等图的性质。
三、邻接矩阵的举例假设有一个无向图,共有 4 个顶点,边的连接关系如下:- 顶点 1 与顶点 2、3、4 相连;- 顶点 2 与顶点 1、3、4 相连;- 顶点 3 与顶点 1、2、4 相连;- 顶点 4 与顶点 1、2、3 相连。
该图的邻接矩阵如下:```1 0 1 10 1 0 11 0 0 11 1 0 1```四、邻接矩阵的计算方法对于无向图,可以采用以下方法计算邻接矩阵:1.初始化一个二维数组,数组的行数和列数分别表示图中的顶点数。
2.遍历图中的每一条边,根据边的起点和终点,将对应的邻接矩阵元素值设为 1。
对于有向图,计算邻接矩阵的方法基本相同,只是在计算邻接矩阵时,需要根据边的方向来设置元素值。
离散数学有向图的路径表示方法有向图是离散数学中的一个重要概念,它由一组顶点和一组有向边组成。
在有向图中,每条边都有一个方向,表示从一个顶点指向另一个顶点。
有向图可以用于表示不同实际问题中的关系和流程,因此了解有向图的路径表示方法对于解决问题至关重要。
在离散数学中,有向图的路径表示方法有多种,以下将介绍三种常见的方法,分别是邻接矩阵表示法、邻接表表示法和关联矩阵表示法。
1. 邻接矩阵表示法:邻接矩阵是一个二维矩阵,用于表示有向图中各顶点之间的关系。
矩阵的行和列代表图中的顶点,矩阵中的元素表示对应顶点之间是否存在直接连接的边。
如果两个顶点之间存在边,则对应的矩阵元素为1;如果两个顶点之间不存在边,则对应的矩阵元素为0。
例如,对于一个有向图G,如果存在一条从顶点A到顶点B的边,则在邻接矩阵中的第A行第B列的元素为1。
邻接矩阵表示法可以通过矩阵的行、列索引来表示有向图中的路径,路径上的顺序即为顶点在矩阵中的索引顺序。
2. 邻接表表示法:邻接表是一种更加紧凑的表示有向图的方法。
它由一个顶点数组和一个边链表组成。
顶点数组中的每个元素表示图中的一个顶点,边链表中的每个节点表示从该顶点出发的边。
邻接表使用链表的方式记录每个顶点所连接的边,其中链表的节点保存了边的终点以及指向下一条边的指针。
在邻接表表示法中,可以通过遍历链表来获取某个顶点的所有直接连接的顶点,从而表示有向图中的路径。
遍历链表的顺序即为顶点与顶点之间路径的顺序。
3. 关联矩阵表示法:关联矩阵是一个二维矩阵,用于表示有向图中顶点和边之间的关系。
矩阵的行代表顶点,矩阵的列代表边,矩阵中的元素表示对应顶点与边之间的连接关系。
关联矩阵表示法可以将有向图中的路径转化为矩阵中的非零元素组成的向量。
矩阵中的每一列表示一条边,矩阵中的每一行表示一个顶点。
如果某个顶点在路径上通过某条边,则对应的矩阵元素为-1;如果某个顶点是路径的起点,则对应的矩阵元素为1;如果某个顶点是路径的终点,则对应的矩阵元素为-1。
班级:信息1102 姓名:贾孟涛========实习报告十四“邻接矩阵表示的带权有向图(网)”演示程序==========(一)、程序的功能和特点该程序可以建立有向图的带权邻接矩阵,能够对建立的邻接矩阵进行添加顶点,添加边和删除顶点,删除边的操作,并能显示输出邻接矩阵。
该程序的特点是采用java面向对象语言,对边,顶点和邻接矩阵用类进行封装。
采用链式存储结构。
(二)、程序的算法设计算法一:“插入一个顶点”算法:1.【逻辑结构与存储结构设计】逻辑结构:线性结构。
存储结构:顺序存储与链式存储结合。
2.【基本操作设计】文字说明:创建新结点,找到结点L位置,在 L后插入新结点。
3.【算法设计】文字说明:(1).首先判断顶点表是否满。
(2).若满则插入失败,放回false。
(3).顶点表若不满,创建新顶点,将新顶点加入顶点表。
(4).插入顶点成功,返回true。
4.【高级语言代码】//插入一个顶点public int InsertVertex ( char vertex ){if(IsGraphFull()) return -1; //插入失败//顶点表增加一个元素VerticesList[CurrentVertices]=vertex;//邻接矩阵增加一行一列for ( int j = 0;j <=CurrentVertices;j++ ) {Edge[CurrentEdges][j]=MaxValue;Edge[j][CurrentEdges]=MaxValue;}Edge[CurrentEdges][CurrentEdges]=0;CurrentVertices++;return CurrentVertices; //插入位置}算法二:“插入一条边”算法:1.【逻辑结构与存储结构设计】逻辑结构:线性结构。
存储结构:链式存储结构。
3.【基本操作设计】文字说明:创建新边结点,再将新创建的边结点插入图中。
4.【算法设计】文字说明:(1).首先判断插入边上的两个顶点编号是否越界。
if (v1 < 0 || v1 > CurrentVertices - 1) return false; if (v2 < 0 || v2 > CurrentVertices - 1) return false; (2).如果越界则插入失败,返回false。
(3).否则创建新边结点(4).再将新创建的边结点插入图中(5) .插入成功返回true。
4.【高级语言代码】//插入一个边public boolean InsertEdge( int v1, int v2, double weight){ if (v1 < 0 || v1 > CurrentVertices - 1)return false; //出错if (v2 < 0 || v2 > CurrentVertices - 1)return false;Edge[v1][v2]=weight; //网,有向边return true;}(三)、程序中类的设计“Graph”类:1.【逻辑结构与存储结构】逻辑结构:网状结构。
存储结构:顺序存储与链式存储结合。
2.【主要成员变量说明】static int MaxEdges = 50;static int MaxVertices = 10;static double MaxValue=9999.9; //无穷大//存放顶点的数组private char VerticesList[]=new char[MaxVertices];//邻接矩阵(存放两个顶点权值)private double Edge[][]=new double[MaxVertices][MaxVertices];private int CurrentEdges; //现有边数private int CurrentVertices; //现有顶点数//构造函数:建立空的邻接矩阵3.【主要成员方法说明】public Graph ( ):为定义的构造函数,建立空的邻接矩阵。
public int FindVertex (char vertex):查找指定的顶点的序号public boolean IsGraphEmpty ( ):判断图是否为空。
public boolean IsGraphFull ( ):判断图是否为满。
public char GetValue ( int i ):按顶点序号返回顶点数据。
public int NumberOfVertices ( ):返回图的顶点数。
public int NumberOfEdges ( ):返回图的边数。
public double GetWeight ( int v1, int v2 ):取得一条边的权值。
public int GetFirstNeighbor ( int v ):取得第一个邻接点的序号public int InsertVertex ( char vertex ):插入一个顶点。
public boolean RemoveVertex ( int v ):删除一个顶点。
public boolean InsertEdge ( int v1,int v2,double weight ):插入一条边。
public boolean RemoveEdge ( int v1, int v2 ):删除一条边。
public void display():显示邻接矩阵。
4.【高级语言代码】// “邻接矩阵”类class Graph {static int MaxEdges = 50;static int MaxVertices = 10;static double MaxValue=9999.9; //无穷大//存放顶点的数组private char VerticesList[]=new char[MaxVertices];//邻接矩阵(存放两个顶点权值)private double Edge[][]=new double[MaxVertices][MaxVertices];private int CurrentEdges; //现有边数private int CurrentVertices; //现有顶点数//构造函数:建立空的邻接矩阵public Graph ( ){for ( int i = 0; i < MaxVertices; i++ )for ( int j = 0; j < MaxVertices; j++ )if(i==j)Edge[i][j] = 0; //对角线else //非对角线上无穷大Edge[i][j] =MaxValue;CurrentEdges = 0; //现有边数CurrentVertices = 0; //现有顶点数}//查找指定的顶点的序号public int FindVertex (char vertex){//在顶点数组里面查找for(int i=0;i<CurrentVertices;i++)if(VerticesList[i]==vertex)return i; //返回下标return -1; //没有找到}//图空否?public boolean IsGraphEmpty ( ){return CurrentVertices==0;}//图满否?public boolean IsGraphFull ( ){return CurrentVertices==MaxVertices ||CurrentEdges==MaxEdges;}//取得顶点数public int NumberOfVertices ( ){return CurrentVertices;}//取得边数public int NumberOfEdges ( ){return CurrentEdges;}//按序号取得顶点值public char GetValue ( int i ){return i >= 0 && i <= CurrentVertices-1? VerticesList[i] : ' ';}//取得一条边的权值public double GetWeight ( int v1, int v2 ){ if (v1 < 0 || v1 > CurrentVertices - 1) return -1.0; //用-1表示出错if (v2 < 0 || v2 > CurrentVertices - 1) return -1.0;return Edge[v1][v2];}//取得第一个邻接点的序号public int GetFirstNeighbor ( int v ){if (v< 0 || v > CurrentVertices - 1)return -1; //用-1表示出错//邻接矩阵的行号和列号是两个邻接点的序号for ( int col = 0; col < CurrentVertices; col++ )if ( Edge[v][col] > 0 && //自身Edge[v][col] < MaxValue ) //无穷大return col;return -1; //无邻接点}//插入一个顶点public int InsertVertex ( char vertex ){if(IsGraphFull()) return -1; //插入失败//顶点表增加一个元素VerticesList[CurrentVertices]=vertex;//邻接矩阵增加一行一列for ( int j = 0;j <=CurrentVertices;j++ ) {Edge[CurrentEdges][j]=MaxValue;Edge[j][CurrentEdges]=MaxValue;}Edge[CurrentEdges][CurrentEdges]=0;CurrentVertices++;return CurrentVertices; //插入位置}//插入一个边public boolean InsertEdge( int v1, int v2, double weight){ if (v1 < 0 || v1 > CurrentVertices - 1)return false; //出错if (v2 < 0 || v2 > CurrentVertices - 1)return false;Edge[v1][v2]=weight; //网,有向边return true;}//删除一个顶点public boolean RemoveVertex ( int v ){if (v< 0 || v > CurrentVertices - 1)return false; //出错//修改顶点表for(int i=v+1;i< CurrentVertices;i++)VerticesList[i-1]=VerticesList[i];//修改邻接矩阵int k=0; //累计将要删去的边数for(int i=0;i< CurrentVertices;i++)if ( Edge[v][i] > 0 && //自身Edge[v][i] < MaxValue ) //无穷大k++; //第v行for(int i=0;i< CurrentVertices;i++)if ( Edge[i][v] > 0 && //自身Edge[i][v] < MaxValue ) //无穷大k++; //第v列//覆盖第v行int j;for(int i=v+1;i< CurrentVertices;i++)for(j=0;j< CurrentVertices;j++)Edge[i-1][j]=Edge[i][j];//覆盖第v列for(j=v+1;j< CurrentVertices;j++)for(int i=0;i< CurrentVertices;i++)Edge[i][j-1]=Edge[i][j];CurrentVertices--; //修改顶点数CurrentEdges-=k; //修改边数return true;}//删除一个边public boolean RemoveEdge ( int v1, int v2 ){ if (v1 < 0 || v1 > CurrentVertices - 1)return false; //用-1表示出错if (v2 < 0 || v2 > CurrentVertices - 1)return false;if ( v1==v2) return false;Edge[v1][v2]=MaxValue; //网,无路径return true;}//打印邻接矩阵public void display(){int i,j;System.out.println(" 顶点表");for(i=0;i<CurrentVertices;i++)System.out.print(VerticesList[i]+" ");System.out.println('\n'+" 邻接矩阵");for(i=0;i<CurrentVertices;i++) {for(j=0;j<CurrentVertices;j++)if(Edge[i][j]==MaxValue)System.out.print('@'+" ");elseSystem.out.print(Edge[i][j]+" ");System.out.println();}}//主函数public static void main(String []args){Graph G=new Graph(); //邻接矩阵//准备有向图(网)数据char c[]={'A','B','C','D','E','F'}; //顶点int v[][]={ //弧{0,1},{0,3},{1,2},{2,3},{4,5},{1,3},{2,4},{3,5},{4,3},{2,5}};double e[]={2.3,3.6,6.5,2.5,1.7,0.8,7.2,9.1,5.2,1.3}; //权//插入顶点for(int i=0;i<6;i++)G.InsertVertex(c[i]);//插入弧for(int i=0;i<10;i++)G.InsertEdge(v[i][0],v[i][1],e[i]);//打印输出G.display();//删除一个顶点G.RemoveVertex(3);G.display();//删除一条边G.RemoveEdge(2,4);G.display();} //main方法结束} //“邻接矩阵”类结束(四)、程序的输入输出和运行结果截屏运行结果如下图所示。