图的邻接矩阵和邻接表相互转换
- 格式:doc
- 大小:42.00 KB
- 文档页数:5
数据结构简答题和论述题1、试描述数据结构和抽象数据类型的概念与程序设计语⾔中数据类型概念的区别。
【解答】数据结构是指相互之间存在⼀定关系的数据元素的集合。
⽽抽象数据类型是指⼀个数据结构以及定义在该结构上的⼀组操作。
程序设计语⾔中的数据类型是⼀个值的集合和定义在这个值集上⼀组操作的总称。
抽象数据类型可以看成是对数据类型的⼀种抽象。
串:是零个或多个字符组成的有限序列。
串是⼀种特殊的线性表,它的每个结点仅由⼀个字符组成。
空串 :长度为零的串,它不包含任何字符。
空⽩串 :仅由⼀个或多个空格组成的串⼦串 :串中任意个连续字符组成的⼦序列称为该串的⼦串。
串变量和串常量通常在程序中使⽤的串可分为:串变量和串常量。
(1)串变量 :串变量和其它类型的变量⼀样,其取值是可以改变的。
(2)串常量 :串常量和整常数、实常数⼀样,在程序中只能被引⽤但不能改变其值。
即只能读不能写。
(1)树形图表⽰: 树形图表⽰是树结构的主要表⽰⽅法。
(2)树的其他表⽰法① 嵌套集合表⽰法:是⽤集合的包含关系来描述树结构。
② 凹⼊表表⽰法:类似于书的⽬录③ ⼴义表表⽰法:⽤⼴义表的形式表⽰的。
上图 (a)树的⼴义表表⽰法如下:(A(B(E,F(I,J)), C,D(G,H)))1.中序遍历的递归算法定义:若⼆叉树⾮空,则依次执⾏如下操作:(1)遍历左⼦树; (2)访问根结点; (3)遍历右⼦树。
2.先序遍历的递归算法定义:若⼆叉树⾮空,则依次执⾏如下操作:(1) 访问根结点; (2) 遍历左⼦树; (3) 遍历右⼦树。
3.后序遍历得递归算法定义:若⼆叉树⾮空,则依次执⾏如下操作:(1)遍历左⼦树; (2)遍历右⼦树; (3)访问根结点。
2、链表具有的特点是B 插⼊、删除不需要移动元素C 不必事先估计存储空间D 所需空间与线性表长度成正⽐顺序队列(1)队列的顺序存储结构称为顺序队列,顺序队列实际上是运算受限的顺序表。
(2) 顺序队列的表⽰①和顺序表⼀样顺序队列⽤⼀个向量空间存放当前队列中的元素。
邻接矩阵转换成邻接表算法邻接矩阵是一种常用的图的表示方法,它通过一个二维数组来表示图中各个节点之间的连接关系。
而邻接表则是另一种常见的图的表示方法,它通过链表的形式来表示图中各个节点之间的连接关系。
本文将介绍如何将邻接矩阵转换成邻接表的算法。
邻接矩阵是一个n*n的二维数组,其中n表示图中节点的个数。
邻接矩阵中的元素a[i][j]表示节点i和节点j之间是否存在连接,如果存在连接则为1,否则为0。
邻接表则是一个长度为n的链表数组,每个链表表示一个节点的邻接节点。
邻接矩阵转换成邻接表的算法可以分为以下几个步骤:1. 创建一个长度为n的链表数组,用于存储邻接表。
2. 遍历邻接矩阵的每个元素a[i][j],如果a[i][j]为1,则表示节点i 和节点j之间存在连接。
3. 在链表数组中的第i个链表中插入节点j,表示节点i和节点j之间存在连接。
4. 重复步骤2和步骤3,直到遍历完整个邻接矩阵。
下面是一个具体的示例,以便更好地理解邻接矩阵转换成邻接表的算法。
假设有一个邻接矩阵如下所示:```1 0 0 11 0 0 10 1 1 0```首先,创建一个长度为4的链表数组,用于存储邻接表。
```[][][][]```然后,遍历邻接矩阵的每个元素,如果元素为1,则将对应的节点插入到链表数组中。
遍历第一行,第一个元素为0,不需要插入节点;第二个元素为1,需要插入节点1;第三个元素为1,需要插入节点2;第四个元素为0,不需要插入节点。
此时链表数组的状态如下:```[][][]```接着,遍历第二行,第一个元素为1,需要插入节点0;第二个元素为0,不需要插入节点;第三个元素为0,不需要插入节点;第四个元素为1,需要插入节点3。
此时链表数组的状态如下:```[0][1, 2][3][]```继续遍历第三行和第四行,最终得到的邻接表如下所示:```[0][1, 2][3][1, 2]```通过以上步骤,我们成功地将邻接矩阵转换成了邻接表。
重庆邮电大学2022年[数据结构]考研真题一、选择题1.对于双向循环链表,每个结点有两个指针域next和prior,分别指向前驱和后继。
在p指针所指向的结点之后插入s指针所指结点的操作应为()。
A.p->next=s;s->prior=p;p->next->prior=s;s->next=p->next;B.p->next=s;p->next->prior=s;s->prior=p;s->next=p->next;C.s->prior=p;s->next=p->next;p->next=s;p->next->prior=s;D.s->prior=p;s->next=p->next;p->next->prior=s;p->next=s; 2.由abc,3个结点可以构造出多少种不同的二叉树?()A.2B.3C.4D.53. 设有数组A[i,j],数组的每个元素长度为3字节,i的值为1到8,j的值为1到10,数组从内存首地址BA开始顺序存放,当用以列为主存放时,元素A[5,8]的存储首地址为()。
A.BA+141B.BA+180C.BA+222D.BA+2254. 一个栈的输入序列为123,则下列序列中不可能是栈的输出序列的是()。
A.231B.321C.312D.1235. 下述编码中哪一个不是前缀码()。
A.(00,01,10,11)B.(0,1,00,11)C.(0,10,110,111)D.(1,01,000,001)6. 当一棵有n个结点的二叉树按层次从上到下,同层次从左到右将数据存放在一维数组A[l..n]中时,数组中第i个结点的左孩子为()。
A.A[2i](2i=<n)B.A[2i+1](2i+1=<n)C.A[i/2]D.无法确定7. 假设一个有n个顶点和e条弧的有向图用邻接表表示,则删除与某个顶点vi相关的所有弧的时间复杂度是()。
实验6.1实现图的存储和遍历一,实验目的掌握图的邻接矩阵和邻接表存储以及图的邻接矩阵存储的递归遍历。
二,实验内容6.1实现图的邻接矩阵和邻接表存储编写一个程序,实现图的相关运算,并在此基础上设计一个主程序,完成如下功能:(1)建立如教材图7.9所示的有向图G的邻接矩阵,并输出。
(2)由有向图G的邻接矩阵产生邻接表,并输出。
(3)再由(2)的邻接表产生对应的邻接矩阵,并输出。
6.2 实现图的遍历算法(4)在图G的邻接矩阵存储表示基础上,输出从顶点V1开始的深度优先遍历序列(递归算法)。
(5)利用非递归算法重解任务(4)。
(6)在图G的邻接表存储表示基础上,输出从顶点V1开始的广度优先遍历序列。
三,源代码及结果截图#include<stdio.h>#include<stdlib.h>#include<string.h>#include<iostream.h>#include<malloc.h>#define MAX_VERTEX_NUM 20typedef char VRType;typedef int InfoType; // 存放网的权值typedef char VertexType; // 字符串类型typedef enum{DG,DN,AG,AN}GraphKind; // {有向图,有向网,无向图,无向网}/*建立有向图的邻接矩阵*/typedef struct ArcCell{VRType adj;//VRType是顶点关系类型,对无权图用1或0表示是否相邻;对带权图则为权值类型InfoType *info; //该弧相关信息的指针(可无)}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];typedef struct{VertexType vexs[MAX_VERTEX_NUM];//顶点向量AdjMatrix arcs;//邻接矩阵int vexnum,arcnum;;//图的当前顶点数和弧数GraphKind kind;//图的种类标志}MGraph;/* 顶点在顶点向量中的定位*/int LocateVex(MGraph &M,VRType v1){int i;for(i=0;i<M.vexnum;i++)if(v1==M.vexs[i])return i;return -1;}void CreateGraph(MGraph &M)//建立有向图的邻接矩阵{int i,j,k,w;VRType v1,v2;M.kind=DN;printf("构造有向网:\n");printf("\n输入图的顶点数和边数(以空格作为间隔):");scanf("%d%d",&M.vexnum,&M.arcnum);printf("输入%d个顶点的值(字符):",M.vexnum);getchar();for(i=0;i<M.vexnum;i++) //输入顶点向量{scanf("%c",&M.vexs[i]);}printf("建立邻接矩阵:\n");for(i=0;i<M.vexnum;i++)for(j=0;j<M.vexnum;j++){M.arcs[i][j].adj=0;M.arcs[i][j].info=NULL;}printf("请顺序输入每条弧(边)的权值、弧尾和弧头(以空格作为间隔):\n");for(k=0;k<M.arcnum;++k)// 构造表结点链表{cin>>w>>v1>>v2;i=LocateVex(M,v1);j=LocateVex(M,v2);M.arcs[i][j].adj=w;}}//按邻接矩阵方式输出有向图void PrintGraph(MGraph M){int i,j;printf("\n输出邻接矩阵:\n");for(i=0; i<M.vexnum; i++){printf("%10c",M.vexs[i]);for(j=0; j<M.vexnum; j++)printf("%2d",M.arcs[i][j].adj);printf("\n");}}// 图的邻接表存储表示typedef struct ArcNode{int adjvex; // 该弧所指向的顶点的位置struct ArcNode *nextarc; // 指向下一条弧的指针InfoType *info; // 网的权值指针)}ArcNode; // 表结点typedef struct VNode{VertexType data; // 顶点信息ArcNode *firstarc; // 第一个表结点的地址,指向第一条依附该顶点的弧的指针}VNode,AdjList[MAX_VERTEX_NUM];// 头结点typedef struct{AdjList vertices;int vexnum,arcnum; // 图的当前顶点数和弧数int kind; // 图的种类标志}ALGraph;void CreateMGtoDN(ALGraph &G,MGraph &M){//由有向图M的邻接矩阵产生邻接表int i,j;ArcNode *p;G.kind=M.kind;G.vexnum=M.vexnum;G.arcnum=M.arcnum;for(i=0;i<G.vexnum;++i){//构造表头向量G.vertices[i].data=M.vexs[i];G.vertices[i].firstarc=NULL;//初始化指针}for(i=0;i<G.vexnum;++i)for(j=0;j<G.vexnum;++j)if(M.arcs[i][j].adj){p=(ArcNode*)malloc(sizeof(ArcNode));p->adjvex=j;p->nextarc=G.vertices[i].firstarc;p->info=M.arcs[i][j].info;G.vertices[i].firstarc=p;}}void CreateDNtoMG(MGraph &M,ALGraph &G){ //由邻接表产生对应的邻接矩阵int i,j;ArcNode *p;M.kind=GraphKind(G.kind);M.vexnum=G.vexnum;M.arcnum=G.arcnum;for(i=0;i<M.vexnum;++i)M.vexs[i]=G.vertices[i].data;for(i=0;i<M.vexnum;++i){p=G.vertices[i].firstarc;while(p){M.arcs[i][p->adjvex].adj=1;p=p->nextarc;}//whilefor(j=0;j<M.vexnum;++j)if(M.arcs[i][j].adj!=1)M.arcs[i][j].adj=0;}//for}//输出邻接表void PrintDN(ALGraph G){int i;ArcNode *p;printf("\n输出邻接表:\n");printf("顶点:\n");for(i=0;i<G.vexnum;++i)printf("%2c",G.vertices[i].data);printf("\n弧:\n");for(i=0;i<G.vexnum;++i){p=G.vertices[i].firstarc;while(p){printf("%c→%c(%d)\t",G.vertices[i].data,G.vertices[p->adjvex].data,p->info);p=p->nextarc;}printf("\n");}//for}int visited[MAX_VERTEX_NUM]; // 访问标志数组(全局量)void(*VisitFunc)(char* v); // 函数变量(全局量)// 从第v个顶点出发递归地深度优先遍历图G。
《数据结构》综合复习资料一、填空题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,除此之外没有其他更快的办法。
数据结构实验报告实验名称:结构图提交文档学生姓名:提交文档学生学号:同组成员名单:指导教师姓名:结构图一、实验目的和要求1、设计目的1.掌握图的相关概念,包括图,有向图,无向图,完全图,子图,连通图,度,入度,出度,简单回路和环等定义。
2.重点掌握图的各种存储结构,包括邻接矩阵和邻接表等。
3.重点掌握图的基本运算,包括创建图,输出图,深度优先遍历,广度优先遍历等。
4.掌握图的其他运算,包括最小生成树,最短路径,拓扑排序和关键路径等算法。
5. 灵活运用图这种数据结构解决一些综合应用问题。
2、设计内容和要求1、编写一个程序algo8-1.cpp,实现不带权图和带权图的邻接矩阵与邻接表的相互转换算法、输出邻接矩阵与邻接表的算法,并在此基础上设计一个程序exp8-1.cpp实现如下功能:①建立如图1所示的有向图G的邻接矩阵,并输出;②由有向图G的邻接矩阵产生邻接表,并输出;③再由②的邻接表产生对应的邻接矩阵,并输出。
图12、编写一个程序algo8-2.cpp,实现图的遍历运算,并在此基础上设计一个程序exp8-2.cpp完成如下功能:①输出图1所示的有向图G从顶点0开始的深度优先遍历序列(递归算法);②输出图1所示的有向图G从顶点0开始的深度优先遍历序列(非递归算法);③输出图1所示的有向图G从顶点0开始的广度优先遍历序列。
3、设计一个程序exp8-3.cpp,采用邻接表存储图,并输出图8.1(a)中从指定顶点1出发的所有深度优先遍历序列。
二、运行环境(软、硬件环境)软件环境:Visual C++6.0运行平台: Win32硬件:普通个人pc机三、实验过程描述文件graph.h中定义了图的邻接矩阵表示类型和邻接表表示类型,该头文件在以下三个实验中都会使用到。
其代码如下:#ifndef GRAPH_H_INCLUDED#define GRAPH_H_INCLUDEDtypedef int InfoType;#define MAXV 100 //最大顶点个数#define INF 32767 //INF表示无限大//以下定义邻接矩阵类型typedef struct{int no;InfoType info;}VertexType;typedef struct{int edges[MAXV][MAXV];int n,e;VertexType vexs[MAXV];}MGraph;//以下定义邻接表类型typedef struct ANode{int adjvex;struct ANode* nextarc;InfoType info;}ArcNode;typedef int Vertex;typedef struct VNode{Vertex data;ArcNode* firstarc;}VNode;typedef VNode AdjList[MAXV];typedef struct{AdjList adjlist;int n,e;}ALGraph;#endif // GRAPH_H_INCLUDED实验①源程序。
图1. 填空题⑴设无向图G中顶点数为n,则图G至少有()条边,至多有()条边;若G为有向图,则至少有()条边,至多有()条边。
【解答】0,n(n-1)/2,0,n(n-1)【分析】图的顶点集合是有穷非空的,而边集可以是空集;边数达到最多的图称为完全图,在完全图中,任意两个顶点之间都存在边。
⑵任何连通图的连通分量只有一个,即是()。
【解答】其自身⑶图的存储结构主要有两种,分别是()和()。
【解答】邻接矩阵,邻接表【分析】这是最常用的两种存储结构,此外,还有十字链表、邻接多重表、边集数组等。
⑷已知无向图G的顶点数为n,边数为e,其邻接表表示的空间复杂度为()。
【解答】O(n+e)【分析】在无向图的邻接表中,顶点表有n个结点,边表有2e个结点,共有n+2e个结点,其空间复杂度为O(n+2e)=O(n+e)。
⑸已知一个有向图的邻接矩阵表示,计算第j个顶点的入度的方法是()。
【解答】求第j列的所有元素之和⑹有向图G用邻接矩阵A[n][n]存储,其第i行的所有元素之和等于顶点i的()。
【解答】出度⑺图的深度优先遍历类似于树的()遍历,它所用到的数据结构是();图的广度优先遍历类似于树的()遍历,它所用到的数据结构是()。
【解答】前序,栈,层序,队列⑻对于含有n个顶点e条边的连通图,利用Prim算法求最小生成树的时间复杂度为(),利用Kruskal 算法求最小生成树的时间复杂度为()。
【解答】O(n2),O(elog2e)【分析】Prim算法采用邻接矩阵做存储结构,适合于求稠密图的最小生成树;Kruskal算法采用边集数组做存储结构,适合于求稀疏图的最小生成树。
⑼如果一个有向图不存在(),则该图的全部顶点可以排列成一个拓扑序列。
【解答】回路⑽在一个有向图中,若存在弧、、,则在其拓扑序列中,顶点vi, vj, vk的相对次序为()。
【解答】vi, vj, vk【分析】对由顶点vi, vj, vk组成的图进行拓扑排序。
邻接矩阵和邻接表是图论中用于表示图结构的两种常见方式,而深度遍历和广度遍历则是图论中常用的两种图遍历算法。
本文将从简介、原理和应用三个方面探讨这四个主题。
一、邻接矩阵和邻接表1.邻接矩阵邻接矩阵是一种使用二维数组来表示图中顶点之间关系的方法。
如果图中有n个顶点,那么对应的邻接矩阵就是一个n*n的矩阵,其中元素a[i][j]表示顶点i和顶点j之间是否有边,通常用0和1表示。
邻接矩阵适用于稠密图,其存储结构简单,可以直观地展示图的结构,但对于稀疏图来说可能会造成存储空间的浪费。
2.邻接表邻接表是一种使用链表来表示图中顶点之间关系的方法。
对于图中的每一个顶点,都维护一个相邻顶点的列表,图中所有顶点的列表再组合成一个链表,用于表示整个图的结构。
邻接表适用于稀疏图,其存储结构灵活,可以有效地节省存储空间,但查找任意两个顶点之间的关系可能会比较耗时。
二、深度遍历和广度遍历原理1.深度遍历深度遍历是一种用于遍历或搜索图中节点的算法,其原理是从图的某一顶点出发,沿着一条路径不断向下遍历直到末端,然后回溯到上一个节点继续遍历。
深度遍历使用栈来实现,可以通过递归或迭代来进行。
2.广度遍历广度遍历是一种用于遍历或搜索图中节点的算法,其原理是从图的某一顶点出发,依次访问其所有相邻节点,然后再依次访问这些相邻节点的相邻节点,以此类推。
广度遍历使用队列来实现。
三、深度遍历和广度遍历的应用1.深度遍历的应用深度遍历常用于求解图的连通分量、拓扑排序、解决迷宫问题等。
在连通分量中,深度遍历可以帮助我们找到图中的所有连通分量,并对其进行标记,用于进一步的算法运算。
在拓扑排序中,深度遍历可以帮助我们找到一个合理的顺序,用以处理依赖关系问题。
在解决迷宫问题时,深度遍历可以帮助我们找到一条从起点到终点的路径。
2.广度遍历的应用广度遍历常用于求解最短路径、解决迷宫问题等。
在求解最短路径中,广度遍历可以帮助我们找到起点到终点的最短路径,从而解决了许多实际问题。
第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.采用邻接表存储的图的广度优先遍历算法类似于二叉树的______算法。
图的邻接矩阵和邻接表相互转换图的邻接矩阵存储方法具有如下几个特征: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++){。