图的建立及遍历算法的实现
c++实现图的基本操作的建立及输出

int w;
visited[v]=1; printf("%d%c->",v,G.vertices[v].data);
for(w=FirstAdjVex(G,v);w!=-1;w=NextAdjVex(G,v,w))
if(visited[w]==0) DFS(G,w);
}
void DFSTrave宝箱开启!
淘金行动火热升级,第二波奖品等你来拿!更有财富值及精美徽章等着你哦~勇往直前,意想不到的惊喜等着你!
查看
新闻网页贴吧知道MP3图片视频百科 帮助 | 设置 知道 > 电脑/网络 > 程序设计 > C/C++
最佳答案 两个版本.第一个是我自己做的,带深度遍历 第二个是同学的,比较全.
时间太久了..自己都看不明白了
您自己研究吧
#include "stdlib.h"
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
typedef struct VNode {
VertexType data; // 顶点信息
ArcNode *firstarc;
// 指向第一条依附该顶点的弧
} VNode, AdjList[MAX_VERTEX_NUM];
while(TNode->nextarc!=NULL){
printf("->%d",TNode->nextarc->adjvex);
数据结构-实验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。
数据结构第七章-图

*
V0
V7
V6
V5
V4
V3
V2
V1
若图的存储结构为邻接表,则 访问邻接点的顺序不唯一, 深度优先序列不是唯一的
V0
V1
V3
V2
V7
V6
V5
V4
V0,V1,V3,V4,V7,V2,V5,V6,
※求图G以V0为起点的的深度优先序列(设存储结构为邻接矩阵)
void DFSAL(ALGraph G, int i) {/*从第v个顶点出发,递归地深度优先遍历图G*/ /* v是顶点的序号,假设G是用邻接表存储*/ EdgeNode *p; int w; visited[i] =1; Visit(i); /*访问第v个顶点*/ for (p=G.vertices[i].firstarc;p;p=p->nextarc) {w=p->adjvex; /*w是v的邻接顶点的序号*/ if (!visited[w]) DFSAL(G, w); /*若w尚未访问, 递归调用DFS*/ } }/*DFSAL*/
在邻接表存储结构上的广度优先搜索
*
Q
V0
V1
V2
V3
V4
V7
V5
V6
V1
V2
V3
V0
V4
V7
V5
V6
V0
V7
V6
V5
V4
V3
V2
V1
7.3 图的遍历
7
0
1
2
V0
V2
V3
V1
data
firstarc
0
1
^
^
adjvex
next
3
图的遍历操作实验报告

-实验三、图的遍历操作一、目的掌握有向图和无向图的概念;掌握邻接矩阵和邻接链表建立图的存储构造;掌握DFS及BFS对图的遍历操作;了解图构造在人工智能、工程等领域的广泛应用。
二、要求采用邻接矩阵和邻接链表作为图的存储构造,完成有向图和无向图的DFS 和BFS操作。
三、DFS和BFS 的根本思想深度优先搜索法DFS的根本思想:从图G中*个顶点Vo出发,首先访问Vo,然后选择一个与Vo相邻且没被访问过的顶点Vi访问,再从Vi出发选择一个与Vi相邻且没被访问过的顶点Vj访问,……依次继续。
如果当前被访问过的顶点的所有邻接顶点都已被访问,则回退到已被访问的顶点序列中最后一个拥有未被访问的相邻顶点的顶点W,从W出发按同样方法向前遍历。
直到图中所有的顶点都被访问。
广度优先算法BFS的根本思想:从图G中*个顶点Vo出发,首先访问Vo,然后访问与Vo相邻的所有未被访问过的顶点V1,V2,……,Vt;再依次访问与V1,V2,……,Vt相邻的起且未被访问过的的所有顶点。
如此继续,直到访问完图中的所有顶点。
四、例如程序1.邻接矩阵作为存储构造的程序例如#include"stdio.h"#include"stdlib.h"#define Ma*Verte*Num 100 //定义最大顶点数typedef struct{char ve*s[Ma*Verte*Num]; //顶点表int edges[Ma*Verte*Num][Ma*Verte*Num]; //邻接矩阵,可看作边表int n,e; //图中的顶点数n和边数e}MGraph; //用邻接矩阵表示的图的类型//=========建立邻接矩阵=======void CreatMGraph(MGraph *G){int i,j,k;char a;printf("Input Verte*Num(n) and EdgesNum(e): ");scanf("%d,%d",&G->n,&G->e); //输入顶点数和边数scanf("%c",&a);printf("Input Verte* string:");for(i=0;i<G->n;i++){scanf("%c",&a);G->ve*s[i]=a; //读入顶点信息,建立顶点表}for(i=0;i<G->n;i++)for(j=0;j<G->n;j++)G->edges[i][j]=0; //初始化邻接矩阵printf("Input edges,Creat Adjacency Matri*\n");for(k=0;k<G->e;k++) { //读入e条边,建立邻接矩阵 scanf("%d%d",&i,&j); //输入边〔Vi,Vj〕的顶点序号G->edges[i][j]=1;G->edges[j][i]=1; //假设为无向图,矩阵为对称矩阵;假设建立有向图,去掉该条语句}}//=========定义标志向量,为全局变量=======typedef enum{FALSE,TRUE} Boolean;Boolean visited[Ma*Verte*Num];//========DFS:深度优先遍历的递归算法======void DFSM(MGraph *G,int i){ //以Vi为出发点对邻接矩阵表示的图G进展DFS搜索,邻接矩阵是0,1矩阵 int j;printf("%c",G->ve*s[i]); //访问顶点Vivisited[i]=TRUE; //置已访问标志for(j=0;j<G->n;j++) //依次搜索Vi的邻接点if(G->edges[i][j]==1 && ! visited[j])DFSM(G,j); //〔Vi,Vj〕∈E,且Vj未访问过,故Vj为新出发点}void DFS(MGraph *G){int i;for(i=0;i<G->n;i++)visited[i]=FALSE; //标志向量初始化for(i=0;i<G->n;i++)if(!visited[i]) //Vi未访问过DFSM(G,i); //以Vi为源点开场DFS搜索}//===========BFS:广度优先遍历=======void BFS(MGraph *G,int k){ //以Vk为源点对用邻接矩阵表示的图G进展广度优先搜索 int i,j,f=0,r=0;int cq[Ma*Verte*Num]; //定义队列for(i=0;i<G->n;i++)visited[i]=FALSE; //标志向量初始化for(i=0;i<G->n;i++)cq[i]=-1; //队列初始化printf("%c",G->ve*s[k]); //访问源点Vkvisited[k]=TRUE;cq[r]=k; //Vk已访问,将其入队。
《软件技术基础》实验指导

说明每个实验题目含有一个main函数和一些函数, 与实验题目相关的基本运算的函数定义和main函数定义的代码在附录以及对应的文件夹中给出, 供上机实验参考使用。
对于每个题目, 只需要根据题目要求设计算法, 补充函数定义, 然后对程序进行编译、调试。
实验一线性表一、实验目的1.熟悉线性表的顺序和链式存储结构2.掌握线性表的基本运算3.能够利用线性表的基本运算完成线性表应用的运算二、实验内容设有一个线性表E={e1, e2, …, en-1, en}, 设计一个算法, 将线性表逆置, 即使元素排列次序颠倒过来, 成为逆线性表E’={ en , en-1 , …, e2 , e1 }, 要求逆线性表占用原线性表空间, 并且用顺序表和单链表两种方法表示, 分别用两个程序来完成。
(文件夹: 顺序表逆置、单链表逆置)已知由不具有头结点的单链表表示的线性表中, 含有三类字符的数据元素(字母、数字和其他字符), 试编写算法构造三个以循环链表表示的线性表, 使每个表中只含有同一类的字符, 且利用原表中的结点空间, 头结点可另辟空间。
(文件夹: 分解单链表)实验二栈和队列一、实验目的1.熟悉栈和队列的顺序和链式存储结构2.掌握栈和队列的基本运算3.能够利用栈和队列的基本运算完成栈和队列应用的运算二、实验内容1.设单链表中存放有n个字符, 试编写算法, 判断该字符串是否有中心对称的关系, 例如xyzzyx是中心对称的字符串。
(提示: 将单链表中的一半字符先依次进栈, 然后依次出栈与单链表中的另一半字符进行比较。
)(文件夹: 判字符串中心对称)假设以数组sequ[m]存放循环队列的元素, 同时设变量rear和quelen 分别指示循环队列中队空的条件:sq->quelen==0;队满的条件:sq->quelen==m。
(文件夹:循环队列)实验三串一、实验目的1.熟悉串的顺序存储结构2.掌握串的基本运算及应用二、实验内容1. 串采用顺序存储结构, 编写朴素模式匹配算法, 查找在串中是否存在给定的子串。
数据结构课设——有向图的深度、广度优先遍历及拓扑排序

数据结构课设——有向图的深度、⼴度优先遍历及拓扑排序任务:给定⼀个有向图,实现图的深度优先, ⼴度优先遍历算法,拓扑有序序列,并输出相关结果。
功能要求:输⼊图的基本信息,并建⽴图存储结构(有相应提⽰),输出遍历序列,然后进⾏拓扑排序,并测试该图是否为有向⽆环图,并输出拓扑序列。
按照惯例,先上代码,注释超详细:#include<stdio.h>#include<stdlib.h>#include<malloc.h>#pragma warning(disable:4996)#define Max 20//定义数组元素最⼤个数(顶点最⼤个数)typedef struct node//边表结点{int adjvex;//该边所指向结点对应的下标struct node* next;//该边所指向下⼀个结点的指针}eNode;typedef struct headnode//顶点表结点{int in;//顶点⼊度char vertex;//顶点数据eNode* firstedge;//指向第⼀条边的指针,边表头指针}hNode;typedef struct//邻接表(图){hNode adjlist[Max];//以数组的形式存储int n, e;//顶点数,边数}linkG;//以邻接表的存储结构创建图linkG* creat(linkG* g){int i, k;eNode* s;//边表结点int n1, e1;char ch;g = (linkG*)malloc(sizeof(linkG));//申请结点空间printf("请输⼊顶点数和边数:");scanf("%d%d", &n1, &e1);g->n = n1;g->e = e1;printf("顶点数:%d 边数:%d\n", g->n, g->e);printf("请输⼊顶点信息(字母):");getchar();//因为接下来要输⼊字符串,所以getchar⽤于承接上⼀条命令的结束符for (i = 0; i < n1; i++){scanf("%c", &ch);g->adjlist[i].vertex = ch;//获得该顶点数据g->adjlist[i].firstedge = NULL;//第⼀条边设为空}printf("\n打印顶点下标及顶点数据:\n");for (i = 0; i < g->n; i++)//循环打印顶点下标及顶点数据{printf("顶点下标:%d 顶点数据:%c\n", i, g->adjlist[i].vertex);}getchar();int i1, j1;//相连接的两个顶点序号for (k = 0; k < e1; k++)//建⽴边表{printf("请输⼊对<i,j>(空格分隔):");scanf("%d%d", &i1, &j1);s = (eNode*)malloc(sizeof(eNode));//申请边结点空间s->adjvex = j1;//边所指向结点的位置,下标为j1s->next = g->adjlist[i1].firstedge;//将当前s的指针指向当前顶点上指向的结点g->adjlist[i1].firstedge = s;//将当前顶点的指针指向s}return g;//返回指针g}int visited[Max];//标记是否访问void DFS(linkG* g, int i)//深度优先遍历{eNode* p;printf("%c ", g->adjlist[i].vertex);visited[i] = 1;//将已访问过的顶点visited值改为1p = g->adjlist[i].firstedge;//p指向顶点i的第⼀条边while (p)//p不为NULL时(边存在){if (visited[p->adjvex] != 1)//如果没有被访问DFS(g, p->adjvex);//递归}p = p->next;//p指向下⼀个结点}}void DFSTravel(linkG* g)//遍历⾮连通图{int i;printf("深度优先遍历;\n");//printf("%d\n",g->n);for (i = 0; i < g->n; i++)//初始化为0{visited[i] = 0;}for (i = 0; i < g->n; i++)//对每个顶点做循环{if (!visited[i])//如果没有被访问{DFS(g, i);//调⽤DFS函数}}}void BFS(linkG* g, int i)//⼴度优先遍历{int j;eNode* p;int q[Max], front = 0, rear = 0;//建⽴顺序队列⽤来存储,并初始化printf("%c ", g->adjlist[i].vertex);visited[i] = 1;//将已经访问过的改成1rear = (rear + 1) % Max;//普通顺序队列的话,这⾥是rear++q[rear] = i;//当前顶点(下标)队尾进队while (front != rear)//队列⾮空{front = (front + 1) % Max;//循环队列,顶点出队j = q[front];p = g->adjlist[j].firstedge;//p指向出队顶点j的第⼀条边while (p != NULL){if (visited[p->adjvex] == 0)//如果未被访问{printf("%c ", g->adjlist[p->adjvex].vertex);visited[p->adjvex] = 1;//将该顶点标记数组值改为1rear = (rear + 1) % Max;//循环队列q[rear] = p->adjvex;//该顶点进队}p = p->next;//指向下⼀个结点}}}void BFSTravel(linkG* g)//遍历⾮连通图{int i;printf("⼴度优先遍历:\n");for (i = 0; i < g->n; i++)//初始化为0{visited[i] = 0;}for (i = 0; i < g->n; i++)//对每个顶点做循环{if (!visited[i])//如果没有被访问过{BFS(g, i);//调⽤BFS函数}}}//因为拓扑排序要求⼊度为0,所以需要先求出每个顶点的⼊度void inDegree(linkG* g)//求图顶点⼊度{eNode* p;int i;for (i = 0; i < g->n; i++)//循环将顶点⼊度初始化为0{g->adjlist[i].in = 0;}for (i = 0; i < g->n; i++)//循环每个顶点{p = g->adjlist[i].firstedge;//获取第i个链表第1个边结点指针while (p != NULL)///当p不为空(边存在){g->adjlist[p->adjvex].in++;//该边终点结点⼊度+1p = p->next;//p指向下⼀个边结点}printf("顶点%c的⼊度为:%d\n", g->adjlist[i].vertex, g->adjlist[i].in);}void topo_sort(linkG *g)//拓扑排序{eNode* p;int i, k, gettop;int top = 0;//⽤于栈指针的下标索引int count = 0;//⽤于统计输出顶点的个数int* stack=(int *)malloc(g->n*sizeof(int));//⽤于存储⼊度为0的顶点for (i=0;i<g->n;i++)//第⼀次搜索⼊度为0的顶点{if (g->adjlist[i].in==0){stack[++top] = i;//将⼊度为0的顶点进栈}}while (top!=0)//当栈不为空时{gettop = stack[top--];//出栈,并保存栈顶元素(下标)printf("%c ",g->adjlist[gettop].vertex);count++;//统计顶点//接下来是将邻接点的⼊度减⼀,并判断该点⼊度是否为0p = g->adjlist[gettop].firstedge;//p指向该顶点的第⼀条边的指针while (p)//当p不为空时{k = p->adjvex;//相连接的顶点(下标)g->adjlist[k].in--;//该顶点⼊度减⼀if (g->adjlist[k].in==0){stack[++top] = k;//如果⼊度为0,则进栈}p = p->next;//指向下⼀条边}}if (count<g->n)//如果输出的顶点数少于总顶点数,则表⽰有环{printf("\n有回路!\n");}free(stack);//释放空间}void menu()//菜单{system("cls");//清屏函数printf("************************************************\n");printf("* 1.建⽴图 *\n");printf("* 2.深度优先遍历 *\n");printf("* 3.⼴度优先遍历 *\n");printf("* 4.求出顶点⼊度 *\n");printf("* 5.拓扑排序 *\n");printf("* 6.退出 *\n");printf("************************************************\n");}int main(){linkG* g = NULL;int c;while (1){menu();printf("请选择:");scanf("%d", &c);switch (c){case1:g = creat(g); system("pause");break;case2:DFSTravel(g); system("pause");break;case3:BFSTravel(g); system("pause");break;case4:inDegree(g); system("pause");break;case5:topo_sort(g); system("pause");break;case6:exit(0);break;}}return0;}实验⽤图:运⾏结果:关于深度优先遍历 a.从图中某个顶点v 出发,访问v 。
中国石油大学(华东)859数据结构2021年考研专业课初试大纲
2021年硕士研究生入学考试大纲考试科目名称:数据结构考试时间:180分钟,满分:150分一、考试要求1.理解数据结构、存储结构、算法、数据类型、抽象数据类型(ADT)等基本概念及它们之间的关系。
2.掌握线性表、树、图等基本数据结构的ADT定义以及基于不同存储方式(顺序、链式等)的实现,并能对占用存储空间情况和算法的时间复杂度进行分析。
3.掌握典型的查找结构(静态表、搜索树、散列等)、查找算法的基本思想及性能分析。
4.掌握内部排序(选择、插入、交换、归并等)的重要算法的基本思想、特点及性能分析。
5.能够运用学习的数据结构及算法的知识和技能进行问题的分析与求解,即能对问题进行抽象建模,能熟练使用高级语言(C或C++或JAVA等)进行模型的具体实现(编程)。
二、考试内容1.数据结构和算法的重要性(1)基本概念及它们之间的关系(2)各种存储结构的空间占用情况及映射逻辑关系的方式(3)算法的评价及对算法渐近时间复杂性的理解2.一般线性表(1)一般线性表ADT的定义(2)线性表ADT基于顺序存储的实现(存储方式、特点、重要操作的算法,下同)(3)线性表ADT基于链式存储的实现(存储方式、特点、重要操作的算法,下同)3.特殊线性表(栈、队列、字符串、数组)(1)栈的特点及栈ADT的定义(2)栈ADT基于顺序存储的实现(3)栈ADT基于链式存储的实现(4)栈ADT的应用(表达式求值、递归处理、迷宫问题)(5)队列的特点及队列ADT的定义(6)队列ADT基于顺序存储的实现(7)队列ADT基于链式存储的实现(8)队列ADT的应用(广度遍历、资源分配问题)(9)字符串特点及串ADT的定义(10)字符串ADT基于顺序存储的实现(重点掌握经典的模式匹配算法:BF,KMP)(11)数组的特点及ADT定义(12)数组ADT基于顺序存储的实现(重点掌握多维数组的存储结构)(13)特殊矩阵的存储及操作实现(重点掌握分布有规律的特殊矩阵和分布无规律的稀疏矩阵如何高效存储及矩阵典型操作的实现)4.树与二叉树(1)二叉树的特点及ADT定义(2)二叉树的重要性质及证明(3)二叉树基于顺序存储的实现(4)二叉树基于链式存储的实现(重点掌握重要操作:建立、遍历、求深度、计算叶子等等)(5)线索二叉树的基本概念(为什么加线索?如何记录线索?如何使用线索?)(6)建立(画)线索二叉树(7)树、森林的定义及特点(8)树的存储结构(重点掌握子女-兄弟表示)(9)树、森林与二叉树的相互转换(10)树和森林的遍历(11)哈夫曼(Huffman)树和哈夫曼编码的构造过程(12)二叉排序树的定义及建立(重点掌握结点的插入和删除的思想和过程)(13)平衡二叉树的定义及建立(平衡的目的?如何达到平衡?)(14)堆的定义及建立和调整(堆的构造和调整过程)5.图(1)图的基本概念及ADT定义(2)图的ADT的实现(存储方式及基本操作实现)①邻接矩阵存储(无向图、有向图、无向带权图、有向带权图)②邻接表存储(无向图、有向图、无向带权图、有向带权图)③各种存储方式下操作的算法实现(图的建立、遍历、插入边、删除边等)(3)图的遍历及生成树①深度优先遍历(思想、过程及算法实现)②广度优先遍历(思想、过程及算法实现)(4)图的基本应用(掌握算法的思想、过程)①最小生成树问题②最短路径问题③有向图与工程问题(工程调度:AOV网与拓扑排序,工期:AOE网与关键路径)6.查找(1)查找的基本概念(2)顺序查找法(监视哨法的思想和算法)(3)折半查找法(思想和算法)(4)树查找(二叉排序树)(5)B树及其基本操作、B+树的基本概念(思想和过程)(6)散列(Hash)查找(Hash函数和解决冲突的方法的思想和过程)(6)各种查找表的组织及查找算法的时间复杂度、平均查找长度的分析7.排序(1)排序的基本概念(2)基于“插入”思想的排序方法①直接插入排序②折半插入排序(思想和过程)③希尔排序(思想和过程)(3)基于“交换”思想的排序方法①冒泡排序(思想、过程和算法)②快速排序(思想、过程和算法)(4)基于“选择”思想的排序方法①简单选择排序(思想、过程和算法)②堆排序(思想和过程)(5)基于“归并”思想的排序方法二路归并排序(思想、过程)(6)各种常用内部排序算法的特点及应用三、参考书目1.数据结构(用面向对象方法与C++语言描述)(第2版).殷人昆主编.北京:清华大学出版社.2007.62.数据结构(C语言版).严蔚敏、吴伟民编著.北京:清华大学出版社.2007。
数据结构(C语言版)_第7章 图及其应用
实现代码详见教材P208
7.4 图的遍历
图的遍历是对具有图状结构的数据线性化的过程。从图中任 一顶点出发,访问输出图中各个顶点,并且使每个顶点仅被访 问一次,这样得到顶点的一个线性序列,这一过程叫做图的遍 历。
图的遍历是个很重要的算法,图的连通性和拓扑排序等算法 都是以图的遍历算法为基础的。
V1
V1
V2
V3
V2
V3
V4
V4
V5
图9.1(a)
图7-2 图的逻辑结构示意图
7.2.2 图的相关术语
1.有向图与无向图 2.完全图 (1)有向完全图 (2)无向完全图 3.顶点的度 4.路径、路径长度、回路、简单路径 5.子图 6.连通、连通图、连通分量 7.边的权和网 8.生成树
2. while(U≠V) { (u,v)=min(wuv;u∈U,v∈V-U); U=U+{v}; T=T+{(u,v)}; }
3.结束
7.5.1 普里姆(prim)算法
【例7-10】采用Prim方法从顶点v1出发构造图7-11中网所对 应的最小生成树。
构造过程如图7-12所示。
16
V1
V1
V2
7.4.2 广度优先遍历
【例7-9】对于图7-10所示的有向图G4,写出从顶点A出发 进行广度优先遍历的过程。
访问过程如下:首先访问起始顶点A,再访问与A相邻的未被 访问过的顶点E、F,再依次访问与E、F相邻未被访问过的顶 点D、C,最后访问与D相邻的未被访问过的顶点B。由此得到 的搜索序列AEFDCB。此时所有顶点均已访问过, 遍历过程结束。
【例7-1】有向图G1的逻辑结构为:G1=(V1,E1) V1={v1,v2,v3,v4},E1={<v1,v2>,<v2,v3>,<v2,v4>,<v3,v4>,<v4,v1>,<v4,v3>}
邻接表的深度遍历
邻接表的深度遍历邻接表是一种表示图的数据结构,深度遍历是一种图遍历的算法。
下面是邻接表的深度遍历的一般步骤:1.初始化:建立一个布尔类型的数组,用于标记节点是否已经被访问。
2.选择起始节点:从图中选择一个未被访问的节点作为起始节点。
3.深度优先遍历:对于选定的起始节点,进行深度优先遍历。
具体步骤如下:•将当前节点标记为已访问。
•访问当前节点,并执行相应的操作。
•对于当前节点的所有未访问邻接节点,递归调用深度遍历函数。
4.迭代:重复步骤3,直到所有节点都被访问。
下面是一个深度遍历的伪代码示例,假设图用邻接表表示:# 定义图的邻接表表示graph = {'A': ['B', 'C'],'B': ['A', 'D', 'E'],'C': ['A', 'F', 'G'],'D': ['B'],'E': ['B', 'H'],'F': ['C'],'G': ['C'],'H': ['E']}# 定义深度遍历函数def dfs(node, visited):if node not in visited:print(node)visited.add(node)for neighbor in graph[node]:dfs(neighbor, visited)# 初始化已访问节点的集合visited_set = set()# 选择起始节点start_node = 'A'# 调用深度遍历函数dfs(start_node, visited_set)这个示例中,图用字典表示,每个节点对应一个键,对应的值是一个列表,包含与该节点邻接的节点。
Java实现无向图的建立与遍历
Java实现⽆向图的建⽴与遍历⼀、基于邻接矩阵表⽰法的⽆向图 邻接矩阵是⼀种利⽤⼀维数组记录点集信息、⼆维数组记录边集信息来表⽰图的表⽰法,因此我们可以将图抽象成⼀个类,点集信息和边集信息抽象成类的属性,就可以在Java中描述出来,代码如下:1class AMGraph{23private String[] vexs = null; //点集信息45private int[][] arcs = null; //边集信息67 } 每⼀个具体的图,就是该类的⼀个实例化对象,因此我们可以在构造函数中实现图的创建,代码如下:1public AMGraph(int vexNum,int arcNum) { //输⼊点的个数和边的个数23this.vexs = new String[vexNum];4this.arcs = new int[vexNum][vexNum];56 System.out.print("请依次输⼊顶点值,以空格隔开:");7 Scanner sc = new Scanner(System.in);8for(int i = 0; i < vexNum; i++) { //根据输⼊建⽴点集9this.vexs[i] = sc.next();10 }1112for(int i = 0; i < vexNum; i++) { //初始化边集13for(int j = 0; j < vexNum; j++) {14this.arcs[i][j] = 0; //0表⽰该位置所对应的两顶点之间没有边15 }16 }1718 start:for(int i = 0; i < arcNum; i++) { //开始建⽴边集1920 sc = new Scanner(System.in);21int vex1Site = 0;22int vex2Site = 0;23 String vex1 = null;24 String vex2 = null;2526 System.out.print("请输⼊第" + (i+1) + "条边所依附的两个顶点,以空格隔开:");27 vex1 = sc.next();28 vex2 = sc.next();29for(int j = 0; j < this.vexs.length; j++) { //查找输⼊的第⼀个顶点的位置30if (this.vexs[j].equals(vex1)) {31 vex1Site = j;32break;33 }34if (j == this.vexs.length - 1) {35 System.out.println("未找到第⼀个顶点,请重新输⼊!");36 i--;37continue start;38 }39 }40for (int j = 0; j < this.vexs.length; j++) { //查找输⼊的第⼆个顶点的位置41if(this.vexs[j].equals(vex2)) {42 vex2Site = j;43break;44 }45if (j == this.vexs.length - 1) {46 System.out.println("未找到第⼆个顶点,请重新输⼊!");47 i--;48continue start;49 }50 }51if(this.arcs[vex1Site][vex2Site] != 0) { //检测该边是否已经输⼊52 System.out.println("该边已存在!");53 i--;54continue start;55 }else {56this.arcs[vex1Site][vex2Site] = 1; //1表⽰该位置所对应的两顶点之间有边57this.arcs[vex2Site][vex1Site] = 1; //对称边也置158 }59 }60 System.out.println("基于邻接矩阵的⽆向图创建成功!");61 sc.close();62 } 创建好图后,我们还要实现图的遍历。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
visited[v]=1; visit(G,v); for(w=FirstAdjvex(G,v);w>=0;w=NextAdjvex(G,v,w))
if(!visited[w]) DFS(G,w); }
void DFSTraverse(ALGraph G) { int v; for(v=0;v<G.vexnum;++v) visited[v]=0; for(v=0;v<G.vexnum;++v) if(!visited[v]) DFS(G,v); }
} int NextAdjvex(ALGraph G,int v,int w) { ArcNode *p;int adjvex; p=G.vertices[v].firstarc; while(p!=NULL) { adjvex=p->adjvex; if(adjvex==w&&p->nextarc!=NULL) return p->nextarc->adjvex; p=p->nextarc; } return -1; }
for(i=0;i<G.vexnum;i++) { scanf("%d",&G.vertices[i].data); G.vertices[i].firstarc=NULL; }
for(k=0;k<G.arcnum;k++) {
printf("请输入边的信息 arc<i,j>:"); scanf("%d,%d",&i,&j); s=(ArcNode*)malloc(sizeof(ArcNode)); s->adjvex=j; s->nextarc=G.vertices[i].firstarc; G.vertices[i].firstarc=s; } }
for(w=FirstAdjvex(G,u); w>=0; w=NextAdjvex(G,u,w))
//w 为 u 未被
访问的元素 if(!visited[w]) { visited[w]=1; visit(G,w); EnQueue(Q,w); } } } }
void vertexOD(ALGraph G) { int i,vertexOD; ArcNode *p; for(i=0;i<G.vexnum;i++) { vertexOD=0; p=G.vertices[i].firstarc; while(p) { ++vertexOD; p=p->nextarc; }
void visit(ALGraph G,int v) { printf("%d",G.vertices[v].data); } int FirstAdjvex(ALGraph G,int v) { if(G.vertices[v].firstarc==NULL) return -1; else return G.vertices[v].firstarc->adjvex;
/*
4
/\
56
/\ /
789
*/
图<stdio.h> #include<malloc.h> #include<stdlib.h> #define MaxVertexNum 20 #define MAX_QUEUE_NUMBER 100 int visited[MaxVertexNum]; //定义图的邻接表 typedef struct ArcNode { int adjvex; struct ArcNode *nextarc; }ArcNode; typedef struct VNode { int data; ArcNode *firstarc; }VNode,AdjList[MaxVertexNum]; typedef struct { AdjList vertices; int vexnum,arcnum; }ALGraph; //定义队列 typedef struct { int *elem; int front, rear; }Queue; //队列的初始化 void InitQueue(Queue &Q) { Q.elem =new int[MAX_QUEUE_NUMBER]; Q.front = Q.rear = 0; } //入队 void EnQueue(Queue &Q, int e) { if((Q.rear + 1)%MAX_QUEUE_NUMBER == Q.front) printf("队列满!\n");
//置空的辅助队列
for(v=0;v<G.vexnum;++v) if(!visited[v])
//v 未被访问
{
visited[v]=1;
visit(G,v);
EnQueue(Q,v);
//v 入队
while(!QueueEmpty(Q))
{
DeQueue(Q,u); //对头元素出队并置为 u
printf(" 顶点%d 的度为%d\n",G.vertices[i].data,vertexOD); } }
void main() { system("color f0"); ALGraph G; CreateALGraph(G); vertexOD(G); printf(" 深度优先遍历该图的输出结果为: \n"); printf("\t"); DFSTraverse(G); printf("\n"); printf(" 广度优先遍历该图的输出结果为: \n"); printf("\t"); BSFTraverse(G); printf("\n"); }
// 深度优先遍历
//按广度优先遍历非递归遍历图 G。使用辅助队列 Q 和访问标志数组 visited void BSFTraverse(ALGraph G) { int v; int u,w; Queue Q;
for(v=0;v<G.vexnum;++v) visited[v]=0;
InitQueue(Q);
else Q.elem[Q.rear ] = e; Q.rear = (Q.rear + 1)%MAX_QUEUE_NUMBER; } //出队 void DeQueue(Queue &Q, int &e) { if(Q.rear == Q.front) printf("队列空!\n"); else e = Q.elem[Q.front]; Q.front = (Q.front+1)%MAX_QUEUE_NUMBER; } //置空 int QueueEmpty(Queue Q) { if(Q.front==Q.rear) return 0; else return 1; }
//创立图 void CreateALGraph(ALGraph &G) { int i,j,k; ArcNode *s; printf("\n"); printf("******************************** 图 的 邻 接 表 存 储 结 构 ******************************"); printf("请输入数据:顶点数,边数:"); scanf("%d,%d",&G.vexnum,&G.arcnum); printf("请输入%d 个顶点的数据:",G.vexnum);