《数据结构》实验报告
               
程序名: 图的生成和连通性判断                                              
一、上机实验的问题和要求:
1、设计一个程序生成图并判断该图是否连通,如不连通,输出其联通分量个数。
2、连通OR不连通
描述:给定一个无向图,一共n个点,m条边。请编写一个程序实现两种操作:
D x y从原图中删除连接x,y节点的边。
Q x y询问x,y节点是否连通
输入:
第一行两个数n,m(5<=n<=40000,1<=m<=100000)
接下来m行,每行一对整数x y(x,y<=n),表示x,y之间有边相连。保证没有重复的边。
接下来一行一个整数q(q<=1000003
以下q行每行一种操作,保证不会有非法删除。 输出 
按询问次序输出所有Q操作的回答,连通的回答C,不连通的回答D
样例输入:
3 3
1 2
1 3
2 3
5
Q 1 2
D 1 2
Q 1 2
D 3 2
Q 1 2

样例输出
CCD


二、程序设计的基本思想,原理和算法描述:
(包括程序的结构,数据结构,输入/输出设计,符号名说明等)







三、源程序及注释(将所有代码直接复制于此):
#ifndef MGraph_H//避免包含MGraph.h头文件
#define MGraph_H
const int MaxSize = 10;//图中最多顶点个数//以下是类MGraph的声明
extern int visited[MaxSize];
template<class T>
class MGraph
{
public:
	MGraph(T a[], int n, int e);//构造函数,建立n个顶点e条边的图
	  ~MGraph() {};//析构函数为空
	  void DFSTraverse(int v);//深度优先遍历图
	  void BFSTraverse(int v);//广度优先遍历图
	  void judge();
	  void cancel();
	  void degree();
private:
	T vertex[MaxSize];
	int arc[MaxSize][MaxSize];
	int vertexNum;
	int	arcNum;
};

#endif
#include <iostream>
using namespace std;
#include"MGraph.h"
template<class T>
MGraph<T>::MGraph(T a[], int n, int e)//构造函数,建立n个顶点e条边的图
{
	int i, j, k;
	vertexNum = n;
	arcNum = e;
	for (i = 0; i < vertexNum; i++)
		vertex[i] = a[i];
	for (i = 0; i < vertexNum; i++)
		for (j = 0; j < vertexNum; j++)
			arc[i][j] = 0;
	for (k = 0; k < arcNum; k++)
	{
		cout << "请输入边的两个顶点的序号";
		cin >> i >> j;
		arc[i][j] = 1;
		arc[j][i] = 1;

	}
}
template<class T>
void MGraph<T>::DFSTraverse(int v)//深度优先遍历图

{
	cout << vertex[v]; visited[v] = 1;
	for (int j = 0; j < vertexNum; j++)
		if (arc[v][j] == 1 && visited[j] == 0)
			DFSTraverse(j);

}
template<class T>
void  MGraph<T>::BFSTraverse(int v)//广度优先遍历图
{
	int Q[MaxSize];
	int front = -1, rear = -1;
	cout << vertex[v]; visited[v] = 1; Q[++rear] = v;
	while (front != rear)
	{
		v = Q[++front];
		for(int j=0;j<vertexNum;j++)
			if (arc[v][j] == 1 && visited[j] == 0)
			{
				cout << vertex[j]; visited[j] = 1; Q[++rear] = j;
			}
	}
}
template<class T>
void MGraph<T>::judge()
{
	int i, j;
	cout << "请输入查找的两个顶点的序号:";
	cin >> i >> j;
	if (arc[i][j])
		cout << "两个顶点邻接" << endl;
	else cout << "两个顶点不邻接" << endl;
}
template <class T>
void MGraph<T>::cancel()
{
	int i, j;
	cout << "请输入你要删除的邻接顶点的序号";
	cin >> i >> j;
	arc[i][j] = arc[j][i] =0;
}
template <class T>
void MGraph<T>::degree() {
	int v;
	int count = 0;
		cout << "请输入要查询的顶点的序号:" << endl;
	cin >> v;
	for (int j = 0; j < vertexNum; j++)
	{
		if (arc[v][j])
			count++;

	}
	cout << "第" << v << "个顶点的度数是:" << endl;
}
#include<iostream>
using namespace std;
#include"MGraph.cpp"
int visited[MaxSize] = { 0 };
int main()
{
	//char ch[] = { 'A','B','C','D','E' };
	//MGraph<char>MG(ch, 5, 6);
	char ch[MaxSize];
	int x, y, n;
	cout << "请输入顶点个数" << endl;
	cin >> x;
	cout << "请输入" << x << "个字符" << endl;
	for(int i=0;i<x;i++)
	cin >> ch[i];
	cout << "请输入邻接边条数" << endl;
	cin >> y;
	MGraph<char> MG(ch, x, y);
	cout << "请输入以下你想完成操作的序号" << endl;
	cout << "1.深度优先遍历输出" << endl << "2.广度优先遍历输出" << endl
		<< "3.查询连接" << endl << "4.删除连接" << endl << "查询度数" << endl;
	cin >> n;
	char sign = 'y';
	while (sign == 'y' || sign== 'Y')
	{
		switch (n)
		{
		case 1:
			for (int i = 0; i < MaxSize; i++)
				visited[i] = 0;
			cout << "深度优先遍历的序列是:";
			MG.DFSTraverse(0);
			cout << endl;
			break;
		case 2:
			for (int i = 0; i < MaxSize; i++)
				visited[i] = 0;
			cout << "广度优先遍历的序列是:";
			MG.BFSTraverse(0);
			cout << endl;
			break;
		case 3:
			MG.judge(); break;
		case 4:
			MG.cancel(); break;
		case 5:
			MG.degree(); break;
		default:break;
		}
		cout << "是否还要做其他操作?(Y/N)" << endl;
		cin >> sign;
	}return 0;
	
}
#ifndef ALGraph_H
#define ALGraph_H
using namespace std;
const int MaxSize = 10;
extern int visited[MaxSize];
struct ArcNode
{
	int adjvex;
	ArcNode* next;
};
template <class T>
struct VertexNode
{
	T vertex;
	ArcNode* firstEdge;
};
template<class T>
class ALGraph {
public:
	ALGraph(T a[], int n, int e);
	~ALGraph();
	void DFSTraverse(int v);
	void BFSTraverse(int v);
	void judge();
	void cancel();
	void degree();
private:
	VertexNode<T>adjlist[MaxSize];
	int vertexNum, arcNum;

};

#endif
#include<iostream>
using namespace std;
#include"ALGraph.h"
template<class T>
ALGraph<T>::ALGraph(T a[], int n, int e)
{
	ArcNode* s;
	int i, j, k;
	vertexNum = n; arcNum = e;
	for (i = 0; i < vertexNum; i++)
	{
		adjlist[i].vertex = a[i];
		adjlist[i].firstEdge = NULL;

	}
	for (k = 0; k < arcNum; k++)
	{
		cout << "请输入边的两个顶点符号:";
		cin >> i >> j;
		s = new ArcNode; s->adjvex = j;
		s->next = adjlist[i].firstEdge = s;
	}
}
template<class T>
ALGraph<T>::~ALGraph()
{
	ArcNode* p = NULL;
	for (int i = 0; i < vertexNum; i++)
	{
		p = adjlist[i].firstEdge;
		while (p != NULL)
		{
			adjlist[i].firstEdge = p->next;
			delete p;
			p = adjlist[i].firstEdge;
		}
	}
}
template<class T>
void  ALGraph<T>:: DFSTraverse(int v)
{
	ArcNode* p = NULL; int j;
	cout << adjlist[v].vertex;
	visited[v] = 1;
	p = adjlist[v].firstEdge;
	while (p != NULL)
	{
		j = p->adjvex;
		if (visited[j] == 0)DFSTraverse(j);
		p = p->next;
	}
}
template<class T>
void  ALGraph<T>:: BFSTraverse(int v)
{
	int Q[MaxSize];
	int front = -1, rear = -1;
	ArcNode* p = NULL;
	cout << adjlist[v].vertex; visited[v] = 1; Q[++rear] = v;
	while (p != NULL)
	{

		int j = p->adjvex;
		if (visited[j] == 0)
		{
			cout << adjlist[j].vertex;
			visited[j] = 1; Q[++rear] = j;
		}
		p = p->next;
	}
}
template<class T>
void  ALGraph<T>::judge()
{
	int i,j;
cin>>i>>j;
	int sign= 0;
	ArcNode * p = NULL;
	p= adjlist[i].firstEdge;
   while(p!= NULL)
	{
	   if (p->adjvex == j)sign = 1;
		p= p->next;
	}
	if(sign==1)cout << "邻接" << endl;
	else cout<< "不邻接" << endl;
}
template<class T>
void  ALGraph<T>::cancel()
{
	int i, j;
cout << "两个顶点序号:";
cin>> i>> j;
	ArcNode * p= NULL; 
	p= adjlist[i].firstEdge;
	while(p!= NULL)
	{
		if(p->next->adjvex== j) { p->next= p->next->next;delete p->next; }
		p= p->next;
	}
}
template<class T>
void  ALGraph<T>::degree()
{
	int x;
	cout<<"输入你要查询度的顶点的序号";
	cin>>x;
	ArcNode* p = NULL;
	p= adjlist[x].firstEdge;
int count  = 0;
	while(p!= NULL)
	{
		count++;
		p= p->next;
	}
	cout<< count<< endl;
}

#include"ALGraph.cpp"
#include<iostream>
using namespace std;
int visited[MaxSize];
int main()
{
	//char ch[] = { 'A','B','C','D','E' };
	int i;
	//ALGraph<char>ALG(ch, 5, 6);
	char ch[MaxSize];
	int x, y, n;
	cout << "请输入顶点个数"<<endl;
		cin >> x;
		cout<< "输入" << x<< "个字符" << endl;
		for(i= 0;i< x;i++)
			cin>> ch[i];
		cout<< "输入邻接边条数" << endl;
		cin>> y;
		ALGraph<char>MG(ch, x, y);
		cout<< "输入数字选择你想完成的操作" << endl;
		cout<< "1.深度优先级输出" << endl;
		cout<< "2.广度优先级输出" << endl;
		cout <<"3.查询连接" << endl;
		cout<< "4.删除连接" << endl;
		cout<< "5.查询度数" << endl;
		cin>> n;
		char sign= 'y';
		while(sign== 'y' || sign== 'Y')
		{
			switch(n)
			{
			case1:
				for(int j= 0;j< MaxSize;j++)visited[j]= 0;
				cout<< "深度优先级遍历输出:" << endl;
				MG.DFSTraverse(0);cout<< endl;
				break;
			case2:
				for(int j= 0; j< MaxSize;j++)visited[j] = 0;
				cout<< "广度优先级遍历输出:" << endl;
				MG.BFSTraverse(0);cout<< endl;
			case3:
				MG.judge();cout<< endl;break;
			case4:
				MG.cancel();cout<< endl;break;
			case5:
				MG.degree();cout<< endl;break;
			}
			cout<< "你是否还想做其他的操作(Y OR N)" << endl;
			cin>> sign;
		}
		return 0;
}



#pragma once
#include<iostream>
#include<stdlib.h>
using namespace std;

const int MaxSize = 10;
typedef struct ArcNode
{
	int adjvex;        //该弧所指向的顶点的位置
	struct ArcNode* nextarc;//指向下一条弧的指针
	//InfoType *info;
}ArcNode;
typedef struct VertexNode
{
	char data;         //顶点信息
	ArcNode* firstarc;  //指向第一条依附该顶点的弧的指针
}VNode, AdjList[MaxSize];


template<class T>
class ALGraph {
public:
	ALGraph();
	ALGraph(T a[], int n, int e);
	~ALGraph();
	void DFSTraverse(int v);
	void BFSTraverse(int v);
	void judge();
	void cancel();
	void degree();
int vertexNum, arcNum;
AdjList vertices;
private:
	VertexNode<T>adjlist[MaxSize];

};
#include"连.h"
using namespace std;
int visited[MaxSize];
template<class T>
ALGraph<T>::ALGraph(T a[], int n, int e)
{
	ArcNode* s;
	int i, j, k;
	vertexNum = n; arcNum = e;
	for (i = 0; i < vertexNum; i++)
	{
		adjlist[i].vertex = a[i];
		adjlist[i].firstEdge = NULL;

	}
	for (k = 0; k < arcNum; k++)
	{
		cout << "请输入边的两个顶点符号:";
		cin >> i >> j;
		s = new ArcNode; s->adjvex = j;
		s->next = adjlist[i].firstEdge = s;
	}
}
template<class T>
ALGraph<T>::~ALGraph()
{
	ArcNode* p = NULL;
	for (int i = 0; i < vertexNum; i++)
	{
		p = adjlist[i].firstEdge;
		while (p != NULL)
		{
			adjlist[i].firstEdge = p->next;
			delete p;
			p = adjlist[i].firstEdge;
		}
	}
}
template<class T>
void  ALGraph<T>::DFSTraverse(int v)
{
	ArcNode* p = NULL; int j;
	cout << adjlist[v].vertex;
	visited[v] = 1;
	p = adjlist[v].firstEdge;
	while (p != NULL)
	{
		j = p->adjvex;
		if (visited[j] == 0)DFSTraverse(j);
		p = p->next;
	}
}
template<class T>
void  ALGraph<T>::BFSTraverse(int v)
{
	int Q[MaxSize];
	int front = -1, rear = -1;
	ArcNode* p = NULL;
	cout << adjlist[v].vertex; visited[v] = 1; Q[++rear] = v;
	while (p != NULL)
	{

		int j = p->adjvex;
		if (visited[j] == 0)
		{
			cout << adjlist[j].vertex;
			visited[j] = 1; Q[++rear] = j;
		}
		p = p->next;
	}
}
template<class T>
void  ALGraph<T>::judge()
{
	int i, j;
	cin >> i >> j;
	int sign = 0;
	ArcNode* p = NULL;
	p = adjlist[i].firstEdge;
	while (p != NULL)
	{
		if (p->adjvex == j)sign = 1;
		p = p->next;
	}
	if (sign == 1)cout << "邻接" << endl;
	else cout << "不邻接" << endl;
}
template<class T>
void  ALGraph<T>::cancel()
{
	int i, j;
	cout << "两个顶点序号:";
	cin >> i >> j;
	ArcNode* p = NULL;
	p = adjlist[i].firstEdge;
	while (p != NULL)
	{
		if (p->next->adjvex == j) { p->next = p->next->next; delete p->next; }
		p = p->next;
	}
}
template<class T>
void  ALGraph<T>::degree()
{
	int x;
	cout << "输入你要查询度的顶点的序号";
	cin >> x;
	ArcNode* p = NULL;
	p = adjlist[x].firstEdge;
	int count = 0;
	while (p != NULL)
	{
		count++;
		p = p->next;
	}
	cout << count << endl;
}



int num = 0;
bool found = false;
int LocateVertices(ALGraph<char> MG, char a)
//查找字符a在图中的位置
{
	for (int i = 0; i < MG.vertexNum; i++)
		if (MG.vertices[i].data == a)
			return i;
	return -1;
}
int LocateArc(ALGraph<char> MG, char a, char b)
//判断弧ab是否已经存在于图中,若已经存在则返回1,否则返回0
{
	ArcNode* p;
	if (LocateVertices(MG, a) >= 0)
	{
		p = MG.vertices[LocateVertices(MG, a)].firstarc;
		while (p && p->adjvex != LocateVertices(MG, b))
			p = p->nextarc;
		if (p)
			return 1;
		return 0;
	}
	return 0;
}
void  CreateGraph(ALGraph<char>& MG)
//利用邻接表存储结构构造有向图
{
	int a, b;
	char s1, s2;
	ArcNode* p;
	for (int i = 0; i < MG.vertexNum; i++)
	{
		MG.vertices[i].data = '#';
		MG.vertices[i].firstarc = NULL;
	}
	for (int i = 1; i <= MG.arcNum; i++)
	{
		cin >> s1;
		a = LocateVertices(MG, s1);
		if (a < 0)
		{
			num++;
			MG.vertices[num - 1].data = s1;
			a = LocateVertices(MG, s1);
		}
		cin >> s2;
		b = LocateVertices(MG, s2);
		if (b < 0)
		{
			num++;
			MG.vertices[num - 1].data = s2;
			b = LocateVertices(MG, s2);
		}
		if (!LocateArc(MG, s1, s2))
		{
			p = new ArcNode;
			if (!p)
				return;
			p->adjvex = b;
			p->nextarc = MG.vertices[a].firstarc;
			MG.vertices[a].firstarc = p;
			p = new ArcNode;
			if (!p)
				return;
			p->adjvex = a;
			p->nextarc = MG.vertices[b].firstarc;
			MG.vertices[b].firstarc = p;
		}
	}
}
int FirstAdjVex(ALGraph<char> MG, int v)
//查找图中位置v的第一个邻接点在图中所在的位置
{
	if (MG.vertices[v].firstarc)
		return MG.vertices[v].firstarc->adjvex;
	return -1;
}
int NextAdjVex(ALGraph<char> MG, int v, int w)
//查找相对于图中位置v的邻接点w的下一邻接点在图中的位置
{
	ArcNode* p;
	p = MG.vertices[v].firstarc;
	while (p->adjvex != w)
		p = p->nextarc;
	if (p->nextarc)
		return p->nextarc->adjvex;
	return -1;
}
void DestroyGraph(ALGraph<char>& MG)
//销毁图
{
	ArcNode* p, * p1;
	for (int i = 0; i < MG.vertexNum; i++)
	{
		p = MG.vertices[i].firstarc;
		if (p)
			p1 = p->nextarc;
		while (p)
		{
			delete p;
			p = p1;
			if (p1)
				p1 = p1->nextarc;
		}
	}
}
void DFSearch(ALGraph<char> G, int i, int s)
//查找i与s之间是否有路径,以此来判断二者是否连通,若连通found=true,否则found=false
{
	int w;
	//	for(int x=0;x<G.vexnum;x++)
	//		visited[x]=false;
	visited[i] = true;
	for (w = FirstAdjVex(G, i); w >= 0 && !found; w = NextAdjVex(G, i, w))
	{
		if (w == s)
		{
			found = true;
			visited[s] = true;
		}
		else if (!visited[w])
			DFSearch(G, w, s);
	}
}
void DeleteArc(ALGraph<char>& MG, char a, char b)
//删除有向边ab
{
	ArcNode* p, * p1;
	if (LocateVertices(MG, a) >= 0)
	{
		p1 = MG.vertices[LocateVertices(MG, a)].firstarc;
		while (p1 && p1->adjvex != LocateVertices(MG, b))
		{
			p = p1;
			p1 = p1->nextarc;
		}
		if (!p1)
			return;
		if (p1 == MG.vertices[LocateVertices(MG, a)].firstarc)
		{
			MG.vertices[LocateVertices(MG, a)].firstarc = p1->nextarc;
			free(p1);
		}
		else
		{
			p->nextarc = p1->nextarc;
			free(p1);
		}
	}
	return;
}

#include"连.cpp"
#include <iostream>
using namespace std;
void main()
{
	ALGraph<int> G;
	char ch[MaxSize];
	int x, y, n;
	cout << "请输入顶点个数" << endl;
	cin >> x;
	cout << "输入" << x << "个字符" << endl;
	for (int i = 0; i < x; i++)
		cin >> ch[i];
	cout << "输入邻接边条数" << endl;
	cin >> y;
	ALGraph<char>MG(ch, x, y);        //定义图变量
	bool visited[MaxSize];        //访问标志数组
	int num = 0;
	bool found = false;
    char a, b, k;
	int n;
	cin >>MG.vertexNum >>MG.arcNum;
	CreateGraph(MG);
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		found = false;
		cin >> k;
		switch (k)
		{
		case 'Q':
			cin >> a >> b;
			int x;
			for (x = 0; x < MG.vertexNum; x++)
				visited[x] = false;
			MG.DFSTraverse(0);
			if (found)
			{
				cout << "C" << endl;
			}
			else
			{
				cout << "D" << endl;
			}
			break;
		case 'D':
			cin >> a >> b;
			DeleteArc(MG, a, b);
			DeleteArc(MG, b, a);
			break;
		default:
			cout << "输入有误" << endl;
			break;
		}
	}
	DestroyGraph(MG);
}






四、运行输出结果:
(可以将运行结果抓图贴至此处)







五、调试和运行程序过程中产生的问题及采取的措施:







六、对算法的程序的讨论、分析,改进设想,其它经验教训:





七、对数据结构教学的意见和建议:

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐