数据结构图的存储结构及
数据结构的逻辑结构、存储结构及数据运算的含义及其相互关系
2007 C C C 语言的特点,简单的C 程序介绍,C 程序的上机步骤。
1 、算法的概念2、简单的算法举例3、算法的特性4、算法的表示(自然语言、流程图、N-S 图表示) 1 、 C 的数据类型、常量与变星、整型数据、实型数据、字符型数据、字符串常量。
2、 C 的运算符运算意义、优先级、结合方向。
3、算术运算符和算术表达式,各类数值型数据间的混合运算。
4、赋值运算符和赋值表达式。
5、逗号运算符和逗号表达式。
1 、程序的三种基本结构。
2、数据输入输出的概念及在C 语言中的实现。
字符数据的输入输出,格式输入与输出。
1 、关系运算符及其优先级,关系运算和关系表达式。
2、逻辑运算符及其优先级,逻辑运算符和逻辑表达式。
3、if语句。
if语句的三种形式,if语句的嵌套,条件运算符。
4、switch 语句. 1 、while 语句。
2、do/while 语句。
3、for 语句。
4、循环的嵌套。
5、break 语句和continue 语句。
1 、一维数组的定义和引用。
2、二维数组的定义和引用。
3、字符数组。
4、字符串与字符数组。
5、字符数组的输入输出。
6、字符串处理函数1 、函数的定义。
2、函数参数和函数的值,形式参数和实际参数。
3、函数的返回值。
4、函数调用的方式,函数的声明和函数原型。
5、函数的嵌套调用。
6、函数的递归调用。
7、数组作为函数参数。
8、局部变量、全局变量的作用域。
9、变量的存储类别,自动变星,静态变量。
1 、带参数的宏定义。
2、“文件包含”处理。
1 、地址和指针的概念。
2、变量的指针和指向变量的指针变量。
3、指针变量的定义和引用。
4、指针变量作为函数参数。
5、数组的指针和指向数组的指针变量。
6、指向数组元素的指针。
7、通过指针引用数组元素。
8、数组名作函数参数。
9、二维数组与指针。
1 0、指向字符串的指针变星。
字符串的指针表示形式,字符串指针作为函数参数。
11 、字符指针变量和字符数组的异同。
数据结构-chap7 (1)图的存储结构
V2
V4 G2图示
无向图:在图G中,若所有边是无向边,则称G为无向图。
有向图:在图G中,若所有边是有向边,则称G为有向图。
二、图的基本术语
有向完全图: n个顶点的有向图最大边数是n(n-1) 无向完全图: n个顶点的无向图最大边数是n(n-1)/2 1、邻接点及关联边
主要内容
知识点
– – – – 1.图的定义,概念、术语及基本操作。 2.图的存储结构,特别是邻接矩阵和邻接表。 3.图的深度优先遍历和宽度优先遍历。 4.图的应用(连通分量,最小生成树,拓扑排序,关键路经,最短 路经)。 1.基本概念中,完全图、连通分量、生成树和邻接点是重点。 2.建立图的各种存储结构的算法。 3.图的遍历算法及其应用。 4.通过遍历求出连通分量的个数,深(宽)度优先生成树。 5.最小生成树的生成过程。 6.拓扑排序的求法。关键路经的求法。 7.最短路径的手工模拟。
自测题 2
设无向图的顶点个数为n,则该图最多有( )条边。 A.n-1
B.n(n-1)/2
C.n(n+1)/2 D.0 E.N2 【清华大学1998一.5(分)】
自测题 3
一个有n个结点的图,最少有( )个连通分量,最多有( )个 连通分量。
A. 0
B.1 C.n-1 D.n 【北京邮电大学 2000 二.5 (20/8分)】
0
V1 e1 V3 V4 V5 V2 1 0 1 0 1
否则
0 1 0 1 1 1 0 1 0 0 0 1 1 0 0 V1 V2 0 1 1 0 0 0 0 0 0 1 0 0 0 0 1 0
数据结构-实验6图的存储和遍历
实验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。
北京理工大学数据结构图课件
B C D
第 5 页
E
7.1 图的定义与术语
3、无向图——无向图G是由两个集合V(G)和 E(G)组成的。 其中:V(G)是顶点的非空有限集。 E(G)是边的有限集合,边是顶点的 无序对,记为 (v,w) 或 (w,v),并且 (v,w)=(w,v)。
第 6 页
7.1 图的定义与术语
例如:
G2 = <V2,E2> V2 = { v0 ,v1,v2,v3,v4 } E2 = { (v0,v1), (v0,v3), (v1,v2), (v1,v4), (v2,v3), (v2,v4) }
V5
第 15 页
7.1 图的定义与术语
非 连 通 图
V0
V1
V2
V3
V0
V1 V3
V2
强连通分量
第 16 页
7.1 图的定义与术语
7、生成树
包含无向图 G 所有顶点的极小连通子图称为G生 成树。 极小连通子图意思是:该子图是G的连通子图, 在该子图中删除任何一条边,子图不再连通。
V0 V2 V3 V4 V3 连通图G1 V1 V0 V1 连通 所有顶点 V4 无回路
第 22 页
7.2 图的存储结构 3、有向图的逆邻接表 顶点:用一维数组存储(按编号顺序) 以同一顶点为终点的弧:用线性链表存储。
vexdata V0 V1 0 1 v0 v1 v2
v3
firstarc 3 0 0 ^ ^
V2
V3
2 3
^
^
2
章 类似于有向图的邻接表,所不同的是: 以同一顶点为终点弧:用线性链表存储
Boolean visited[MAX]; // 访问标志数组
数据结构:第7章 图
6.2 图的存储结构
➢图的邻接矩阵存储表示
6.2 图的存储结构
➢采用数组表示法构造无向网G
• 输入顶点数、边数等基本数据 • 输入各顶点信息,构造顶点向量 G.vexs[n] • 初始化邻接矩阵 G.arcs • 输入各条边所依附的顶点及权值,写入邻接矩阵G.arcs
6.2 图的存储结构
➢采用邻接矩阵表示法,创建无向网G
图的定义和术语
• 对于有n个顶点的图,最多有多少条弧? (不考虑自身到自身的弧)
每个顶点最多向其它n-1个顶点分别发出一条弧 所以
• n个顶点的有向图最多可以有 n(n-1)条弧 • 考虑无向图的情况: • n个顶点的无向图最多可以有n(n-1)/2 条边
• 弧(边)数达到最大的图称作完全图
• 有很少(如e<nlogn)弧(边)的图称为稀疏图 • 反之称为稠密图
图的定义和术语
• 无向图G=(V,{E}) • 从顶点v到顶点v’的路径 是由v出发到达v’的顶点序列 • 若为有向图,则路径也是有向的 • 第一个顶点和最后一个顶点相同的路径叫做回路或环 • 序列中顶点不重复出现的路径称为简单路径 • 除了第一个顶点和最后一个顶点之外,其余顶点不重复
出现的回路称为简单回路或简单环
图的定义和术语
• 无向图G中,如果从顶点v到v’有路径, 则称v和v’是连通的
• 对于任意两个顶点都连通的图,叫做连通图 • 无向图中的极大连通子图叫做连通分量
v1
v2
v3
v4
v5
图的定义和术语
• 有向图中, • 对于任意两个顶点都存在双向路径的图,叫做强连通图 • 有向图中的极大强连通子图叫做强连通分量
6.2 图的存储结构
➢数组表示法
数据结构-图
出发点,访问D,标注数字序号④;
(a)无向图 G9
(b)深度优先遍历
图的遍历
3.1图的深度优先遍历
接着到G,访问G, 标注数字序号⑤;G 相邻顶点都访问过了,顺着虚线箭头方向
回退到 D,D 相邻顶点都访问过了,顺着虚线箭头方向回退到C,C 相邻顶点也都访问过
图的基本概念
1.2图的操作定义
02
PART
图的存储结构
2.1邻接矩阵
首先介绍的是数组表示法,即用两个数组分别存储顶点的信息和顶点之间的关系。
用来存放图中 n 个顶点的数组称为顶点数组。我们可将图中顶点按任意顺序保存到顶点数组中,
这样按存放次序每个顶点就对应一个位置序号(简称位序),依次为0~n-1;接着用一个 n×n 的二维
称为有向图。例如,当V={v1,v2,v3,v4,v5},VR={<v1,v2>,
<v1,v4>,<v2,v4>,<v3,v1>,<v3,v5>,<v4,v3>,<v5,v4>},则顶点集合
V、关系集合VR 构成有向图G1=(V,VR),如图(a)所示。
图的基本概念
1.1图的定义与基本术语
无向图(Undirected Graph)。如果顶点间的关系是无
序号作为表结点的值,所以一条弧对应一个表结点。右图为有向图 G1
和无向图 G2的邻接表表示法存储示意图。
图的存储结构
2.2邻接表
对于有向网和无向网,由于表结点表示边或弧,因此需要对表结点扩充一个属性域,表
结点至少包含顶点序号、权值和下一表结点指针 3 个属性,由此构成网的邻接表。
数据结构图
所以:对于点多边少的稀疏图来说,采用邻接表 结构使得算法在时间效 率上大大提高。
16
3/12
广度优先搜索(Breadth First Search,简称BFS ) BFS类似于树的层序遍历; 用一个数组用于标志已访问与否,还需要一个工作队列。
【例】一个无向图的BFS
8
6
CD
4
7
HG
BA
邻接多重表(Adjacency Multilist)
9
边表
• 在某些应用中,有时主要考察图中边的权值以及所依附的 两个顶点,即图的结构主要由边来表示,称为边表存储结 构。
• 边表结构采用顺序存储,用2个一维数组构成,一个存储 顶点信息,一个存储边的信息。边数组的每个元素由三部 分组成:
– 边的起点下标 – 边的终点下标 – 边的权值
1
A [i][
j]
0
如果 (vi , v j ) 或 vi , v j G的边 其它
无权图的邻接矩阵表示示例
V1
V2
V0
3
V3
4 12/15
带权图的邻接矩阵的定义
A [i][ j] wij
如果 (vi , vj ) 或 vi , v j G的边 其它
带图权的图邻的接邻矩接阵矩表阵示表示示例示[例例6.9]
1
第一部分 图的定义和术语
2
图的定义
“图” G可以表示为两个集合:G =(V, E)。每条 边是一个顶点对(v, w) E ,并且 v, w V。
通常:用 |V| 表示顶点的数量(|V| ≥ 1), 用 |E| 表示边的数量(|E| ≥ 0)。
(1) 无向图(完全有向图边数与顶点数之间的 关系) (2) 有向图(完全有向图弧数与顶点数之间的 关系) (3) 简单图:没有重边和自回路的图 (4) 邻接 (5) 路径,路径长度 (6) 无环(有向)图:没有任何回路的(有向)图 (7) 度,入度,出度 (8) 无向图的顶点连通、连通图、连通分量 (9) 有向图的顶点强连通,强连通图、连通分量
数据结构的存储方式以及优缺点
数据结构的存储⽅式以及优缺点在计算机中,数据的存储结构可以采⽤如下四种⽅法来实现。
1、顺序存储⽅式:顺序存储⽅式就是在⼀块连续的存储区域⼀个接着⼀个的存放数据。
顺序存储⽅式把逻辑上相邻的节点存储在物理位置放在相邻的存储单元⾥,节点间的逻辑关系由存储单元的邻接关系来体现。
顺序存储⽅式也称为顺序存储结构,⼀般采⽤数组或结构数组来描述。
2、链接存储⽅式:链接存储⽅式⽐较灵活,不要求逻辑上相邻的节点在物理位置上相邻,节点间的逻辑关系由附加的引⽤字段来表⽰。
⼀个节点的引⽤字段往往指向下⼀个节点的存放位置。
链接存储⽅式也成为链式存储结构。
3、索引存储⽅式:索引存储⽅式是采⽤附加的索引表的⽅式来存储节点信息的⼀种存储⽅式。
索引表由若⼲索引项组成。
索引存储⽅式中索引项的⼀般形式为(关键字、地址)。
其中,关键字是能够唯⼀标识⼀个节点的数据项。
索引存储⽅式还可以细分为如下两类。
稠密索引:这种⽅式中每个节点在索引表中都有⼀个索引项,其中索引项的地址知识节点所在的存储位置。
稀疏索引:这种⽅式中⼀组节点在索引表中只对应⼀个索引项。
其中,索引项的地址指⽰⼀组节点的起始存储位置。
4、散列存储⽅式:散列存储⽅式是根据节点的关键字直接计算出该节点的存储地址的⼀种存储⽅式。
1、顺序存储优点:在结点等长时可以随机存取存储密度⾼节省存储空间⽤结点的物理次序反映结点之间的逻辑关系缺点:插⼊和删除结点时要移动⼤量的结点必须静态分配连续空间2、链接存储优点:插⼊和删除⽐较灵活,不需要⼤量移动结点动态分配空间⽐较灵活,不需要预先申请最⼤的连续空间缺点:增加指针的空间开销检索必须沿链进⾏,不能随机存取。
数据结构-图及其存储结构
for (j=0;j<G.vexnum;+ +j ) adj Info G.arcs[i][j]={∞,NULL}; //Arccell的形式为: for (k=0;k<G.arcnum;+ +i ) { //二维数组存放各边上的信息 scanf(v1,v2,w); i=locatevex(G,v1); j=locatevex(G,v2); //求顶点v1,v2在图中的位置 G.arcs[i][j].adj=w; G.arcs[j][i].adj=w; //无向网的邻接矩阵是对称的 if (IncInfo) Input (*G.arcs[i][j].info); //将弧上的信息存储在指针info
case UDN: return CreateUDN(G);
default : return ERROR; }//CreateGraph
二、存储结构
2.数组表示法前提下图的输入
*以无向网为例,即当用户输入图的类型标志为UDN时,有:
Status CreateUDN(MGraph &G){ scanf(G.vexnum,G.arcnum,IncInfo); //IncInfo 为0时表示各弧
v2 6 5
v1 5 1 5 v3 3 6 4 2 v4
一个连通无向图的生成树是该图的一个连通分量,它 包含有该图的所有n个顶点以及连接这n个顶点的(n-1) 条边。 边或弧上带权值的图称为带权图或网(分为无向网和 有向网)。 一个无向图的所有生成树中,边上的权值之和最小的 生成树称为该图的最小生成树或最小代价生成树。
《数据结构》第 7 章 图
v3
v4 v5 v4
v3
v5 v4
v3
v5 v4
v3
v5 v4
v3
v5
注
一个图可以有许多棵不同的生成树。 所有生成树具有以下共同特点: 生成树的顶点个数与图的顶点个数相同; 生成树是图的极小连通子图; 一个有 n 个顶点的连通图的生成树有 n-1 条边; 生成树中任意两个顶点间的路径是唯一的; 在生成树中再加一条边必然形成回路。 含 n 个顶点 n-1 条边的图不一定是生成树。
A1 = {< v1, v2>, < v1, v3>, < v3, v4>, < v4, v1>} v1 v2
有向图
v3
v4
制作:计算机科学与技术学院 徐振中
数据结构 边:若 <v, w>∈VR 必有<w, v>∈VR,则以 无序对 (v, w) 代表这两个有序对,表示 v 和 w 之 间的一条边,此时的图称为无向图。 G2 = (V2, E2) V2 = {v1, v2, v3, v4, v5}
第七章 图
E2 = {(v1, v2), (v1, v4), (v2, v3), (v2, v5) , (v3, v4), (v3, v5)} v1
G2
v3
v2
无向图
v4
v5
制作:计算机科学与技术学院 徐振中
数据结构
第七章 图
例:两个城市 A 和 B ,如果 A 和 B 之间的连线的涵义是 表示两个城市的距离,则<A, B> 和 <B, A> 是相同的, 用 (A, B) 表示。 如果 A 和 B 之间的连线的涵义是表示两城市之 间人口流动的情况,则 <A, B> 和 <B, A> 是不同的。 北京 <北京,上海> (北京,上海) <上海,北京> <北京,上海> 北京 上海 上海
《数据结构》教案.
教学内容纲要: 第7章 图 7.1 图的定义和术语 (1)图 (2)无向图: (3)有向图:(4)完全图: 7.2 图的存储结构 (1)邻接矩阵 (2)邻接表
1
课程名称:数据结构
总课序
授课 时间
课型 (教法)
多媒体讲授
课题
任课教师 撰写(修改) 讲课内容
7.2.3 — 7.3
《数据结构》教案
广西民族大学数学与计算机学院
课程名称:数据结构
总课序
授课 时间
课型 (教法)
多媒体讲授
课题教具 准备教学 的掌握图的基本概念 掌握图的存储结构
任课教师 撰写(修改) 讲课内容
7.1—7.2.2
图的基本概念、存储结构
教学 重点
教学 难点 与关键
基本概念 图的邻接矩阵存储和邻接表存储
1.拓扑排序 2.关键路径、 7.6 最短路径
4
图的存储结构及遍历
教具 准备
教学 目的
掌握图的遍历 理解图的十字链表和邻接多重表存储结构:
教学 重点
图的深度优先遍历和广度优先遍历
教学 难点 与关键
图的深度优先遍历和广度优先遍历
教学内容纲要: 第7章 图 7.2 图的存储结构 3.十字链表 4.邻接多重表
7.3 图的遍历 1.深度优先遍历 2.广度优先遍历
2
课程名称:数据结构
总课序
授课 时间
课型 (教法)
多媒体讲授
任课教师 撰写(修改) 讲课内容
7.3 —7.4.3
课题
图的生成树、最小生成树
教具 准备
教学 目的
掌握生成树、最小生成树的相关问题
教学 重点
最小生成树的生成
数据结构_图_采用邻接矩阵存储,构造无向图
1.采用邻接矩阵(邻接表)存储,构造无向图(网)输入:顶点数、边数、顶点信息、边信息输出:图的顶点,图的边邻接矩阵(数组表示法)处理方法:用一个一维数组存储图中顶点的信息,用一个二维数组(称为邻接矩阵)存储图中各顶点之间的邻接关系。
假设图G=(V,E)有n个顶点,则邻接矩阵是一个n×n 的方阵,定义为:如果(vi,vj)属于边集,则edges[i][j]=1,否则edges[i][j]=0。
邻接表存储的处理方法:对于图的每个顶点vi,将所有邻接于vi的顶点链成一个单链表,称为顶点vi的边表(对于有向图则称为出边表),所有边表的头指针和存储顶点信息的一维数组构成了顶点表。
程序代码:#include<iostream>using namespace std;#define MAX_VERTEX_NUM 20 //最大顶点个数#define OK 1typedef int Status;//图的数组(邻接矩阵)存储表示typedef struct ArcCell { // 弧的定义int adj; // VRType是顶点关系类型。
// 对无权图,用1或0表示相邻否;// 对带权图,则为权值类型。
int *info; // 该弧相关信息的指针} ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];typedef struct { // 图的定义char vexs[MAX_VERTEX_NUM];//顶点向量AdjMatrix arcs; // 邻接矩阵int vexnum, arcnum; // 图的当前顶点数、弧数} MGraph;int LocateV ex(MGraph G, char v){int a;for (int i = 0; i <= G.vexnum; i++){if (G.vexs[i] == v)a= i;}return a;}Status CreateUDN(MGraph &G) { //采用邻接矩阵表示法,构造无向网Gint i, j, k, w;char v1, v2;cout <<"输入顶点数,边数:"<< endl;cin >> G.vexnum >> G.arcnum;//IncInfo为0,表示各弧无信息cout <<"各顶点分别为:"<< endl;for (i = 0; i<G.vexnum; i++)cin >> G.vexs[i]; //构造顶点向量for (i = 0; i<G.vexnum; i++) //初始化邻接矩阵for (j = 0; j<G.vexnum; j++){G.arcs[i][j].adj =NULL;}cout <<"顶点信息、边信息:"<< endl;for (k = 0; k<G.arcnum; k++) { //构造邻接矩阵cin >> v1 >> v2 >> w; //输入一条边依附的顶点及权值i = LocateV ex(G, v1); j = LocateV ex(G, v2);G.arcs[i][j].adj = w;G.arcs[j][i] = G.arcs[i][j];} return OK;} //CreateUDN (p162 算法7.2)Status printf1(MGraph G){cout <<"该图的顶点分别为:";for (int i = 0; i<G.vexnum; i++)cout << G.vexs[i] <<"";return OK;}Status printf2(MGraph G){cout <<"该图的边为:";for (int i = 1; i<G.vexnum; i++) //初始化邻接矩阵for (int j = 0; j<i; j++){if (G.arcs[i][j].adj !=NULL)cout << G.vexs[j]<< G.vexs[i] <<"," ;}return OK;}int main(){MGraph G;CreateUDN(G);printf1(G);cout << endl;printf2(G);cout << endl;system("pause");return 0;}。
数据结构-图的定义和术语
继续进行 ·3
·4
搜索。
·5
·6
·7
·3 ·1
·2
·4 从结点 5 出发的搜索序列:
5、6、2、3、1、4、7 适用的数据结构:栈
图的遍历
2、广度(宽度)优先搜索:
• 树:
A
B
C
D
EFG H
I JK
树的按层次进行访问的次序: A、B、C、D、E、F、G、H、 I、J、K、L
适用的数据结构:队列
L A
1
·1
2
12
11
·2
·11
·12
3
6
7
10
·3 ·6 ·7
·10
4
5
8
9
·4 ·5 ·8
·9
图的广度优先的访问次序:
1、2、11、12、3、6、7、10、4、5、8、9
适用的数据结构:队列
图的连通性问题
2、有向图的强连通分量的求法:续 •强连通分量的求法:
1、对有向图 G 进行深度为主的搜索,按照退 出该结点的次序给结点进行编号。最先退 出的结点的编号为 1,其它结点的编号按 次序逐次增大 1。
点1
3 已在U中
16 21 35
0 0 0
lowcost 表示最小距离
4∞ 0
adjvex 表示相应结点(在V -U中的)
5∞
0
lowcost adjvex
U1
6
5 1
25 35 4
3
6
4
2
566 图G
数组:closedge[ 6 ]
00 15 2 20 35 0 46 2 54 2
lowcost adjvex
数据结构(C++)--图
一、图的概念 二、图的应用 三、图的基本术语 四、图的存储结构
难点
1
一、图的概念
(Graph) Graph)
定义:图是由顶点集合(vertex)及边的集合 定义:图是由顶点集合 及边的集合 组成的一种数据结构: 组成的一种数据结构: Graph= Graph=( V, R ) 其中: 某个数据对象} 其中: V = { x | x ∈ 某个数据对象} 是顶点的有穷非空集合; 是顶点的有穷非空集合; R = {(u, v) | u, v ∈ V } {(u 是顶点之间关系的有穷集合, 是顶点之间关系的有穷集合,也叫做 (edge)集合 集合。 边(edge)集合。
1, 如果 < i , j >∈ E 或者 (i , j ) ∈ E Matrix[i ][ j ] = 0, 否则
1 7 3 4 2 8 3 1 6 5 5 4 2
最小(生成 树 最小 生成)树 生成 也称为 最小(支撑 树 最小 支撑)树 支撑
5
二、图的应用举例
例2: 最短路问题(SPP-Shortest Path Problem) : 最短路问题( ) 一名货柜车司机奉命在最短的时间内将一车货物从 甲地运往乙地。从甲地到乙地的公路网纵横交错, 甲地运往乙地。从甲地到乙地的公路网纵横交错, 因此有多种行车路线,这名司机应选择哪条线路呢? 因此有多种行车路线,这名司机应选择哪条线路呢? 假设货柜车的运行速度是恒定的, 假设货柜车的运行速度是恒定的,那么这一问题相 当于需要找到一条从甲地到乙地的最短路。 当于需要找到一条从甲地到乙地的最短路。 5 A 7 C 4 B 6 4 F 5 3 E 1
5 (开始) A 开始) 7 4
数据结构的三大概念逻辑结构、存储结构和运算
数据结构的三大概念逻辑结构、存储结构和运算数据结构的三大概念:逻辑结构、存储结构和运算数据结构是计算机科学中非常重要的一个概念,它是指数据元素之间的关系以及对这些数据元素进行操作的方法。
在数据结构中,有三个核心概念,分别是逻辑结构、存储结构和运算。
这三个概念相互联系、相互作用,共同构成了数据结构的基本框架。
下面将分别对这三个概念进行详细介绍。
逻辑结构逻辑结构是指数据元素之间的逻辑关系,它独立于数据元素的存储结构。
在数据结构中,常见的逻辑结构包括线性结构、树形结构和图形结构。
1. 线性结构线性结构是最简单、最基本的逻辑结构,数据元素之间是一对一的关系。
线性结构包括线性表、栈、队列等。
其中,线性表是最为常见的线性结构,它包括顺序表和链表两种存储结构。
顺序表中的数据元素在内存中是连续存储的,而链表中的数据元素在内存中是不连续存储的,通过指针来连接各个节点。
2. 树形结构树形结构是一种重要的非线性结构,它包括二叉树、二叉搜索树、平衡二叉树等。
在树形结构中,每个节点可以有零个或多个子节点,节点之间通过边相连。
树形结构常用于表示具有层次关系的数据,如文件系统、组织结构等。
3. 图形结构图形结构是最为复杂的逻辑结构,它包括有向图和无向图。
在图形结构中,节点之间的关系是任意的,可以是一对一、一对多或多对多的关系。
图形结构常用于描述网络、社交关系等复杂系统。
存储结构存储结构是指数据结构在计算机内存中的表示方式,它决定了数据元素在内存中的存储位置以及数据元素之间的物理关系。
常见的存储结构包括顺序存储结构和链式存储结构。
1. 顺序存储结构顺序存储结构是将数据元素存储在一块连续的内存空间中,数据元素之间的物理关系与其逻辑关系一致。
顺序存储结构适合于对数据元素的随机访问,但插入和删除操作效率较低。
2. 链式存储结构链式存储结构是通过指针将数据元素存储在不连续的内存空间中,数据元素之间通过指针相连。
链式存储结构适合于频繁的插入和删除操作,但访问效率较低。
计算机图形学-图形数据结构
(2)插入操作 顺序表的删除操作是指在长度为 n 的线性表的第 i-1个元素 和第 i 元素之间插入一个新的元素,就是要使长度为 n 的线性表
T =(t1,…,ti–1,ti,…,tn) 变成长度为 n +1 的线性表
(t1,…,ti–1,x,ti,…,tn)
2023/6/18
12
计算机图形学
数据元素 ti–1和 ti 之间的逻辑关系发生改变。为了在存储结 构上反映这个变化,除非 i = n +1,否则必须移动元素才能反映 这个逻辑关系的变化。具体的算法步骤如下:
t[1] t[2] … t[i-1] t[i] t[i+1] … t[n]
X
(3)顺序表的应用及不足
在图形程序中,可用顺序表对简单的图形(包括二维和三
维)进行建模:
顶点表(各顶点坐标)
边表(各顶点间的连边规则)
2023/6/18
14ห้องสมุดไป่ตู้
计算机图形学
但由于图形间的运算,使得两表不断改变,致使表中元素搬家 频繁。因此,线性表适用作静态表。图形间的运算,使得图形 的几何关系和拓扑关系经常发生变化(见图例)。
① 用一组地址连续的存储单元依次存储线性表的数据 元素,采用这种存储结构的线性表称为顺序表;
② 用一组任意的存储单元存储线性表的数据元素,采 用这种存储结构的线性表称为链表; 线性表的操作。线性表的基本操作有存取元素、删除和 插入元素操作等。
2023/6/18
8
计算机图形学
2.2 线性表的顺序表示和实现
2023/6/18
30
计算机图形学
3.2 二叉树
二叉树是最为重要的树形结构,与一般形态的树的区别在 于:
2024版《数据结构图》ppt课件
良好的数据结构可以带来更高的运 行或存储效率,是算法设计的基础, 对程序设计的成败起到关键作用。
常见数据结构类型介绍
线性数据结构
如数组、链表、栈、队 列等,数据元素之间存
在一对一的关系。
树形数据结构
如二叉树、多叉树、森 林等,数据元素之间存
在一对多的关系。
图形数据结构
由顶点和边组成,数据 元素之间存在多对多的
队列定义、特点及应用场景
队列的特点 只能在队尾进行插入操作,队头进行删除操作。
队列是一种双端开口的线性结构。
队列定义、特点及应用场景
应用场景 操作系统的任务调度。 缓冲区的实现,如打印机缓冲区。
队列定义、特点及应用场景
广度优先搜索(BFS)。
消息队列和事件驱动模型。
串定义、基本操作及实现方法
最短路径问题 求解图中两个顶点之间的最短路径,即路径上边 的权值之和最小。
3
算法介绍 Prim算法、Kruskal算法、Dijkstra算法、Floyd 算法等。
拓扑排序和关键路径问题探讨
拓扑排序
对有向无环图(DAG)进行排序, 使得对每一条有向边(u,v),均有
u在v之前。
关键路径问题
求解有向无环图中从源点到汇点 的最长路径,即关键路径,它决
遍历二叉树和线索二叉树
遍历二叉树
先序遍历、中序遍历和后序遍历。遍历算 法可以采用递归或非递归方式实现。
VS
线索二叉树
利用二叉链表中的空指针来存放其前驱结 点和后继结点的信息,使得在遍历二叉树 时可以利用这些线索得到前驱和后继结点, 从而方便地遍历二叉树。
树、森林与二叉树转换技巧
树转换为二叉树
加线、去线、层次调整。将树中的每个结点的所有孩子结点用线连接起来,再去掉与原结点相连的线,最后 将整棵树的层次进行调整,使得每个结点的左子树为其第一个孩子,右子树为其兄弟结点。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据结构图的存储结构及基本操作1.实验目的通过上机实验进一步掌握图的存储结构及基本操作的实现。
2.实验内容与要求要求:⑴能根据输入的顶点、边/弧的信息建立图;⑵实现图中顶点、边/弧的插入、删除;⑶实现对该图的深度优先遍历;⑷实现对该图的广度优先遍历。
备注:单号基于邻接矩阵,双号基于邻接表存储结构实现上述操作。
3.数据结构设计逻辑结构:图状结构存储结构:顺序存储结构、链式存储结构4.算法设计#include <stdio.h> #include <string.h> #include <stdlib.h> #defineMAX_VERTEX_NU M 20 typedef struct ArcNode{int adjvex;struct ArcNode *nextarc;}ArcNode;typedef struct VNode {char data[2]; //顶点就设置和书上V1等等一样吧ArcNode *firstarc; }VNode,AdjList[MAX _VERTEX_NUM]; typedef struct{AdjList vertices;int vexnum,arcnum; }ALGraph;typedef struct{intdata[MAX_VERTEX_ NUM+10];int front;int rear;}queue; intvisited[MAX_VERTE X_NUM];queue q;int main(){ALGraph G;intCreateUDG(ALGraph &G);intDeleteUDG(ALGraph &G);intInsertUDG(ALGraph &G);void BFSTraverse(ALGrap h G, int (*Visit)(ALGraphG,ArcNode v));intPrintElement(ALGrap h G,ArcNode v);void menu();void depthfirstsearch(ALG raph *g,int vi);voidtravel(ALGraph *g); void breadfirstsearch(ALG raph *g);int i;G.arcnum = G.vexnum = 0;while(1){menu();do{printf ( "请输入要进行的操作\n" );scanf("%d",&i);if (i<1||i>6)printf("错误数字,请重新输入\n");}while (i<1||i>6);switch (i){case 1: CreateUDG(G); system("pause"); system("cls"); break;case 2: DeleteUDG(G); system("pause"); system("cls"); break;case 3: InsertUDG(G); system("pause"); system("cls"); break;case 4: travel(&G);system("pause"); system("cls"); break;case 5: breadfirstsearch(&G); system("pause"); system("cls"); break;case 6: exit(0); break;}}return 1;}void enterqueue(int v) {q.data[q.rear]=v;q.rear++;}int deletequeue() {int t;t=q.data[q.front];q.front++;return(t);}int empty(){if(q.front==q.rear)return 1;return 0;}intLocateVex(ALGraph G,char node[2]){int i;for(i = 0 ; i < G.vexnum ; i++){if(strcmp(G.vertices[ i].data,node)==0)return i;}return -1;}intCreateUDG(ALGraph &G){intLocateVex(ALGraph G,char node[2]);voidPrintUDG(ALGraph G);int i,j,k;charnode1[2],node2[2]; ArcNode *p,*q;printf("请输入顶点数和弧数\n");printf("例如:5,6\n");scanf("%d,%d",&G .vexnum,&G.arcnum); printf("请输入各顶点\n");for(i = 0 ; i < G.vexnum ; i++){printf("第%d个\n",i+1);scanf("%s",&G.vert ices[i]);G.vertices[i].firstarc = NULL;}//这里开始构造边printf("请输入边的信息\n");printf("例如:v1 v2\n");for(i = 0 ; i < G.arcnum ; i++){printf("第%d条边\n",i+1);scanf("%s %s",&n ode1,&node2);j = LocateVex(G,node1);k = LocateVex(G,node2);p = (ArcNode *)malloc(sizeof(ArcNo de));q = (ArcNode *)malloc(sizeof(ArcNo de));p->adjvex = k;q->adjvex = j;p->nextarc = G.vertices[j].firstarc;G.vertices[j].firstarc = p;q->nextarc = G.vertices[k].firstarc;G.vertices[k].firstar c = q;}PrintUDG(G); return 1;}intDeleteUDG(ALGraph &G){int i,j;ArcNode *p,*q; char node[2];intLocateVex(ALGraph G,char node[2]);voidPrintUDG(ALGraph G);if(G.arcnum == 0) {printf("请先生成图\n");return 0;}printf("请输入要删除的节点\n");scanf("%s",&node) ;i = LocateVex(G,node);if(i == -1){printf("无此节点\n");return 0;}else{G.vexnum--;if((p = q = G.vertices[i].firstarc) ! = NULL){G.arcnum--;p = p->nextarc;G.vertices[i].firstarc = p;free(q);q = p;while(p != NULL){G.arcnum--;p = p->nextarc;G.vertices[i].firstarc = p;free(q);q = p;}}for(j = 0 ; j < G.vexnum ; j++ ){if(j >= i){strcpy(G.vertices[j]. data , G.vertices[j+1].data);G.vertices[j].firstarc = G.vertices[j+1].firstarc ;}if(G.vertices[j].firsta rc->nextarc != NULL){p = G.vertices[j].firstarc;q = p->nextarc;if(p->adjvex == i){G.vertices[j].firstarc = q;p = q;q = q->nextarc;continue;}elseif(p->adjvex > i)p->adjvex--;while(q != NULL){if(q->adjvex == i){p->nextarc = q->nextarc;free(q);q = p->nextarc;}elseif(q->adjvex > i)q->adjvex--;else{p = p->nextarc;q = q->nextarc;}}}elseif( (G.vertices[j].firstar c->nextarc == NULL) &&(G.vertices[j].firstarc ! = NULL) )if( G.vertices[j].first arc->adjvex == i ){G.vertices[j].firstarc = NULL;}}}PrintUDG(G); return 1;}intInsertUDG(ALGraph &G){//默认一次插入一个节点吧,不然太麻烦int i,j,k,l;charnode1[2],node2[2]; ArcNode *p,*q;intLocateVex(ALGraph G,char node[2]);voidPrintUDG(ALGraph G);if(G.arcnum == 0) {printf("请先生成图\n");return 0;}printf("请输入插入节点的名称\n"); printf("WARNING:绝不可以和之前的节点重名!\n");scanf("%s",&G.vert ices[G.vexnum].data);G.vertices[G.vexnu m].firstarc = NULL; printf("请输入需要插入的边的数目\n"); scanf("%d",&i); G.arcnum += i; G.vexnum++;printf("请输入边的信息\n");printf("例如:v6 v2\n");printf("WARNING:一定要包含刚加入的节点名称!\n");for(j = 0 ; j < i ; j++) {printf("第%d条边\n",j+1);scanf("%s %s",&n ode1,&node2);l = LocateVex(G,node1);k = LocateVex(G,node2);p = (ArcNode *)malloc(sizeof(ArcNo de));q = (ArcNode *)malloc(sizeof(ArcNo de));p->adjvex = k;q->adjvex = l;p->nextarc = G.vertices[l].firstarc;G.vertices[l].firstarc = p;q->nextarc = G.vertices[k].firstarc;G.vertices[k].firstar c = q;}PrintUDG(G); return 1;}void depthfirstsearch(ALG raph *g,int vi){ArcNode *rear;printf("%s\t",g->verti ces[vi].data);visited[vi]=1;rear=g->vertices[vi].fir starc;while((rear!=NULL)& &(!visited[rear->adjve x])){depthfirstsearch(g,rear ->adjvex);rear=rear->nextarc;}}void travel(ALGraph *g) {int v;for(v=0;v<g->vexnum; v++)if(!visited[v])depthfirstsearch(g,v); }void breadfirstsearch(ALG raph *g){int v,t,i;ArcNode *rear; for(i = 0 ; i <g->vexnum ; i++)visited[i] = 0;for(v=0;v<g->vexnum; v++){if(!visited[v]){printf("%s",g->vertic es[v].data);visited[v]=1;enterqueue(v);}while(!empty()){t=deletequeue();rear=g->vertices[t].firs tarc;while((rear!=NULL)& &(!visited[rear->adjve x])){printf("%s\t",g->verti ces[rear->adjvex].data );visited[rear->adjvex]= 1;enterqueue(rear->adjv ex);rear=rear->nextarc;}}}}void menu(){printf("******************************* **************\n"); printf("*作者:Dick *\n");printf("* 信计1001 xxxxxxxxxx*\n");printf("************ *********MENU**** ****************\n") ;printf("1 建立无向图\n");printf("2 删除图中节点\n");printf("3 插入节点\n");printf("4 深度优先遍历图\n");printf("5 广度优先遍历图\n");printf("6 退出程序\n");}voidPrintUDG(ALGraph G){int i;ArcNode *p;for(i = 0 ; i < G.vexnum ; i++){if(G.vertices[i].firsta rc != NULL){printf("与节点%s相邻的节点为:\n",G .vertices[i].dat a); p= G.vertices[i].firstarc; while(p != NULL) {printf("%s\t",G.ver tices[p->adjvex].data); p =p->nextarc; }printf("\n");}elseprintf("无与节点%s 相邻的节点\n",G .vertices[i].data); } }5. 测试结果图一:菜单项图一:菜单项。