经典代码之图 邻接表转换成邻接矩阵
图的邻接矩阵和邻接表相互转换
图的邻接矩阵和邻接表相互转换图的邻接矩阵存储方法具有如下几个特征:1)无向图的邻接矩阵一定是一个对称矩阵。
2)对于无向图的邻接矩阵的第i 行非零元素的个数正好是第i 个顶点的度()i v TD 。
3)对于有向图,邻接矩阵的第i 行非零元素的个数正好是第i 个顶点的出度()i v OD (或入度()i v ID )。
4)用邻接矩阵方法存储图,很容易确定图中任意两个顶点之间是否有边相连;但是,要确定图中有多少条边,则必须按行、按列对每个元素进行检测,所发费得时间代价大。
邻接表是图的一种顺序存储与链式存储相结合的存储方法。
若无向图中有n 个顶点、e 条边,则它的邻接表需n 个头结点和2e 个表结点。
显然,在边稀疏的情况下,用邻接表表示图比邻接矩阵存储空间。
在无向图的邻接表中,顶点i v 的度恰好是第i 个链表中的结点数,而在有向图中,第i 个链表中结点个数是顶点i v 的出度。
在建立邻接表或邻逆接表时,若输入的顶点信息即为顶点的编号,则建立临接表的时间复杂度是)(e n O +;否则,需要通过查找才能得到顶点在图中位置,则时间复杂度为)*(e n O 。
在邻接表上容易找到任意一顶点的第一个邻接点和下一个邻接点,但要判断任意两个顶点之间是否有边或弧,则需要搜索第i 个或第j 个链表,因此,不及邻接矩阵方便。
邻接矩阵和邻接表相互转换程序代码如下:#include<iostream.h>#define MAX 20//图的邻接表存储表示typedef struct ArcNode{int adjvex; //弧的邻接定点 char info; //邻接点值struct ArcNode *nextarc; //指向下一条弧的指针}ArcNode;typedef struct Vnode{ //节点信息char data;ArcNode *link;}Vnode,AdjList[MAX];typedef struct{AdjList vertices;int vexnum; //节点数int arcnum; //边数}ALGraph;//图的邻接矩阵存储表示typedef struct{int n; //顶点个数char vexs[MAX]; //定点信息int arcs[MAX][MAX]; //边信息矩阵}AdjMatrix;/***_____________________________________________________***///函数名:AdjListToMatrix(AdjList g1,AdjListMatrix &gm,int n)//参数:(传入)AdjList g1图的邻接表,(传入)int n顶点个数,(传出)AdjMatrix gm图的邻接矩阵//功能:把图的邻接表表示转换成图的邻接矩阵表示void AdjListToAdjMatrix(ALGraph gl,AdjMatrix &gm){int i,j,k;ArcNode *p;gm.n=gl.vexnum;for(k=0;k<gl.vexnum;k++)gm.vexs[k]=gl.vertices[k].data;for(i=0;i<MAX;i++)for(j=0;j<MAX;j++)gm.arcs[i][j]=0;for(i=0;i<gl.vexnum;i++){p=gl.vertices[i].link; //取第一个邻接顶点while(p!=NULL){ //取下一个邻接顶点gm.arcs[i][p->adjvex]=1;p=p->nextarc;}}}/***________________________________________________***///函数名:AdjMatrixToAdjListvoid AdjMatrixToAdjList(AdjMatrix gm,ALGraph &gl){int i,j,k,choice;ArcNode *p;k=0;gl.vexnum=gm.n;cout<<"请选择所建立的图形是无向图或是有向图:";cin>>choice;for(i=0;i<gm.n;i++){gl.vertices[i].data=gm.vexs[i];gl.vertices[i].link=NULL;}for(i=0;i<gm.n;i++)for(j=0;j<gm.n;j++)if(gm.arcs[i][j]==1){k++;p=new ArcNode;p->adjvex=j;p->info=gm.vexs[j];p->nextarc=gl.vertices[i].link;gl.vertices[i].link=p;}if(choice==1)k=k/2;gl.arcnum=k;}void CreateAdjList(ALGraph &G){int i,s,d,choice;ArcNode *p;cout<<"请选择所建立的图形是有向图或是无向图:";cin>>choice;cout<<"请输入节点数和边数:"<<endl;cin>>G.vexnum>>G.arcnum;for(i=0;i<G.vexnum;i++){cout<<"第"<<i<<"个节点的信息:";cin>>G.vertices[i].data;G.vertices[i].link=NULL;}if(choice==1){for(i=0;i<2*(G.vexnum);i++){cout<<"边----起点序号,终点序号:";cin>>s>>d;p=new ArcNode;p->adjvex=d;p->info=G.vertices[d].data;p->nextarc=G.vertices[s].link;G.vertices[s].link=p;}}else{for(i=0;i<G.vexnum;i++){cout<<"边----起点序号,终点序号:";cin>>s>>d;p=new ArcNode;p->adjvex=d;p->info=G.vertices[d].data;p->nextarc=G.vertices[s].link;G.vertices[s].link=p;}}}void CreateAdjMatrix(AdjMatrix &M){int i,j,k,choice;cout<<"请输入顶点个数:";cin>>M.n;cout<<"请输入如顶点信息:"<<endl;for(k=0;k<M.n;k++)cin>>M.vexs[k];cout<<"请选择所建立的图形是无向图或是有向图:";cin>>choice;cout<<"请输入边信息:"<<endl;for(i=0;i<M.n;i++)for(j=0;j<M.n;j++)M.arcs[i][j]=0;switch(choice){case 1:{for(k=0;k<M.n;k++){cin>>i>>j;M.arcs[i][j]=M.arcs[j][i]=1;}};break;case 2:{for(k=0;k<M.n;k++){cin>>i>>j;M.arcs[i][j]=1;}};break;}}void OutPutAdjList(ALGraph &G){int i;ArcNode *p;cout<<"图的邻接表如下:"<<endl;for(i=0;i<G.vexnum;i++){cout<<G.vertices[i].data;p=G.vertices[i].link;while(p!=NULL){cout<<"---->("<<p->adjvex<<" "<<p->info<<")";p=p->nextarc;}cout<<endl;}}void OutPutAdjMatrix(AdjMatrix gm){cout<<"图的邻接矩阵如下:"<<endl;for(int i=0;i<gm.n;i++){。
有向图的邻接矩阵
有向图的邻接矩阵有向图的邻接矩阵设有向图,,。
令为邻接到的边的条数,称为D的邻接矩阵,记作。
为图7.12的邻接矩阵,不难看出:(1)(即第i行元素之和为的出度),。
(2)(即第j列元素之和为的入度),。
(3)由(1),(2)可知,为D中边的总数,也可看成是D中长度为1的通路总数,而为D中环的个数,即D中长度为1的回路总数。
D中长度大于等于2的通路数和回路数应如何计算呢,为此,先讨论长度等于2的通路数和回路数。
在图D中,从顶点到顶点的长度等于2的通路,中间必经过一顶点。
对于任意的k,若有通路,必有且,即。
反之,若D中不存在通路,必有或,即。
于是在图D中从顶点到顶点的长度等于2的通路数为:由矩阵的乘法规则知,正好是矩阵中的第i行与第j列元素,记,即就是从顶点到顶点的长度等于2的通路数,时,表示从顶点到顶点的长度等于2的回路数。
因此,即矩阵中所有元素的和为长度等于2的通路总数(含回路),其中对角线的元素和为长度等于2的回路总数。
根据以上分析,则有下面的推论。
定义有向图,,D中长度为的通路数和回路数可以用矩阵(简记)来表示,这里,其中,即则为顶点到顶点长度为的通路数,为到自身长度为的回路数。
中所有元素之和为D中长度为的通路数,而中对角线上元素之和为D中始于(终于)各顶点的长度为的回路数。
在图7.12中,计算,,如下:观察各矩阵发现,,,。
于是,D中到长度为,2的通路有3条,长度为3的通路有4条,长度为4的通路有6条。
由,可知,D中到自身长度为的回路各有1条(此时回路为复杂的)。
由于,所以D中长度为2的通路总数为10,其中有3条回路。
从上述分析,可得下面定理。
定理7.5 设为有向图D的邻接矩阵,,则中元素为到长度为的通路数,为D中长度为的通路总数,其中为D中长度为的回路总数。
若再令矩阵,,……,上面定理有下面推论。
推论设,则中元素为D中到长度小于等于的通路数,为D中长度小于等于的通路总数,其中为D中长度小于等于的回路总数。
中国石油大学期末考试复习题 070109数据结构-18
《数据结构》综合复习资料一、填空题1、数据结构是()。
2、数据结构的四种基本形式为集合、()、()和()。
3、线性结构的基本特征是:若至少含有一个结点,则除起始结点没有直接前驱外,其他结点有且仅有一个直接();除终端结点没有直接()外,其它结点有且仅有一个直接()。
4、堆栈的特点是(),队列的特点是(),字符串中的数据元素为()。
5、字符串s1=“I am a student!”(单词与单词之间一个空格),s2=“student”,则字符串s1的长度为(),串s2是串s1的一个()串,串s2在s1中的位置为()。
6、KMP算法的特点:效率较();()回溯,对主串仅需要从头到尾扫描()遍,可以边读入边匹配。
7、广义表((a),((b),c),(((d))))的长度为(),表头为(),表尾为()。
8、ADT称为抽象数据类型,它是指()。
9、求下列程序的时间复杂度,并用大O表示方法表示()。
for( i=1 ; i<=n ; + + i)for( j=1 ; j<=i; + + j ){ ++x;a[i][j] = x;}10、以下运算实现在链栈上的退栈操作,请在_____处用适当句子予以填充。
int Pop(LstackTp *ls,DataType *x){ LstackTp *p;if(ls!=NULL){ p=ls;*x= ;ls= ;;return(1);}else return(0);}11、用堆栈求中缀表达式a+b*c/d+e*f的后缀表达式,求出的后缀表达式为()。
12、C语言中存储数组是采用以()为主序存储的,在C语言中定义二维数组float a[8][10],每个数据元素占4个字节,则数组共占用()字节的内存。
若第一个数据元素的存储地址为8000,则a[5][8]的存储地址为()。
13、含零个字符的串称为()串,用 表示。
其他串称为()串。
任何串中所含字符的个数称为该串的()。
图基本算法图的表示方法邻接矩阵邻接表
图基本算法图的表⽰⽅法邻接矩阵邻接表 要表⽰⼀个图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,除此之外没有其他更快的办法。
邻接矩阵和度矩阵的公式
邻接矩阵和度矩阵的公式邻接矩阵和度矩阵是图论中常用的两种表示图的方式,它们可以帮助我们更方便地分析和研究图的性质和特征。
邻接矩阵指的是通过矩阵来表示图的边和节点之间的关系,而度矩阵则是表示节点的度数情况的矩阵。
下面我们就来详细讲解这两种矩阵的公式和用法。
一、邻接矩阵邻接矩阵是一种方阵,从第i行第j列到第j行第i列也具有相同的值,表示了节点之间的邻接关系。
主要公式如下:1. 无向图对于一个n个节点的无向图来说,邻接矩阵的元素a[i][j]表示的是节点i和节点j之间是否存在边,其中0表示没有边,1表示有边。
由于是无向图,所以矩阵的上下三角是对称的。
下面是一个无向图的邻接矩阵示例:```0 1 1 01 0 1 01 1 0 10 0 1 0```2. 有向图对于一个n个节点的有向图来说,邻接矩阵的元素a[i][j]表示的是节点i到节点j是否存在有向边,其中0表示没有有向边,1表示有有向边。
下面是一个有向图的邻接矩阵示例:```0 1 0 00 0 1 01 0 0 10 0 1 0```邻接矩阵的优点是方便且易于理解,可以用于表示不同类型的图。
但是在稀疏图中会存在大量的0元素,浪费空间,此时可以使用邻接表优化。
二、度矩阵度矩阵是一个n维的矩阵,表示每个节点的度数情况。
主要公式如下:1. 无向图对于无向图来说,每个节点的度数等于该节点所连的所有边的数量。
度矩阵的第i个对角线元素d[i][i]表示节点i的度数。
下面是一个无向图的度矩阵示例:```2 0 0 00 2 0 00 0 3 00 0 0 1```2. 有向图对于有向图来说,每个节点的入度和出度可以分别计算。
入度是指以节点i为终点的边的数量,出度是指以节点i为起点的边的数量。
度矩阵的第i个对角线元素d[i][i]表示节点i的总度数,即入度与出度之和。
下面是一个有向图的度矩阵示例:```2 1 0 00 0 1 01 0 1 10 1 0 0```度矩阵的优点是可以方便地计算得到每个节点的度数情况,可以用于分析图的特性和性质,如连通性、欧拉图等。
邻接矩阵的应用1
3.1
定义 :设 是图 的结点,则称矩阵 为 的邻接矩阵,其中, 是使 邻接的边的条数 并且 是环时, ,否则 .
例如
则上图的邻接矩阵为:
再如:
它的邻接矩阵为:
3.
性质1 对角线元素全为0当且仅当图 没有环.此时 是对称矩阵.
性质2 在没有环的图中, 等于对应行或列中1的个数.
性质3 的第 行(或第 列)元素之和为结点 的度数 .
欧拉对于一般的图提出了一个普遍的判别法则:要从图中一点出发,经过所有的边一次且仅一次,能回到原来的出发点,则这个图必须是连通的,且每个点都必须与偶数条边相关联.显然,图(1)中的各点都是连通的,但每个点都不是与偶数条边相连接,因此七桥问题不可能有解.1845年,德国物理学家G.R.基尔霍夫为了解决一类线性联立方程组而创建“树”理论.他把电网络和其中的电阻、电容和电感等抽象化,用一个只有点和边组成的组合结构来代替电网络,而不指明每条边所代表的电器元件种类,这样就可以方便地对方程组进行求解 .1852年F.格思里在对地图着色时发现,无论多么复杂的地图,只要用四种颜色就能将相邻区域区分开来。这就是所谓“四色猜想” 经过百余年的努力,直到1976年才由K.阿佩尔和W.赫肯借助电子计算机证明了四色定理.1856年,W.R.哈密顿在给 R.L.格雷夫斯的信中提出一个游戏:用正十二面体上20个顶点表示20个城市,要求游戏者沿着各边行走,走遍每个城市一次且仅一次,最后回到原出发城市。这个游戏促使人们研究如何判断一个图有无这一性质,如果有,则又如何确定这样的路径。这是一个至今尚未完全解决的问题.
深度优先遍历 ,假设初始态是图中所有顶点未曾被访问,从图中某个顶点 出发,访问此顶点,然后依次从 的未被访问的邻接点出发深度优先遍历图,直至图中所有和 有路径相通的顶点都被访问到;若此时图中还有未被访问的顶点,则从一个未被访问的顶点开始,重复上述过程,直至图中所有顶点都被访问为止.显然,这是一个复杂的递归过程 .
邻接矩阵-南京大学
v4
v3
0 0 A(G) 1 1
1 0 0 0 1 1 1 0 1 0 0 0
可推广到简单无向图
举例(邻接矩阵)
v1 v2
v4
v3
0 1 A(G) 1 1
1 0 1 0
1 1 0 1
1 0 1 0
简单无向图的邻接矩阵是对称矩阵
邻接矩阵(adjacency matrix)
简单有向图G = (V, E, ) ,设V=v1,…,vn,E= e1,…,em。
A(G)=aij称为G的邻接矩阵(n×n 阶矩阵),其中
1 如果v i邻接到v j a ij 0 否则
eE. (e)=(vi, vj)
举例(邻接矩阵)
邻接矩阵的运算
逆图(转置矩阵)
设G的邻接矩阵为 A ,则 G 的逆图的邻接矩阵是 A 的转 置矩阵,用AT表示。
0100 0011 A 1101 1000
0011 1010 T A 0100 0110
邻接矩阵的运算
邻接矩阵的运算
顶点的度
行中1的个数就是行中相应结点的出度
列中1的个数就是列中相应结点的入度
v1
v2
v4
v3
Hale Waihona Puke 0 0 A 1 11 0 0 0 1 1 1 0 1 0 0 0
Deg+(1)=1,Deg-(1)=2
Deg+(2)=2,Deg-(2)=2
Deg+(3)=3,Deg-(3)=1 Deg+(4)=1,Deg-(4)=2
邻接表
邻接矩阵的算法
#include"邻接矩阵.h"//图的邻接矩阵存储的初始化算法void InitMatrix(adjmatrix GA,int k){int i,j;for(i=0;i<MaxVertexNum;i++)for(j=0;j<MaxVertexNum;j++)if(i==j) GA[i][j]=0;else if(k) GA[i][j]=MaxValue;else GA[i][j]=0;}//根据一个图的边集生成图的邻接矩阵的算法void CreateMatrix(adjmatrix GA,int n,char*s,int k1,int k2)//k1为0则为无向图否则为有向图,k2为0则为无权图否则为有权图//s字符串用来保存一个图的边集,n为图的顶点数{istrstream sin(s);//定义sin为字符串输入流,与s边集对应char c1,c2,c3;//用来保存从输入流读入的字符int i,j;//WeightType w;//sin>>c1;//if(k1==0&&k2==0)//建立无向无权图do{//从sin流(即字符串s)中读入和处理一条边sin>>c1>>i>>c2>>j>>c3;//依次读入一条边的5个数据GA[i][j]=GA[j][i]=1;//置相应的对称元素为1sin>>c1;//读入逗号成右花括号if(c1=='}') break;//编辑处理完毕,退出循环}while(1);else if(k1==0&&k2!=0)//建立无向有权图do{sin>>c1>>i>>c2>>j>>c3;GA[i][j]=GA[j][i]=w;//置相应的对称元素为wsin>>c1;if(c1==')') break;}while(1);else if(k1==0&&k2!=0)//建立有向无权图do{sin>>c1>>i>>c2>>j>>c3;GA[i][j]=1;//置相应的元素为1sin>>c1;if(c1==')') break;}while(1);else if(k1==0&&k2!=0)//建立有向有权图do{sin>>c1>>i>>c2>>j>>c3;GA[i][j]=w;//置相应的元素为wsin>>c1;if(c1=='}') break;}while(1);}int Degree(adjmatrix GA,int numb)//度数{int i,d=0;for(i=0;i<MaxVertexNum;i++){if(GA[numb][i]!=0 && GA[numb][i]!=MaxValue)d++;}return d;}//输出用邻接矩阵表示一个图的顶点集和边集void PrintMatrix(adjmatrix GA,int n,int k1,int k2){int i,j;cout<<"V={";//输出顶点集开始for(i=0;i<n;i++)cout<<i<<',';//输出顶点集结束cout<<'}'<<endl;cout<<"E=(";//输出边集开始if(k2==0)//对无权图的处理情况{for(i=0;i<n;i++)for(j=0;j<n;j++)if(GA[i][j]==1)if(k1==0)//对无向无权图的处理{if(i<j)//避免输出重复边cout<<'('<<i<<','<<j<<')'<<',';}else //对有向无权图的处理cout<<'<'<<i<<','<<j<<'>'<<',';}else{//对有权图的处理情况for(i=0;i<n;i++)for(j=0;i<n;j++)if(GA[i][j]!=0&&GA[i][j]!=MaxValue)if(k1==0)//的对无向有权图的处理{if(i<j)cout<<'('<<i<<','<<j<<')'<<GA[i][j]<<',';}else //对有向有权图的处理cout<<'<'<<i<<','<<j<<'>'<<GA[i][j]<<',';}cout<<'}'<<endl;}//按图的邻接矩阵输出图的深度优先遍历序列void dfsMatrix(adjmatrix GA,int i,int n,bool*visited){cout<<i<<' ';visited[i]=true;for(int j=0;j<n;j++)if(GA[i][j]!=0&&GA[i][j]!=MaxValue&&!visited[j])dfsMatrix(GA,j,n,visited);}//按图的邻接矩阵输出图的广度优先遍历序列void bfsMatrix(adjmatrix GA,int i,int n,bool*visited){const int MaxSize=30;int q[MaxSize]={0};int front=0,rear=0;cout<<i<<' ';visited[i]=true;q[++rear]=i;while(front!=rear){front=(front+1)%MaxSize;int k=q[front];for(int j=0;j<n;j++){if(GA[k][j]!=0&&GA[k][j]!=MaxValue&&!visited[j]){cout<<j<<' ';visited[j]=true;rear=(rear+1)%MaxSize;q[rear]=j;}}}}void main(){int i,n,k1,k2;cout<<"输入待处理图的定点数:";cin>>n;cout<<"输入图的有无向和有无权选择(0为无,非0为有):";cin>>k1>>k2;bool* visited=new bool[n];adjmatrix ga;InitMatrix(ga,k2);cout<<"输入图的边集:";char*a=new char[100];cin>>a;CreateMatrix(ga,n,a,k1,k2);cout<<"按图的邻接矩阵得到的深度优先遍历序列:"<<endl;for(i=0;i<n;i++)visited[i]=false;dfsMatrix(ga,0,n,visited);cout<<endl;cout<<"按图的邻接矩阵得到的广度优先遍历序列:"<< endl;for(i=0;i<n;i++) visited[i]=false;bfsMatrix(ga,0,n,visited);cout<<endl;cout<<"度数为:"<<Degree(ga,n)<<endl;;PrintMatrix(ga,n,k1,k2);}。
数据结构第7章图习题
第7章图一、单项选择题1.在一个无向图G中,所有顶点的度数之和等于所有边数之和的______倍。
A.l/2 B.1C.2 D.42.在一个有向图中,所有顶点的入度之和等于所有顶点的出度之和的______倍。
A.l/2 B.1C.2 D.43.一个具有n个顶点的无向图最多包含______条边。
A.n B.n+1C.n-1 D.n(n-1)/24.一个具有n个顶点的无向完全图包含______条边。
A.n(n-l) B.n(n+l)C.n(n-l)/2 D.n(n-l)/25.一个具有n个顶点的有向完全图包含______条边。
A.n(n-1) B.n(n+l)C.n(n-l)/2 D.n(n+l)/26.对于具有n个顶点的图,若采用邻接矩阵表示,则该矩阵的大小为______。
A.nB.n×nC.n-1 D.(n-l)×(n-l)7.无向图的邻接矩阵是一个______。
A.对称矩阵B.零矩阵C.上三角矩阵D.对角矩阵8.对于一个具有n个顶点和e条边的无(有)向图,若采用邻接表表示,则表头向量的大小为______。
A.n B.eC.2n D.2e9.对于一个具有n个顶点和e条边的无(有)向图,若采用邻接表表示,则所有顶点邻接表中的结点总数为______。
A.n B.eC.2n D.2e10.在有向图的邻接表中,每个顶点邻接表链接着该顶点所有______邻接点。
A.入边B.出边C.入边和出边D.不是入边也不是出边11.在有向图的逆邻接表中,每个顶点邻接表链接着该顶点所有______邻接点。
A.入边B.出边C.入边和出边D.不是人边也不是出边12.如果从无向图的任一顶点出发进行一次深度优先搜索即可访问所有顶点,则该图一定是______。
A.完全图B.连通图C.有回路D.一棵树13.采用邻接表存储的图的深度优先遍历算法类似于二叉树的______算法。
A.先序遍历B.中序遍历C.后序遍历 D.按层遍历14.采用邻接表存储的图的广度优先遍历算法类似于二叉树的______算法。
邻接表十字链表
(续) for(i=0;i<G->vexnum;i++) printf("%4d",i); printf("\n"); for(i=0;i<G->vexnum;i++) { printf("%6d",i); for(j=0;j<G->vexnum;j++) printf("%4d",G->edges[i][j]);
A B A B
C
D
C
D
图7.6 G2的两棵生成树
例7.1 有n个顶点的连通图最多有多少条边? 最少应多少条边? 解:有n个顶点的连通图最多有n(n-1)/2条 边,也就是一个无向完全图;最少有n-1条 边。
7.2 图的存储结构
图的存储结构除存储图中各个顶点本身 的信息外,同时还要存储顶点之间的所 有关系。图的常用存储结构有邻接矩阵、 邻接表、十字链表。
7.2.1
邻接矩阵
设G=(V,E)是具有n(n>0)个顶点的图,顶 点的顺序依次为(v0,v1,…,vn-1),则 G的邻接矩阵A是n阶方阵,其定义如下: (1) 如果G是无向图,则:
1, 若(vi , v j ) E (G ) A[i ][ j ] 0, 其它
(2) 如果G是有向图,则:
邻接表的头结点和表结点的结构如下:
data
firstarc
adjvex
nextarc
info
头结点
表结点
如图7.8(a)和(b)所示分别为图G1和图G2的 邻接表。
0 1 2 3
A B C D /\ 3 0 /\ /\ 2 1 /\
邻接表转换成邻接矩阵
邻接表转换成邻接矩阵邻接表和邻接矩阵是图数据结构中常见的两种表示方式。
邻接表是一种链式存储结构,适用于稀疏图,而邻接矩阵则是一种二维数组的存储结构,适用于稠密图。
本文将介绍如何将邻接表转换成邻接矩阵,并对其优缺点进行比较。
1. 邻接表在图的邻接表表示中,每个顶点都对应一个链表,该链表存储了与该顶点相连的所有边的信息。
具体来说,可以使用一个数组来存储这些链表。
数组的大小为顶点的个数。
下面是一个示例图的邻接表表示:Vertex: 0 1 2 3Adjacency: 1 → 2 0 → 3 2 → 3 -对应的代码实现如下:class Node:def __init__(self, value):self.value = valueself.next = Noneclass Graph:def __init__(self, vertices):self.vertices = verticesself.adj_list = [None] * verticesdef add_edge(self, src, dest):node = Node(dest)node.next = self.adj_list[src]self.adj_list[src] = nodedef print_adj_list(graph):for i in range(graph.vertices):print(f"Vertex {i}:", end=" ")node = graph.adj_list[i]while node:print(node.value, end=" → ")node = node.nextprint("-")2. 邻接矩阵邻接矩阵是一种使用二维数组来表示图的方法。
对于包含n个顶点的图,邻接矩阵是一个n×n的矩阵,其中每个元素a[i][j]表示顶点i和顶点j之间是否存在边。
洛谷邻接矩阵、邻接表的例题c++
洛谷邻接矩阵、邻接表的例题c++一、概述在学习和理解图的基本概念时,邻接矩阵和邻接表是两种常用的表示方法。
它们可以帮助我们更加直观地理解和分析图的结构和特性。
本文将以洛谷上的一个例题为例,介绍如何使用C++语言结合邻接矩阵和邻接表来解决图相关问题。
二、洛谷例题描述题目描述:给定一个有向图,图中包含n个节点和m条边,每条边连接两个节点。
现在需要求解图中每个节点的入度和出度。
输入格式:第一行包含两个整数n和m,分别表示节点数和边数。
接下来m行,每行包含两个整数a和b,表示图中存在一条边从a指向b。
输出格式:按照节点编号从小到大的顺序,输出每个节点的入度和出度。
三、解题思路1. 使用邻接矩阵表示图的结构;2. 使用邻接表统计每个节点的入度和出度。
四、基于邻接矩阵和邻接表的C++程序实现```cpp#include <iostream>#include <vector>using namespace std;const int MAXN = 1005;int n, m;int g[MAXN][MAXN]; // 邻接矩阵vector<int> inDegree(MAXN, 0); // 入度vector<int> outDegree(MAXN, 0); // 出度int m本人n() {cin >> n >> m;// 初始化邻接矩阵for (int i = 0; i < m; i++) {int a, b;cin >> a >> b;g[a][b] = 1;}// 统计入度和出度for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {if (g[i][j] == 1) { // 有一条边从i指向joutDegree[i]++;inDegree[j]++;}}}// 输出结果for (int i = 1; i <= n; i++) {cout << "节点" << i << "的入度为:" << inDegree[i] << ",出度为:" << outDegree[i] << endl;}return 0;}```五、测试样例输入样例:```5 61 21 32 32 43 44 5```输出样例:```节点1的入度为:0,出度为:2节点2的入度为:1,出度为:2节点3的入度为:2,出度为:2节点4的入度为:2,出度为:1节点5的入度为:1,出度为:0```六、总结通过本文的讲解,我们了解了如何使用C++语言结合邻接矩阵和邻接表来解决有关图的问题。
关联矩阵与邻接矩阵相互转化_概述说明
关联矩阵与邻接矩阵相互转化概述说明1. 引言1.1 概述:在网络和图论领域中, 关联矩阵和邻接矩阵是两个基本且关键的工具。
它们用于描述图结构中的节点之间的连接关系,从而对各种复杂系统进行建模和分析。
关联矩阵是一种表示节点与边之间关联信息的方式,而邻接矩阵则提供了直观且紧凑地表示图的方式。
本文旨在介绍如何相互转化这两种矩阵,并探讨其在实际应用中的意义和重要性。
1.2 文章结构:本文共分为五个主要部分,每个部分都涉及到关联矩阵和邻接矩阵在不同领域中的转化方法及应用案例。
- 第二部分将回顾关联矩阵和邻接矩阵的定义,并介绍它们在图论中的概念及应用。
- 第三部分将探索如何扩展关联矩阵与邻接矩阵之间相互转化的算法,包括稀疏图、加权图和多元图等情况。
- 第四部分将通过几个具体领域中的实际案例,说明关联矩阵和邻接矩阵转化在社交网络分析、工程网络分析和生物信息学领域中的应用。
- 第五部分将总结关联矩阵与邻接矩阵相互转化的重要性,并对未来发展进行展望。
1.3 目的:本文的目的是为读者提供一个全面而清晰的了解关联矩阵和邻接矩阵之间转化方法及其应用的指导。
我们希望通过该文可以增加人们对这两种矩阵的认识,以及它们在各个领域中解决实际问题时的价值。
同时,该文还将讨论现有算法存在的局限性,并探索未来关联矩阵与邻接矩阵相互转化领域可能的发展方向。
2. 关联矩阵与邻接矩阵的概念及应用2.1 关联矩阵的定义关联矩阵是一种描述图结构的数学工具。
对于一个包含n个节点的图,关联矩阵是一个n×m的二维矩阵(其中m是边的数量),并且该矩阵中元素的值表示节点和边之间的关系。
通常,行代表节点,列代表边,而非零元素表示相应节点和边之间存在关联。
2.2 邻接矩阵的定义邻接矩阵也是一种描述图结构的数学工具。
对于一个包含n个节点的图,邻接矩阵是一个n×n的二维方阵,其中每个元素a_ij表示节点i和节点j之间是否存在连接或者边。
当两个节点之间有连边时,邻接矩阵中对应位置上为非零值;反之,在无连边时为0。
图的两种存储方式---邻接矩阵和邻接表
图的两种存储⽅式---邻接矩阵和邻接表图:图是⼀种数据结构,由顶点的有穷⾮空集合和顶点之间边的集合组成,表⽰为G(V,E),V表⽰为顶点的集合,E表⽰为边的集合。
⾸先肯定是要对图进⾏存储,然后进⾏⼀系列的操作,下⾯对图的两种存储⽅式邻接矩阵和邻接表尽⾏介绍。
(⼀)、邻接矩阵存储:⽤两个数组分别进⾏存储数据元素(顶点)的信息和数据元素之间的关系(边或弧)的信息。
存储顶点:⽤⼀个连续的空间存储n个顶点。
存储顶点之间的边:将由n个顶点组成的边⽤⼀个n*n的矩阵来存储,如果两个顶点之间有边,则表⽰为1,否则表⽰为0。
下⾯⽤代码来实现邻接矩阵的存储:#define SIZE 10class Graph{public:Graph(){MaxVertices = SIZE;NumVertices = NumEdges = 0;VerticesList = new char[sizeof(char)*MaxVertices];Edge = new int*[sizeof(int*)*MaxVertices];int i,j;for(i = 0;i<MaxVertices;i++)Edge[i] = new int[sizeof(int)*MaxVertices];for(i = 0;i<MaxVertices;i++){for(j = 0;j<MaxVertices;++j)Edge[i][j] = 0;}}void ShowGraph(){int i,j;cout<<"";for(i = 0;i<NumVertices;i++)cout<<VerticesList[i]<<"";cout<<endl;for(i = 0;i<NumVertices;i++){cout<<VerticesList[i]<<"";for(j = 0;j<NumVertices;j++)cout<<Edge[i][j] <<"";cout<<endl;}cout<<endl;}int GetVertexPos(char v){int i;for(i = 0;i<NumVertices;i++){if(VerticesList[i] == v)return i;}return -1;}~Graph(){Destroy();}void Insert(char v){if(NumVertices < MaxVertices){VerticesList[NumVertices] = v;NumVertices++;}}void InsertEdge(char v1,char v2){int i,j;int p1 = GetVertexPos(v1);int p2 = GetVertexPos(v2);if(p1 == -1 || p2 == -1)return ;Edge[p1][p2] = Edge[p2][p1] = 1;NumEdges++;}void RemoveEdge(char v1,char v2){int p1 = GetVertexPos(v1);int p2 = GetVertexPos(v2);if(p1 == -1 || p2== -1)return;if(Edge[p1][p2] == 0)return;Edge[p1][p2] = Edge[p2][p1] = 0;NumEdges--;}void Destroy(){delete[] VerticesList;VerticesList = NULL;for(int i = 0;i<NumVertices;i++){delete Edge[i];Edge[i] = NULL;}delete[] Edge;Edge = NULL;MaxVertices = NumVertices = 0;}void RemoveVertex(char v){int i,j;int p = GetVertexPos(v);int reNum = 0;if(p == -1)return;for(i = p;i<NumVertices-1;i++){VerticesList[i] = VerticesList[i+1];}for(i = 0;i<NumVertices;i++){if(Edge[p][i] != 0)reNum++;}for(i = p;i<NumVertices-1;i++){for(j = 0;j<NumVertices;j++){Edge[i][j] = Edge[i+1][j];}}for(i = p;i<NumVertices;i++){for(j = 0;j<NumVertices;j++)Edge[j][i] = Edge[j][i+1];}NumVertices--;NumEdges = NumEdges - reNum;}private:int MaxVertices;int NumVertices;int NumEdges;char *VerticesList;int **Edge;};上⾯的类中的数据有定义最⼤的顶点的个数(MaxVertices),当前顶点的个数(NumVertices),当前边的个数(NumEdges),保存顶点的数组,保存边的数组。
数据结构实验 图的邻接表和邻接矩阵操作
p->weight=weight; p->nextarc=G.vertices[vv].firstarc; G.vertices[vv].firstarc=p; strcmp(G.vertices[vv].data,v);
q=(ArcNode *)malloc(sizeof(ArcNode)); q->adjvex=vv; q->weight=weight; q->nextarc=G.vertices[ww].firstarc; G.vertices[ww].firstarc=q; strcmp(G.vertices[ww].data,w);
实验报告 6
课程 数据结构 实验名称 图的建立及遍历
第页
专业
班级_ __ 学号_ ___ 姓名
实验日期: 2010 年 11 月 23 日
评分
一 、实验目的
1.学会用邻接矩阵和邻接表实现图结构和对图的基本操作。 2.掌握对图操作的具体实现; 3. 掌握图的两种遍历算法(深度优先、广度优先); 4、掌握求图的最小生成树和顶点间最短路径的算法;
int adjvex;//该弧指向的顶点的位置 ArcType weight; struct ArcNode *nextarc;//指向下一条弧指针 //InfoType *info;该弧相关信息的指针 }ArcNode; typedef struct VNode { VertexType data;//顶点信息 ArcNode *firstarc;//指向第一条依附该顶点的弧的指针 }VNode,AdjList[MAX_VEX_NUM]; typedef struct { AdjList vertices; int vexnum,arcnum; GraphKind kind; }ALGraph; ALGraph G; struct MiniSpanTree_Flag { VertexType adjvex; ArcType lowcost; }closedge[MAX_VEX_NUM]; typedef bool PathMatrix[MAX_VEX_NUM][MAX_VEX_NUM];
邻接矩阵转换为邻接表
邻接矩阵转换为邻接表1 #include <stdio.h>2 #include <stdlib.h>3#define INFINITY INT_MAX4//定义最⼤定点数5#define MAX_VERTEX_NUM 2067//定义图的类型8 typedef enum GraphKind{9 DG, //DG有向图 ----010 DN, //DN有向⽹ ----111 UDG,//UDG⽆向图----212 UDN //UDN⽆向⽹----313 };1415//=========================----------邻接矩阵的定义--------=================================1617//adj的int,是顶点关系类型,对于⽆权图⽤1或者0,表⽰相邻否;对于有权图,为权值类型。
18 typedef struct{19int adj;20int * info; //info 该弧相关的信息指针21 }AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //邻接矩阵结构2223 typedef struct Graph{24char vex[MAX_VERTEX_NUM] ;//顶点向量,存储顶点名称25 AdjMatrix arcs; //邻接矩阵26int vexnum,arcnum; //图当前定点数和弧度数27//GraphKind kind; //图的种类标志28 }MGraph;2930//=========================----------邻接矩阵结束定义--------================================= 3132//=========================----------邻接表的定义--------===================================== 3334//表⽰图的节点35 typedef struct ArcNode{36int adjvex;//定义节点在图中的位置37 ArcNode *nextarc;//指向下⼀个节点38int *info; //互相关的信息指针39 }ArcNode;//定义图的节点4041//表⽰图的表头42 typedef struct VNode{43char vexdata;44 ArcNode *firstarc;45 } AdjList[MAX_VERTEX_NUM];//定义图的表头4647 typedef struct48 {49 AdjList vertices;//邻接表50int vexnum,arcnum;//顶点个数,弧的个数51 } ALGraph;5253//=========================----------邻接表结束定义-------===================================== 5455int Locate_Vex(MGraph * G, char ch)56 {57for (int i = 0; i < G->vexnum; i++)58 {59if(G->vex[i]==ch) return i;60 }61return -1;62 }6364 MGraph * Create_MGaph()65 {66 MGraph *mgraph;67char start,end;//start 表⽰起点, end 表⽰终点68int vexnum,arcnum;69int i,j;70 mgraph=(MGraph *)malloc(sizeof(MGraph)); //分配空间71if (!mgraph)72 {73 printf("分配失败");74 }75 printf("请输⼊图的顶点数和边数:");76 scanf("%d%d",&vexnum,&arcnum);77 mgraph->vexnum=vexnum;78 mgraph->arcnum=arcnum;7980 printf("请输⼊顶点的名称:");81for (i = 0; i < vexnum; i++) scanf("%s",&(mgraph->vex[i]));//存储顶点的值 82//初始化矩阵83for (i = 0; i < vexnum; i++)84for (j = 0; j< vexnum; j++)85 {86 mgraph->arcs[i][j].adj = 0 ;87 mgraph->arcs[i][j].info = NULL;88 }8990 printf("-------------请输⼊弧的信息------------\n");91for(int k=0; k<arcnum; k++)92 {93 printf("请输⼊第%d条弧起始和终点:",(k+1));94 fflush(stdin);95 scanf("%c %c",&start,&end);96 i=Locate_Vex(mgraph,start);97 j=Locate_Vex(mgraph,end);98 mgraph->arcs[i][j].adj = 1;99 mgraph->arcs[j][i].adj = 1;100 }101102return mgraph;103 }104105 ALGraph * MGraph_Change_ALGraph(MGraph * mgraph)106 {107 ALGraph *algraph;108int vexnum;109 algraph = (ALGraph *)malloc(sizeof (ALGraph)); //分配空间110 algraph->vexnum = mgraph->vexnum;111 algraph->arcnum = mgraph->arcnum;112 vexnum = algraph->vexnum;113for(int i=0; i<mgraph->vexnum; i++)//完成初始化114 {115 algraph->vertices[i].vexdata = mgraph->vex[i];116 algraph->vertices[i].firstarc = NULL;117 }118119for(int i=0; i< vexnum ; i++)120 {121for(int j=0; j< vexnum ; j++)122 {123if(mgraph->arcs[i][j].adj == 1)124 {125 ArcNode * arcnode = (ArcNode *)malloc(sizeof (ArcNode));126 arcnode->adjvex = j;127 arcnode->nextarc = algraph->vertices[i].firstarc;128 algraph->vertices[i].firstarc = arcnode;129 }130 }131 }132133return algraph;134135 }136137void PrintMGraph(MGraph * mgraph)138 {139for(int i=0; i<mgraph->vexnum ; i++)140 {141for(int j=0; j<mgraph->vexnum ; j++)142 {143 printf("%-5d",mgraph->arcs[i][j].adj);144 }145 printf("\n");146 }147 }148149void PrintALGraph(ALGraph * algraph)150 {151for(int i=0; i<algraph->vexnum; i++)152 {153 VNode *p;154 ArcNode *q;155 p = &(algraph->vertices[i]);156 printf("%c",p->vexdata);157 q = p ->firstarc;158while (q)159 {160 printf("-->");161 printf("%c",algraph->vertices[q->adjvex].vexdata);162 q= q->nextarc;163 }164 printf("\n");165 }166 }167168int main(void)169 {170 MGraph *mgraph;171 ALGraph *algraph;172 mgraph = Create_MGaph();173 printf("\n打印邻接矩阵如下:\n");174 PrintMGraph(mgraph);175176 algraph = MGraph_Change_ALGraph(mgraph); 177178 printf("\n打印转换成邻接表如下:\n");179 PrintALGraph(algraph);180 system("pause");181return0;182 }183/*184Output:185请输⼊图的顶点数和边数:5 6186请输⼊顶点的名称:A B C D E187-------------请输⼊弧的信息------------188请输⼊第1条弧起始和终点:A B189请输⼊第2条弧起始和终点:A D190请输⼊第3条弧起始和终点:B C191请输⼊第4条弧起始和终点:B E192请输⼊第5条弧起始和终点:C D193请输⼊第6条弧起始和终点:C E194打印邻接矩阵如下:1950 1 0 1 01961 0 1 0 11970 1 0 1 11981 0 1 0 01990 1 1 0 0200201打印转换成邻接表如下:202A-->D-->B203B-->E-->C-->A204C-->E-->D-->B205D-->C-->A206E-->C-->B207*/。
两个邻接矩阵融合方法
邻接矩阵融合方法是一种将两个或多个邻接矩阵合并为一个的方法,通常用于社交网络分析、图神经网络等领域。
以下是两种常见的邻接矩阵融合方法:
1. 简单平均法(Simple Averaging):
简单平均法是将两个邻接矩阵对应位置的元素相加,然后除以2得到融合后的邻接矩阵。
具体步骤如下:
a. 初始化一个新的空邻接矩阵M,其大小与输入的邻接矩阵相同。
b. 遍历输入的邻接矩阵A和B,对于每个位置(i, j),计算M[i][j] = (A[i][j] + B[i][j]) / 2。
c. 返回融合后的邻接矩阵M。
2. 带权重的平均法(Weighted Averaging):
带权重的平均法是在简单平均法的基础上,为每个元素分配一个权重,然后将加权后的元素相加得到融合后的邻接矩阵。
具体步骤如下:
a. 初始化一个新的空邻接矩阵M,其大小与输入的邻接矩阵相同。
b. 遍历输入的邻接矩阵A和B,对于每个位置(i, j),计算权重w = w_A * A[i][j] + w_B * B[i][j],其中w_A和w_B是预先设定的权重值。
c. 计算M[i][j] = w。
d. 返回融合后的邻接矩阵M。
这两种方法都可以实现邻接矩阵的融合,但简单平均法不考虑元素之间的差异,而带权重的平均法则可以根据实际需求为不同元素分配不同的权重。
在实际应用中,可以根据具体问题选择合适的融合方法。
邻接矩阵求可达矩阵
邻接矩阵求可达矩阵孙悟空一、引言邻接矩阵是图论中常见的图表示方法之一。
可达矩阵则是在邻接矩阵的基础上进行扩展,用于表示图中任意两个顶点之间的可达性。
本文将深入探讨邻接矩阵求可达矩阵的算法原理与实现方法,以及应用场景和优缺点。
二、邻接矩阵邻接矩阵是一个二维矩阵,用于表示图中各个顶点之间的连接关系。
设图G有n个顶点,则邻接矩阵A的大小为n × n。
其中,A[i][j]的值代表顶点i和j之间的连接关系,通常为0或1。
当A[i][j]为1时,表示顶点i和j之间存在一条边;当A[i][j]为0时,表示顶点i和j之间不存在边。
2.1 邻接矩阵的表示方法邻接矩阵可以用二维数组来表示。
如果图中的顶点用数字0到n-1表示,那么可以用一个二维数组G[][]来表示邻接矩阵,其中n为图的顶点个数。
2.2 邻接矩阵的性质邻接矩阵具有以下性质: 1. 对于无向图,邻接矩阵是对称的,即A[i][j] =A[j][i]。
2. 对于有向图,邻接矩阵不一定是对称的,A[i][j]表示从顶点i到顶点j的边的存在性。
三、可达矩阵可达矩阵是在邻接矩阵的基础上进行扩展,用于表示任意两个顶点之间的可达性。
可达矩阵R的大小和邻接矩阵A相同,即为n × n。
R[i][j]的值为1时,表示顶点i能够通过一条或多条路径到达顶点j;R[i][j]的值为0时,表示顶点i无法到达顶点j。
3.1 可达矩阵的计算方法可达矩阵的计算通常采用传递闭包的方法。
传递闭包表示一个图中顶点对之间的传递关系。
如果存在从顶点i到顶点j的路径,那么传递闭包的结果中R[i][j]的值为1。
可达矩阵的计算方法如下: 1. 初始化可达矩阵R为邻接矩阵A。
2. 对于每一对顶点i和j,检查是否存在顶点k,使得R[i][k]和R[k][j]都为1。
如果存在,则令R[i][j] = 1。
3. 重复步骤2,直到R不再变化为止。
3.2 可达矩阵的应用场景可达矩阵在许多实际问题中都有广泛的应用,例如: 1. 社交网络中的好友关系分析:可达矩阵可以用于判断两个人之间是否存在友谊链,即是否通过一系列人的关系形成连接。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
运行结果是:
请输入节点数和弧数:3 3
第1 个节点信息:5
第2 个节点信息:6
第3 个节点信息:7
第1 条弧的弧尾和弧头的位置:1 2 第2 条弧的弧尾和弧头的位置:2 3 第3 条弧的弧尾和弧头的位置:1 3 图的邻接表表示为:
[1,5]-->[3,7]-->[2,6]-->^
[2,6]-->[3,7]-->[1,5]-->^
[3,7]-->[1,5]-->[2,6]-->^
交换后是::
图的邻接矩阵表示为:
0 1 1
1 0 1
1 1 0
请按任意键继续. . .
代码是:
#include<stdio.h>
#include<stdlib.h>
#define MAXV 100
typedef struct
{
int no;
int info;
}vertextype;
typedef struct
{
int num;
int edges[MAXV][MAXV];
// vertextype vexs[MAXV];
}mgraph;
struct arcnode
{
int adjvex;
int info;
struct arcnode *nextarc;
};
struct vexnode
{
int data;
struct arcnode *firstarc;
};
struct graph
{
int vexnum,arcnum;
vexnode vexpex[100];
};
struct graph *creatgraph()
{
int i,s,d;
struct graph *g;
struct arcnode *p,*q;
g = (struct graph *)malloc(sizeof(struct graph));
printf("请输入节点数和弧数:");
scanf("%d%d", &g->vexnum, &g->arcnum);
for(i=1; i<=g->vexnum; i++)
{
printf("第%d 个节点信息:",i);
scanf("%d", &g->vexpex[i].data);
g->vexpex[i].firstarc = NULL;
}
for(i=1; i<=g->arcnum; i++)
{
p = (struct arcnode *)malloc(sizeof(struct arcnode));
q = (struct arcnode *)malloc(sizeof(struct arcnode));
printf("第%d 条弧的弧尾和弧头的位置:",i);
scanf("%d%d",&s,&d);
p->adjvex = d;
p->info = g->vexpex[d].data;
p->nextarc = g->vexpex[s].firstarc;
g->vexpex[s].firstarc = p;
q->adjvex = s;
q->info = g->vexpex[s].data;
q->nextarc = g->vexpex[d].firstarc;
g->vexpex[d].firstarc = q;
}
return g; //return graph!
}
void changeto(graph *G, mgraph &g)
{
int i,j;
arcnode *m;
g.num = G->vexnum;
for(i = 1; i<=G->vexnum; i++)
for(j = 1; j<=G->vexnum; j++)
g.edges[i][j] = 0;
for(i = 1; i<=G->vexnum; i++)
{
m = G->vexpex[i].firstarc;
while(m)
{
g.edges[i][m->adjvex] = 1;
m = m->nextarc;
}
}
}
void printtu(struct graph *g,int n)
{
int i;
arcnode *p;
printf("图的邻接表表示为:\n");
for(i=1; i<=n; i++)
{
printf(" [%d,%d]-->", i, g->vexpex[i].data);
p = g->vexpex[i].firstarc;
while(p != NULL)
{
printf("[%d,%d]-->", p->adjvex, p->info);
p = p->nextarc;
}
printf("^\n");
}
}
void printftu2(mgraph g)
{
int i,j;
printf("图的邻接矩阵表示为:\n");
for(i = 1; i<=g.num; i++)
{
for(j = 1;j <= g.num; j++)
printf("%d ",g.edges[i][j]);
printf("\n");
}
}
void main()
{
graph *G;
mgraph g;
G = creatgraph();
printtu(G,G->vexnum);
printf("交换后是::\n");
changeto(G, g);
printftu2(g);
system("PAUSE");
}。