数据结构课程设计题4: 判断有向图的连通性(4)
判断图的连通性

判断图的连通性连通性判断【试题描述】⽆向图,包含n个节点编号1⾄n,初始没有边。
现在逐次向图中添加m条边,你需要在添加边之前判断该两点是否连通。
【输⼊要求】第⼀⾏两个正整数n、m。
接下来m⾏,每⾏两个正整数x、y。
【输出要求】m⾏,每⾏包含⼀个整数0或1,0表⽰添加这条边之前两个点不连通,1表⽰连通。
【输⼊实例】4 51 21 32 34 43 4【输出实例】11【其他说明】n,m<=300000。
【试题分析】⽤并查集做,这是⼀道全世界最⽔的图论题,直接不⽤说,上代码……【代码】#include<iostream>using namespace std;int x,y,f[301001],n,m;int find(int x){if (f[x]==x) return f[x];return f[x]=find(f[x]);}void merge(int v,int u){int t1,t2;t1=find(v);t2=find(u);if(t1!=t2) f[t2]=t1;return ;}inline int read(){int x,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;for(x=ch-'0';isdigit(ch=getchar());x=x*10+ch-'0');return x*f;}inline void write(int x){if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x;int len=0,buf[15];while(x)buf[len++]=x%10,x/=10;for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return;}int main(){n=read(),m=read();for(int i=1;i<=n;i++) f[i]=i;for(int i=1;i<=m;i++){bool w=false;x=read(),y=read();if(find(x)!=find(y)) w=true;//如果x和y的根⼀样那么就可以知道这两条边加进去以后图是连通的 if(w==false)write(1),printf("\n");else write(0),printf("\n");merge(x,y);//把x和y连起来}}。
图的连通性判断(并查集+Bfs+Dfs+Floyd)

图的连通性判断(并查集+Bfs+Dfs+Floyd)有向图的连通性检查共4种⽅法,并查集性能最⾼,代码也短,优先推荐:⼀、并查集#include <bits/stdc++.h>using namespace std;const int N = 1010; //图的最⼤点数量/**共提供两组数据,样例1为不连通⽤例,样例2为连通⽤例样例1:不连通,5号结点为独⽴的5 41 22 33 41 4样例2:连通,不存在独⽴结点5 41 22 33 41 5检测各种算法是否能准确获取结果*/int n; //n个⼈int m; //m个亲戚int p; //询问p对亲戚关系int x, y; //输⼊两个⼈之间的关系int fa[N]; //并查集数组//要深⼊理解这个递归并压缩的过程int find(int x) {if (fa[x] != x)//如果x不是族长,递归找⽗亲,副产品就是找回的结果更新掉⾃⼰的家族信息。
fa[x] = find(fa[x]);//⾮常经典的更新,路径压缩⼤法!//返回族长是谁return fa[x];}//加⼊家族集合中void join(int c1, int c2) {int f1 = find(c1), f2 = find(c2);if (f1 != f2)fa[f1] = f2;//各⾃找家长,如果家长不⼀样,就把C1的族长,认C2的族长为爸爸,C1的族长强烈表⽰不满意}int cnt;int main() {//n个⼈员,m个关系cin >> n >> m;//并查集初始化for (int i = 1; i <= n; i++)fa[i] = i; //⾃⼰是⾃⼰的⽼⼤//录⼊m种关系,使⽤并查集来判断图的连通性for (int i = 1; i <= m; i++) {cin >> x >> y;//加⼊并查集join(x, y);}//图已经搭好了,接下来看它们根节点是否相同,如只有⼀个相同的根节点,则说明是⼀个连通图for (int i = 1; i <= n; i++) if (fa[i] == i)cnt++;if (cnt == 1)printf("图是连通的\n");else printf("图不是连通的\n");return 0;}⼆、dfs#include <bits/stdc++.h>using namespace std;const int N = 1010; //图的最⼤点数量struct Edge { //记录边的终点,边权的结构体int to; //终点int value; //边权};int n, m; //表⽰图中有n个点,m条边vector<Edge> p[N]; //使⽤vector的邻接表/**共提供两组数据,样例1为不连通⽤例,样例2为连通⽤例样例1:不连通,5号结点为独⽴的5 41 22 33 41 4样例2:连通,不存在独⽴结点5 41 22 33 41 5检测各种算法是否能准确获取结果*/bool st[N];int cnt;//深度遍历void dfs(int u) {st[u] = true;cnt++;//多⾛了⼀个结点for (int i = 0; i < p[u].size(); i++) {int x = p[u][i].to;if (!st[x]) dfs(x);}}int main() {//采⽤邻接表建图cin >> n >> m;//m条边for (int i = 1; i <= m; i++) {int u, v;cin >> u >> v;p[u].push_back({v, 1});//因本题不需要权值,默认权值为1 }//利⽤dfs进⾏检查是不是强连通的dfs(1);if (cnt == n) printf("图是连通的\n");else printf("图不是连通的\n");return 0;}三、bfs#include <bits/stdc++.h>using namespace std;const int N = 1010; //图的最⼤点数量struct Edge { //记录边的终点,边权的结构体int to; //终点int value; //边权};int n, m; //表⽰图中有n个点,m条边vector<Edge> p[N]; //使⽤vector的邻接表/**共提供两组数据,样例1为不连通⽤例,样例2为连通⽤例样例1:不连通,5号结点为独⽴的5 41 22 33 41 4样例2:连通,不存在独⽴结点5 41 22 33 41 5检测各种算法是否能准确获取结果*/bool st[N];int cnt;int main() {//采⽤邻接表建图cin >> n >> m;//m条边for (int i = 1; i <= m; i++) {int u, v;cin >> u >> v;p[u].push_back({v, 1});//因本题不需要权值,默认权值为1 }//利⽤bfs进⾏检查是不是强连通的//把1号结点放⼊队列queue<int> q;q.push(1);while (!q.empty()) {int u = q.front();q.pop();st[u] = true;cnt++;for (int i = 0; i < p[u].size(); i++) {int x = p[u][i].to;if (!st[x]) q.push(x);}}if (cnt == n) printf("图是连通的\n");else printf("图不是连通的\n");return 0;}四、floyd#include <bits/stdc++.h>using namespace std;const int N = 1010; //图的最⼤点数量int n, m;/**共提供两组数据,样例1为不连通⽤例,样例2为连通⽤例样例1:不连通,5号结点为独⽴的5 41 22 33 41 4样例2:连通,不存在独⽴结点5 41 22 33 41 5检测各种算法是否能准确获取结果*///⽤floyd来判断起点是否可以达到终点int dis[N][N]; //邻接矩阵void floyd() {for (int k = 1; k <= n; k++)for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++)dis[i][j] = dis[i][j] || (dis[i][k] && dis[k][j]);}int main() {//采⽤邻接矩阵建图cin >> n >> m;//m条边for (int i = 1; i <= m; i++) {int u, v;cin >> u >> v;//双向建边dis[u][v] = 1;dis[v][u] = 1;}//调⽤floydfloyd();for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++)if (!dis[i][j]) {printf("图不是连通的\n");cout << i << " " << j << endl;exit(0);}printf("图是连通的\n");return 0;}。
(4-2)图的连通性

(3)
(4)
(5)
(6)
(7)
欧拉图
设G=<V,E>是连通无向图 欧拉通路:在图G中存在一条通路,经过图G 中每条边一次且仅一次。 欧拉回路:在图G中存在一条回路,经过图 G中每条边一次且仅一次。(能一笔画) 欧拉图:具有欧拉回路的图。
欧拉图的判定定理
定理7-4 无向图G=<V,E>具有欧拉回路,即是 欧拉图的充分必要条件是这个图是连通的,并且 图G中所有结点的度数都是偶数,即都与偶数条 边相连。 定理7-5 无向图G=<V,E>具有欧拉通路的充分 必要条件是图G是连通的,并且图G中恰有两个度 数是奇数的结点或者没有度数是奇数的结点。
v1
e6
e1
v5
e5
e7 e4
v2
e2
v4
e3
v3
通路和回路 给定图G V , E
通路: G中前后相互关联的点边交替序列 w=v0e1v1e2…envn称为连接v0到vn的通路。 W中边的数目K称为通路W的长。 回路:在点边序列v0e1v1e2…envn中,当 v0=vn时称此通路为回路。
图1
图2
哈密尔顿图
设G=<V,E>是连通无向图 图G中存在一条经过图中的每个结点一次且仅
一次的通(回)路,称此通路为哈密顿通(回)路
哈密顿图:具有哈密尔顿回路的图。
目前还没有找到连通无向图具有哈密顿通(回)
路的充分必要条件。
?
课堂思考题:
学习了欧拉图、哈密尔顿图,请总 结他们的区别。
哈密尔顿回路与欧拉回路的区别
连通
连通、一笔
案例3
周游世界问题
1856年,英国数学家哈 密尔顿设计了一个周游世界的 游戏,他在一个正十二面体的 二十个顶点上标上二十个著名 城市的名字,要求游戏者从一 个城市出发,经过每一个城市 一次且仅一次,然后回到出发 点。
图的连通性判断

基于MATLAB的实现,此方法可以知道有几个连通域,并且知道各个顶点的归属。
Branches中显示各个节点的归属,同一行的为同一连通分支中的节点。
其第一列为它的分类数。
例如下图,有五个连通分支,1、2、3在同一个连通分支中。
这是上图的邻接矩阵,同一节点间为0。
Branches中的显示内容,第一列为连通分支数,后边跟着的是给连通分支中的节点。
第一行就表示1、2、3为一个连通分支,4自己在一个连通分支中等等。
function [Branches,numBranch]=Net_Branches(ConnectMatrix)% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% This program is designed to count the calculate connected components in networks.% Usage [Cp_Average, Cp_Nodal] = Net_ClusteringCoefficients(ConnectMatrix,Type)% Input:% ConnectMatrix --- The connect matrix without self-edges.% Output:% Branches --- A matrix, each rows of which represents the% different connected components.% numBranch --- The numbers of connected components in network%% +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ % Refer:% Ulrik Barandes <A faster algorithm for betweennes centrality>% Written by Hu Yong, Nov,2010% E-mail: carrot.hy2010@% based on Matlab 2008a% Version (1.0),Copywrite (c) 2010% Input check-------------------------------------------------------------%[numNode,I] = size(ConnectMatrix);if numNode ~= Ierror('Pls check your connect matrix');end% End check---------------------------------------------------------------%Node = [1:numNode];Branches = [];while any(Node)Quence = find(Node,1); %find a non-zero number in Node setsubField=[]; %one component% start searchwhile ~isempty(Quence)currentNode = Quence(1);Quence(1) = []; %dequeuesubField=[subField,currentNode];Node(currentNode)=0;neighborNode=find(ConnectMatrix(currentNode,:));for i=neighborNodeif Node(i) ~= 0 %first foundQuence=[Quence,i];Node(i)=0;endendendsubField = [subField,zeros(1,numNode-length(subField))];Branches = [Branches;subField]; %saveendnumBranch = size(Branches,1);。
数据结构判断题

一、判断题 (每题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. 在一个顺序存储的循环队列中, 队头指针指向队头元素的后一个位置。
有向图的连通性

推论11.2
有向图G是单侧连通图当且仅当G中存在经过每个顶点至少一次的通路。
推论11.3
简单有向图中的每个结点和每条边恰好位于一个弱分图中。
小结
理解有向图的连通性、单侧连通、强连通和弱连通及它们的性质。关于有向图的连 通性 的思维形式注记图如下图所示。
至少有一个结点
1 11. 3有向图的连通性
定义1L5
设G二<V, E>是有向图,巧,Vj V如果从H到Vj存在一条有向路径,则称vt到Vj 可达,记为 Vj T V"
规定:Vi/e K 匕t Vj.
单侧连通:在有向图G=<V, E〉中,若对于任意结点偶对,至少有一个结点到另一 个结点
是可达的。
强连通:在有向图G二<V, E>中,若对于任意结点偶对都是相互可达的。
-小结
图 回路 路径 存在路
无向图
有向图
可±
扩大路径法
k(G)公(G)
割点 点连通度、边连通度
割边
有
1 强连通 虽分图' 弱连
向
1 通 弱分图 单侧连通「单
连
通
侧分图
图
ቤተ መጻሕፍቲ ባይዱ
定理11.5
在有向图G = <V, E〉中,它的每一个结点位于且仅位于一个强分图内。
e 证:(1 )设v V,令S是G中所有与v相互可达的结点的集合,当然S也包括v,而S 与顶
点在S中的边集构成的G'是G中的一个强分图,因此G中的每一个结点必位于-个强分图 中。 (2)设v位于两个不同的强分图Gi和G2中,因为Gi中的每一个结点与v可达,而v 与G2中的每一个结点也相互可达,Gi中的每一个结点与G2中的每一个结点通过v都 相 互可达,这与题设Gi为强分图矛盾,故G的每一个结点只能位于一个强分图中。
数据结构试题(含答案)讲解
数据结构试题一、单选题1、在数据结构的讨论中把数据结构从逻辑上分为(C )A 内部结构与外部结构B 静态结构与动态结构C 线性结构与非线性结构D 紧凑结构与非紧凑结构。
2、采用线性链表表示一个向量时,要求占用的存储空间地址(D )A 必须是连续的B 部分地址必须是连续的C 一定是不连续的D 可连续可不连续3、采用顺序搜索方法查找长度为n的顺序表时,搜索成功的平均搜索长度为( D )。
A nB n/2C (n-1)/2D (n+1)/24、在一个单链表中,若q结点是p结点的前驱结点,若在q与p之间插入结点s,则执行( D )。
A s→link = p→link;p→link = s;B p→link = s; s→link = q;C p→link = s→link;s→link = p;D q→link = s;s→link = p;5、如果想在4092个数据中只需要选择其中最小的5个,采用( C )方法最好。
A 起泡排序B 堆排序C 锦标赛排序D 快速排序6、设有两个串t和p,求p在t中首次出现的位置的运算叫做( B )。
A 求子串B 模式匹配C 串替换D 串连接7、在数组A中,每一个数组元素A[i][j]占用3个存储字,行下标i从1到8,列下标j从1到10。
所有数组元素相继存放于一个连续的存储空间中,则存放该数组至少需要的存储字数是( C )。
A 80B 100C 240D 2708、将一个递归算法改为对应的非递归算法时,通常需要使用( A )。
A 栈B 队列C 循环队列D 优先队列9、一个队列的进队列顺序是1, 2, 3, 4,则出队列顺序为( C )。
10、在循环队列中用数组A[0..m-1] 存放队列元素,其队头和队尾指针分别为front和rear,则当前队列中的元素个数是( D )。
A ( front - rear + 1) % mB ( rear - front + 1) % mC ( front - rear + m) % mD ( rear - front + m) % m11、一个数组元素a[i]与( A )的表示等价。
数据结构课设有向图强连通分量求解
数据结构课设有向图强连通分量求解数据结构课设:有向图强连通分量求解一、引言有向图是图论中的一种重要概念,强连通分量是有向图中的一个子图,其中任意两个顶点之间都存在一条有向路径。
在数据结构课设中,我们需要实现一个算法,能够求解给定有向图的强连通分量。
二、问题描述给定一个有向图G=(V,E),其中V表示顶点的集合,E表示边的集合。
我们需要设计一个算法,能够找出图G中的所有强连通分量,并将其输出。
三、算法设计为了解决这个问题,我们可以使用Tarjan算法,该算法是一种经典的强连通分量求解算法。
下面是Tarjan算法的详细步骤:1. 初始化步骤:- 创建一个空栈S,用于存储访问过的顶点。
- 创建一个整数数组dfn和low,用于记录每个顶点的访问次序和最早访问到的祖先顶点的次序。
- 创建一个布尔数组inStack,用于标记顶点是否在栈中。
- 创建一个整数变量index,用于记录当前访问的次序。
2. 递归搜索步骤:- 遍历图中的每个顶点v,若v未被访问,则执行递归搜索函数Tarjan(v)。
- 在Tarjan(v)函数中,首先将v入栈,并标记v在栈中。
- 然后将dfn[v]和low[v]均设为index的值,并将index加1。
- 对于v的每个邻接顶点u,若u未被访问,则执行递归搜索函数Tarjan(u)。
- 在递归返回后,更新low[v]的值为v的所有邻接顶点u的low值的最小值。
- 若dfn[v]等于low[v],则说明v是一个强连通分量的根节点,将栈中的顶点依次出栈,直到v为止,并将这些顶点构成一个强连通分量。
3. 输出结果:- 将找到的所有强连通分量输出。
四、算法分析Tarjan算法的时间复杂度为O(V+E),其中V为顶点的数量,E为边的数量。
该算法通过深度优先搜索的方式遍历图中的每个顶点,同时使用dfn和low数组记录顶点的访问次序和最早访问到的祖先顶点的次序。
通过比较dfn和low数组的值,可以确定强连通分量的根节点,并将其输出。
有向图的连通性
第十一章图的连通性11.3有向图的连通性定义11.5例图:上图给出了含3个结点的强连通图、单侧连通图、弱连通图。
定义11.6在简单有向图G中,具有强连通性质的极大子图G′称为G的强分图(或强连通分量);具有单侧连通性质的极大子图G”称为G的单侧分图(或单侧连通分量);具有弱连通性质的极大子图G’’’称为G的弱分图(或弱连通分量)。
定理11.4一个有向图是强连通的,当且仅当G中存在经过每个顶点至少一次的回路。
证:先证充分性,再证必要性。
(1)充分性:如果图中有一条回路,它至少包含每个结点一次,则G中任意两个结点都是互相可达的,故G是强连通的。
(2)必要性:若有向图G是强连通的,则任意两个结点都是可达的,故必可作一回路经过图中的所有各点。
若不然则必有一回路不包含某一结点v,而且,v与回路上的各结点不是互相可达,与强连通的条件矛盾。
证毕。
定理11.5在有向图G=<V, E>中,它的每一个结点位于且仅位于一个强分图内。
证:(1)设v V,令S是G中所有与v相互可达的结点的集合,当然S也包括v,而S 与顶点在S中的边集构成的G’是G中的一个强分图,因此G中的每一个结点必位于一个强分图中。
(2)设v位于两个不同的强分图G1和G2中,因为G1中的每一个结点与v可达,而v 与G2中的每一个结点也相互可达,G1中的每一个结点与G2中的每一个结点通过v都相互可达,这与题设G1为强分图矛盾,故G的每一个结点只能位于一个强分图中。
推论11.2有向图G是单侧连通图当且仅当G中存在经过每个顶点至少一次的通路。
推论11.3简单有向图中的每个结点和每条边恰好位于一个弱分图中。
理解有向图的连通性、单侧连通、强连通和弱连通及它们的性质。
关于有向图的连通性的思维形式注记图如下图所示。
有向图可达单侧连通强连通无向图弱连通至少有一个结点到另一个结点任意结点略去方向连通充要条件图始点终点连通无向图有向图无向连通图有向连通图割点点割集割边边割集点连通度、边连通度弱分图弱连通强分图强连通回路路径存在路连通分支可达扩大路径法k(G)≤λ(G)单侧连通单侧分图。
数据结构与算法设计与分析考核试卷
8.在冒泡排序中,每一趟排序都能确定一个元素的最终位置。()
答案:______
9. Prim算法和Kruskal算法都可以用来求解最小生成树问题,但Prim算法总是从某一顶点开始,而Kruskal算法总是从某一权值最小的边开始。()
答案:______
10.在一个递归算法中,如果递归调用不是算法的最后一个操作,那么这种递归称为尾递归。()
B.邻接表适合表示稀疏图
C.邻接多重表适合表示无向图
D.邻接表和邻接多重表适合表示有向图
14.以下哪些算法属于分治算法?()
A.快速排序
B.归并排序
C.二分查找
D.动态规划
15.以下哪些情况下,动态规划比贪心算法更适合解决问题?()
A.存在重叠子问题
B.问题具有最优子结构
C.需要考虑所有可能的选择
D.问题可以通过局部最优达到全局最优
C.插入一个节点
D.查找某个节点
5.以下哪些算法可以用于解决最小生成树问题?()
A. Kruskal算法
B. Prim算法
C. Dijkstra算法
D. Bellman-Ford算法
6.以下哪些数据结构可以用来实现堆?()
A.数组
B.链表
C.栈
D.队列
7.关于图的深度优先遍历和广度优先遍历,以下哪些说法是正确的?()
________________________________
2.动态规划算法通常用于解决最优化问题,请阐述动态规划算法的三个基本要素,并给出一个动态规划问题的实例。
________________________________
________________________________
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include<iostream>#include<conio.h>#include<stdlib.h>using namespace std;const int MaxSize=20; //×î¶à¼¸¸ö½Úµãint i,j,k;struct ArcNode //±ß±í½Úµã{int adjivex;ArcNode * next;};struct VertexNode //¶¥µã±í½Úµã{int data;ArcNode * firstedge;ArcNode * nfirstedge;} ;struct ArcNode* s; //±ß±í½Úµã¹¤×÷Ö¸Õëclass Graph{public:Graph(int data[],int v,int a); //³õʼ»¯Í¼±í~Graph(); //ɾ³ýͼ±ívoid PrintGraph(); //ͼµÄÏÔʾvoid InsertArc(int v1,int v2);void InsertArc(int n); //²åÈë±ßvoid InsertVertex(int v,int data);void InsertVertex(int data); //²åÈë½Úµãbool DeleteArc(int v1,int v2); //ɾ³ý±ßvoid DeleteVertex(); //ɾ³ý½Úµãbool Isconect(); //Éî¶ÈÓÅÏȱéÀúÓëÁ¬Í¨ÐÔµÄÅж¨ void Scprint(); //Ç¿Á¬Í¨·ÖÁ¿void DFS(int v,int a[]);void DFS1(int v,int a[],int b[]);void NDFS(int i,int visited[],int b[]);void scPrint(int b[]);void BFS(int v,int visisted[]);void BFS(); //ȫͼ¹ã¶ÈÓÅÏȱéÀúprivate:VertexNode adjlist[MaxSize];int vertexNum, arcNum;} ;////////////////////////////////////////////////////////////////// ////////void Graph::InsertVertex(int v,int data){adjlist[v].data=data ;adjlist[v].firstedge=NULL ;adjlist[v].nfirstedge =NULL ;}void Graph::InsertArc(int v1,int v2){s=new ArcNode; s->adjivex=v2;s->next=adjlist[v1].firstedge;adjlist[v1].firstedge=s;s=new ArcNode; s->adjivex=v1;s->next=adjlist[v2].nfirstedge;adjlist[v2].nfirstedge=s;}Graph::Graph(int data[],int v,int a){if(a>v*v-v){/////+++++++rong chuo}vertexNum=v ; arcNum=a ;cout<<"Ä㽨Á¢ÁËÒ»¸ö"<<v<<"½Úµã"<<a<<"Ìõ±ßµÄͼ"<<endl;for(int w=0; w<vertexNum; w++) //½Úµã³õʼ»¯ InsertVertex(w,data[w]) ;for(int v1,v2,w=0;w<arcNum;w++) //±ßµÃ³õʼ»¯ {cout<<"ÇëÊäÈëµÚ"<<w+1<<"Ìõ±ß £º ";cin>>v1>>v2;////////////+++++++++rongcuoif(v1>=vertexNum||v1<0||v2>=vertexNum||v2<0){cout<<"´íÎó "; w--;continue;}InsertArc(v1,v2);}}Graph::~Graph(){for(i=0; i<vertexNum; i++){while(adjlist[i].firstedge!=NULL){s=adjlist[i].firstedge;adjlist[i].firstedge= (adjlist[i].firstedge)->next;delete s;}while(adjlist[i].nfirstedge!=NULL){s=adjlist[i].nfirstedge;adjlist[i].nfirstedge= (adjlist[i].nfirstedge)->next;delete s;}}}void Graph::InsertVertex(int data){vertexNum++;InsertVertex(vertexNum-1,data);}void Graph::InsertArc(int n){arcNum+=n;int v1,v2;for(int w=0;w<n;w++){cout<<"ÇëÊäÈëµÚ"<<w+1<<"Ìõ±ß £º ";cin>>v1>>v2;InsertArc( v1, v2);}}void Graph::BFS(int v,int visisted[]) //¹ã¶ÈÓÅÏȱéÀú {int Q[MaxSize],front,rear;front=rear=-1;int w ;struct ArcNode* p;cout<<v<<": "<<adjlist[v].data<<"\t";visisted[v]=1;Q[++rear]=v;while(front!=rear){v=Q[++front];p=adjlist[v].firstedge;while(p!=NULL){w=p->adjivex;if(visisted[w]==0){cout<<w<<": "<<adjlist[w].data<<"\t";visisted[w]=1;Q[++rear]=j;}p=p->next;}}}void Graph::BFS(){cout<<"¹ã¶ÈÓÅÏȱéÀú £º ";int n=vertexNum;int* visited=new int[n];for(int w=0;w<n;w++){visited[w]=0;}for(int w=0;w<n;w++){if(visited[w]==0){BFS(w,visited);}}delete []visited;cout<<endl;}bool Graph::DeleteArc(int v1,int v2){s=adjlist[v1].firstedge;if(s!=NULL){if(s->adjivex==v2){adjlist[v1].firstedge=s->next;delete s;arcNum--;}else{while(s->next!=NULL){if(s->next->adjivex==v2){struct ArcNode* q;q=s->next;s->next=q->next;delete q;arcNum--;break;}s=s->next;}}}s=adjlist[v2].nfirstedge;if(s!=NULL){if(s->adjivex==v1){adjlist[v2].nfirstedge=s->next;delete s;return true;}else{while(s->next!=NULL){if(s->next->adjivex==v1){struct ArcNode* q;q=s->next;s->next=q->next;delete q;return true;}s=s->next;}}}return false;}void Graph::DeleteVertex(){for(int w=0;w<vertexNum-1;w++){DeleteArc(w,vertexNum-1);DeleteArc(vertexNum-1,w);}vertexNum--;}void Graph::PrintGraph(){cout<<"\t"<<vertexNum<<" ¸ö½Úµã "<<arcNum<<" Ìõ±ß"<<endl;for(i=0; i<vertexNum; i++){cout<<i<<"; "<<adjlist[i].data<<"\t" ;}cout<<endl;for(i=0; i<vertexNum; i++){s=adjlist[i].firstedge ;while(s!=NULL){cout<<i<<"-->"<<s->adjivex<<endl;s=s->next ;}}cout<<"ÄæÏòͼ"<<endl;for(i=0; i<vertexNum; i++){s=adjlist[i].nfirstedge ;while(s!=NULL){cout<<i<<"-->"<<s->adjivex<<endl;s=s->next ;}}}bool Graph::Isconect(){cout<<"Éî¶ÈÓÅÏȱéÀúÓëÁ¬Í¨ÐÔÅж¨ £º"<<endl;int n=vertexNum;int* visited=new int[n];for(i=0;i<n;i++){visited[i]=0;}for(i=0,j=0;i<n;i++){if(visited[i]==0){DFS(i,visited);j++;}}delete []visited;cout<<endl;if(j>1){cout<<"²»ÊÇÁ¬Í¨Í¼"<<endl;return true;}else{cout<<"ÊÇÁ¬Í¨Í¼"<<endl;return false;}}void Graph::DFS(int v,int visited[]){struct ArcNode* p;cout<<v<<"£º "<<adjlist[v].data<<"\t";visited[v]=1;p=adjlist[v].firstedge;while(p!=NULL){k=p->adjivex;if(visited[k]==0) DFS(k,visited);p=p->next;}p=adjlist[v].nfirstedge;while(p!=NULL){k=p->adjivex;if(visited[k]==0) DFS(k,visited);p=p->next;}}void Graph::DFS1(int v,int visited[],int a[]) {struct ArcNode* p;visited[v]=1;p=adjlist[v].firstedge;while(p!=NULL){k=p->adjivex;if(visited[k]==0) DFS1(k,visited,a);p=p->next;}a[j++]=v;}void Graph::NDFS (int v,int visited[],int b[]) {struct ArcNode* p;visited[v]=1;p=adjlist[v].nfirstedge;while(p!=NULL){k=p->adjivex;if(visited[k]==0) NDFS(k,visited,b);p=p->next;}b[j++]=v;}void Graph::scPrint(int b[]){cout<<"Ç¿Á¬Í¨·ÖÁ¿°ü £º"<<endl;cout<<"½ÚµãºÅ £º";for(i=0;i<j;i++){cout<<b[i]<<" ";}cout<<endl;cout<<"±ß £º"<<endl;for(i=0;i<j;i++){s=adjlist[b[i]].firstedge;while(s!=NULL){for(int t=0;t<j;t++){if(s->adjivex==b[t]){cout<<b[i]<<"-->"<<b[t]<<"\t"<<endl;} }s=s->next;}}cout<<endl;}void Graph::Scprint(){int n=vertexNum ;int* a=new int[n];int* visited=new int[n];int* b=new int[n];cout<<"Ç¿Á¬Í¨Í¼·ÖÁ¿ £º"<<endl;for(i=0;i<n;i++){b[i]=-1;a[i]=-1;visited[i]=0;}for(i=0,j=0;i<n;i++){if(visited[i]==0){DFS1(i,visited,a);}}for(i=0;i<n;i++){visited[i]=0;}for(int w=n-1;w>=0;w--){j=0;//cout<<w;//cout<<a[w];if(visited[a[w]]==0){NDFS(a[w],visited,b);scPrint(b);}}delete []a;delete []visited;}///////////////////////////////////////////////////////////////// void printinfo(){cout<<"ÃüÁîÌáʾ£º"<<endl;cout<<"1 ÏÔʾͼÐÅÏ¢\t2 ²åÈë½Úµã\t3 ɾ³ý½Úµã\t4 ²åÈë±ß\t5 ɾ³ý±ß"<<endl;cout<<"6 ¹ã¶È±éÀú\t7 Á¬Í¨ÐÔ\t8 Ç¿Á¬Í¨·ÖÁ¿\t9 Ë¢ÐÂ\t esc Í˳ö"<<endl;}int main(){int a[20]={1,2,3,4,5,6,7,8,9,012,12,13,14,15,16,12,234,46,78};int v,a1;cout<<"ÊäÈë½ÚµãÊýºÍ±ßÊý £º";cin>>v>>a1;Graph mp(a,v,a1);mp.PrintGraph();printinfo();char m=0;while( m!=27){cout<<"ÇëÊäÈëÖ¸Áî"<<endl;m=getch();switch(m){case '1':mp.PrintGraph();break;case '2':cout<<"ÇëÊäÈëÊý¾Ý £º ";int data; cin>>data;mp.InsertVertex(data);break;case '3':mp.DeleteVertex();break;case '4':cout<<"²åÈ뼸Ìõ±ß£º";int n;cin>>n;mp.InsertArc (n);break;case '5':cout<<"ɾ³ý±ß ";int v1,v2;cin>>v1>>v2;mp.DeleteArc (v1,v2);break;case '6':mp.BFS();break;case '7':mp.Isconect();break;case '8':mp.Scprint();break;case '9':system("cls");mp.PrintGraph();printinfo();break;default:;}}return 0;}。