深圳大学计软《数据结构》实验09--图的存储和遍历

问题 A: DS图—图的邻接矩阵存储及度计算

题目描述

假设图用邻接矩阵存储。输入图的顶点信息和边信息,完成邻接矩阵的设置,并计算各顶点的入度、出度和度,并输出图中的孤立点(度为0的顶点)

–程序要求–
若使用C++只能include一个头文件iostream;若使用C语言只能include一个头文件stdio
程序中若include多过一个头文件,不看代码,作0分处理
不允许使用第三方对象或函数实现本题的要求

输入

测试次数T,每组测试数据格式如下:

图类型 顶点数 (D—有向图,U—无向图)

顶点信息

边数

每行一条边(顶点1 顶点2)或弧(弧尾 弧头)信息

输出

每组测试数据输出如下信息(具体输出格式见样例):

图的邻接矩阵

按顶点信息输出各顶点的度(无向图)或各顶点的出度 入度 度(有向图)。孤立点的度信息不输出。

图的孤立点。若没有孤立点,不输出任何信息。

样例输入

2
D 5
V1 V2 V3 V4 V5
7
V1 V2
V1 V4
V2 V3
V3 V1
V3 V5
V4 V3
V4 V5
U 5
A B C D E
5
A B
A C
B D
D C
A D

样例输出

0 1 0 1 0
0 0 1 0 0
1 0 0 0 1
0 0 1 0 1
0 0 0 0 0
V1: 2 1 3
V2: 1 1 2
V3: 2 2 4
V4: 2 1 3
V5: 0 2 2
0 1 1 1 0
1 0 0 1 0
1 0 0 1 0
1 1 1 0 0
0 0 0 0 0
A: 3
B: 2
C: 2
D: 3
E

AC代码

#include<iostream>
using namespace std;

const int GREAT = 0;

class Map {
	int  VertexNum;	 
	string* Vertex;    
	int** AdjMatrix;  
	char kind;
public:
	Map() {
		cin >> kind >> VertexNum;
		Vertex = new string[VertexNum];
		for (int i = 0; i < VertexNum; i++)
			cin >> Vertex[i];
		AdjMatrix = new int* [VertexNum];
		for (int i = 0; i < VertexNum; i++)
		{
			AdjMatrix[i] = new int[VertexNum];
			for (int j = 0; j < VertexNum; j++)
				AdjMatrix[i][j] = GREAT;
		}
		int n;
		cin >> n;
		for (int i = 0; i < n; i++) {
			string s1, s2;
			cin >> s1 >> s2;
			int index1, index2;
			for (int j = 0; j < VertexNum; j++)
				if (Vertex[j] == s1)
				{
					index1 = j;
					break;
				}
			for (int j = 0; j < VertexNum; j++)
				if (Vertex[j] == s2)
				{
					index2 = j;
					break;
				}
			switch (kind)
			{
			case 'U':
				AdjMatrix[index2][index1] = 1;
			case 'D':
				AdjMatrix[index1][index2] = 1;
			default:
				break;
			}
		}

	}

	void display_array() {
		for (int i = 0; i < VertexNum; i++)
		{
			cout << AdjMatrix[i][0];
			for (int j = 1; j < VertexNum; j++)
				cout << " " << AdjMatrix[i][j];
			cout << endl;
		}
	}

	void display_node() {
		if (kind == 'U')
		{
			for (int i = 0; i < VertexNum; i++)
			{
				int cnt = 0;
				for (int j = 0; j < VertexNum; j++)
					if (AdjMatrix[i][j] != GREAT)
						cnt++;
				if (cnt)
					cout << Vertex[i] << ": " << cnt << endl;
				else
					cout << Vertex[i] << endl;
			}
		}

		else if (kind == 'D')
		{
			for (int i = 0; i < VertexNum; i++)
			{
				int cnt1 = 0;
				for (int j = 0; j < VertexNum; j++)
					if (AdjMatrix[i][j] != GREAT)
						cnt1++;
				int cnt2 = 0;
				for (int j = 0; j < VertexNum; j++)
					if (AdjMatrix[j][i] != GREAT)
						cnt2++;
				if (cnt1 || cnt2)
					cout << Vertex[i] << ": " << cnt1 << " " << cnt2 << " " << cnt1 + cnt2 << endl;
				else
					cout << Vertex[i] << endl;
			}
		}
	}
	~Map()
	{
		delete[]Vertex;
		for (int i = 0; i < VertexNum; i++)
			delete[]AdjMatrix[i];
		delete[]AdjMatrix;
	}
};


int main() {
	int n;
	cin >> n;
	while (n--)
	{
		Map m;
		m.display_array();
		m.display_node();
	}
	return 0;
}

问题 B: 图综合练习–构建邻接表

题目描述

已知一有向图,构建该图对应的邻接表。

邻接表包含数组和单链表两种数据结构,其中每个数组元素也是单链表的头结点,数组元素包含两个属性,属性一是顶点编号info,属性二是指针域next指向与它相连的顶点信息。

单链表的每个结点也包含两个属性,属性一是顶点在数组的位置下标,属性二是指针域next指向下一个结点。

输入

第1行输入整数t,表示有t个图

第2行输入n和k,表示该图有n个顶点和k条弧。

第3行输入n个顶点。

第4行起输入k条弧的起点和终点,连续输入k行

以此类推输入下一个图

输出

输出每个图的邻接表,每行输出格式:数组下标 顶点编号-连接顶点下标-…-^,数组下标从0开始。

具体格式请参考样例数据,每行最后加入“^”表示NULL。

样例输入

1
5 7
A B C D E
A B
A D
A E
B D
C B
C E
E D

样例输出

0 A-1-3-4-^
1 B-3-^
2 C-1-4-^
3 D-^
4 E-3-^

AC代码

#include<iostream>
using namespace std;

struct Node {
	int VertexNo;
	int  Weight;
	Node* NextArc;
	Node() { NextArc = NULL; }
};

class  Graph {
	int  VertexNum;
	int  ArcNum;
	string* Vertex;
	Node* AdjList;
	void insert(string v1, string v2)
	{
		int index1, index2;
		for (int i = 0; i < VertexNum; i++)
			if (Vertex[i] == v1)
			{
				index1 = i;
				break;
			}
		for (int i = 0; i < VertexNum; i++)
			if (Vertex[i] == v2)
			{
				index2 = i;
				break;
			}
		Node* p = AdjList + index1;
		while (p->NextArc)
			p = p->NextArc;
		Node* s = new Node;
		s->VertexNo = index2;
		p->NextArc = s;
	}
public:
	Graph() {
		cin >> VertexNum >> ArcNum;
		Vertex = new string[VertexNum];
		AdjList = new Node[VertexNum];
		for (int i = 0; i < VertexNum; i++)
			cin >> Vertex[i];
		for (int i = 0; i < ArcNum; i++)
		{
			string v1, v2;
			cin >> v1 >> v2;
			insert(v1, v2);
		}
	}

	void display() {
		for (int i = 0; i < VertexNum; i++)
		{
			cout << i << " " << Vertex[i] << "-";
			Node* p = (AdjList + i)->NextArc;
			while (p)
			{
				cout << p->VertexNo << "-";
				p = p->NextArc;
			}
			cout << "^" << endl;
		}
	}

	~Graph() {
		delete[]Vertex;
		for (int i = 0; i < VertexNum; i++) {
			Node* p = (AdjList + i)->NextArc;
			while (p)
			{
				(AdjList + i)->NextArc = p->NextArc;
				delete p;
				p = (AdjList + i)->NextArc;
			}
		}
		delete[]AdjList;
	}
};

int main() {
	int n;
	cin >> n;
	while (n--)
	{
		Graph g;
		g.display();
	}
	return 0;
}

问题 C: DS图遍历–深度优先搜索

题目描述

给出一个图的邻接矩阵,对图进行深度优先搜索,从顶点0开始

注意:图n个顶点编号从0到n-1

代码框架如下:

在这里插入图片描述
在这里插入图片描述

输入

第一行输入t,表示有t个测试实例

第二行输入n,表示第1个图有n个结点

第三行起,每行输入邻接矩阵的一行,以此类推输入n行

第i个结点与其他结点如果相连则为1,无连接则为0,数据之间用空格隔开

以此类推输入下一个示例

输出

每行输出一个图的深度优先搜索结果,结点编号之间用空格隔开

样例输入

2
4
0 0 1 1
0 0 1 1
1 1 0 1
1 1 1 0
5
0 0 0 1 1
0 0 1 0 0
0 1 0 1 1
1 0 1 0 0
1 0 1 0 0

样例输出

0 2 1 3
0 3 2 1 4

AC代码

#include<iostream>
using namespace std;
#include<stack>
const int GREAT = 0;

class Map {
	int  VertexNum;
	int* Vertex;
	int** AdjMatrix;
	bool* visited;
public:
	Map() {
		cin >> VertexNum;
		Vertex = new int[VertexNum];
		visited = new bool[VertexNum];

		for (int i = 0; i < VertexNum; i++)
		{
			Vertex[i] = i;
			visited[i] = 0;
		}

		AdjMatrix = new int* [VertexNum];
		for (int i = 0; i < VertexNum; i++)
		{
			AdjMatrix[i] = new int[VertexNum];
			for (int j = 0; j < VertexNum; j++)
				cin >> AdjMatrix[i][j];
		}



	}

	void dfs() {
		stack<int>s;
		for (int j = 0; j < VertexNum; j++)
		{
			if (visited[j])
				continue;
			s.push(j);
			while (!s.empty())
			{
				int cur_index = s.top();
				s.pop();
				if (visited[cur_index])
					continue;
				visited[cur_index] = 1;
				cout << Vertex[cur_index] << " ";
				for (int i = VertexNum - 1; i >= 0; i--)
					if (AdjMatrix[cur_index][i] && !visited[i])
						s.push(i);
			}
		}
		cout << endl;
	}

	~Map()
	{
		delete[]Vertex;
		for (int i = 0; i < VertexNum; i++)
			delete[]AdjMatrix[i];
		delete[]AdjMatrix;
	}
};


int main() {
	int n;
	cin >> n;
	while (n--)
	{
		Map m;
		m.dfs();
	}
	return 0;
}

问题 D: DS图遍历–广度优先搜索

题目描述

给出一个图的邻接矩阵,对图进行深度优先搜索,从顶点0开始

注意:图n个顶点编号从0到n-1

代码框架如下:

在这里插入图片描述

输入

第一行输入t,表示有t个测试实例

第二行输入n,表示第1个图有n个结点

第三行起,每行输入邻接矩阵的一行,以此类推输入n行

第i个结点与其他结点如果相连则为1,无连接则为0,数据之间用空格隔开

以此类推输入下一个示例

输出

每行输出一个图的广度优先搜索结果,结点编号之间用空格隔开

样例输入

2
4
0 0 1 1
0 0 1 1
1 1 0 1
1 1 1 0
5
0 0 0 1 1
0 0 1 0 0
0 1 0 1 1
1 0 1 0 0
1 0 1 0 0

样例输出

0 2 3 1
0 3 4 2 1

AC代码

#include<iostream>
using namespace std;
#include<queue>
const int GREAT = 0;

class Map {
	int  VertexNum;
	int* Vertex;
	int** AdjMatrix;
	bool* visited;
public:
	Map() {
		cin >> VertexNum;
		Vertex = new int[VertexNum];
		visited = new bool[VertexNum];

		for (int i = 0; i < VertexNum; i++)
		{
			Vertex[i] = i;
			visited[i] = 0;
		}

		AdjMatrix = new int* [VertexNum];
		for (int i = 0; i < VertexNum; i++)
		{
			AdjMatrix[i] = new int[VertexNum];
			for (int j = 0; j < VertexNum; j++)
				cin >> AdjMatrix[i][j];
		}



	}

	void bfs() {
		queue<int>q;
		for (int j = 0; j < VertexNum; j++)
		{
			if (visited[j])
				continue;
			q.push(j);
			while (!q.empty())
			{
				int cur_index = q.front();
				q.pop();
				if (visited[cur_index])
					continue;
				visited[cur_index] = 1;
				cout << Vertex[cur_index] << " ";
				for (int i = 0; i < VertexNum; i++)
					if (AdjMatrix[cur_index][i] && !visited[i])
						q.push(i);
			}
		}
		cout << endl;
	}

	~Map()
	{
		delete[]Vertex;
		for (int i = 0; i < VertexNum; i++)
			delete[]AdjMatrix[i];
		delete[]AdjMatrix;
	}
};


int main() {
	int n;
	cin >> n;
	while (n--)
	{
		Map m;
		m.bfs();
	}
	return 0;
}

问题 E: DS图—图的连通分量

题目描述

输入无向图顶点信息和边信息,创建图的邻接矩阵存储结构,计算图的连通分量个数。

输入

测试次数t

每组测试数据格式如下:

第一行:顶点数 顶点信息

第二行:边数

第三行开始,每行一条边信息

输出

每组测试数据输出,顶点信息和邻接矩阵信息

输出图的连通分量个数,具体输出格式见样例。

每组输出直接用空行分隔。

样例输入

3
4 A B C D
2
A B
A C
6 V1 V2 V3 V4 V5 V6
5
V1 V2
V1 V3
V2 V4
V5 V6
V3 V5
8 1 2 3 4 5 6 7 8
5
1 2
1 3
5 6
5 7
4 8

样例输出

A B C D
0 1 1 0
1 0 0 0
1 0 0 0
0 0 0 0
2

V1 V2 V3 V4 V5 V6
0 1 1 0 0 0
1 0 0 1 0 0
1 0 0 0 1 0
0 1 0 0 0 0
0 0 1 0 0 1
0 0 0 0 1 0
1

1 2 3 4 5 6 7 8
0 1 1 0 0 0 0 0
1 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 1 1 0
0 0 0 0 1 0 0 0
0 0 0 0 1 0 0 0
0 0 0 1 0 0 0 0
3

AC代码

#include<iostream>
using namespace std;

const int GREAT = 0;

class Map {
	int  VertexNum;
	string* Vertex;
	int** AdjMatrix;
	int* myset;			//并查集
	void set_union() {
		for (int i = 0; i < VertexNum; i++)
			for (int j = 0; j < VertexNum; j++)
				if (AdjMatrix[i][j])
				{
					int root1 = find(i), root2 = find(j);
					if (root1 != root2)
						myset[root1] = root2;
				}
	}

	int find(int index)
	{
		if (index == myset[index])
			return index;
		return myset[index] = find(myset[index]);
	}
public:
	Map() {
		cin >> VertexNum;
		Vertex = new string[VertexNum];
		myset = new int[VertexNum];
		for (int i = 0; i < VertexNum; i++)
		{
			cin >> Vertex[i];
			myset[i] = i;
		}
		AdjMatrix = new int* [VertexNum];
		for (int i = 0; i < VertexNum; i++)
		{
			AdjMatrix[i] = new int[VertexNum];
			for (int j = 0; j < VertexNum; j++)
				AdjMatrix[i][j] = GREAT;
		}
		int n;
		cin >> n;
		for (int i = 0; i < n; i++) {
			string s1, s2;
			cin >> s1 >> s2;
			int index1, index2;
			for (int j = 0; j < VertexNum; j++)
				if (Vertex[j] == s1)
				{
					index1 = j;
					break;
				}
			for (int j = 0; j < VertexNum; j++)
				if (Vertex[j] == s2)
				{
					index2 = j;
					break;
				}
			AdjMatrix[index1][index2] = 1;
			AdjMatrix[index2][index1] = 1;
		}
		set_union();
	}


	void display_array() {
		for (int i = 0; i < VertexNum; i++)
		{
			if (i)
				cout << " ";
			cout << Vertex[i];
		}
		cout << endl;
		for (int i = 0; i < VertexNum; i++)
		{
			cout << AdjMatrix[i][0];
			for (int j = 1; j < VertexNum; j++)
				cout << " " << AdjMatrix[i][j];
			cout << endl;
		}
	}

	~Map()
	{
		delete[]myset;
		delete[]Vertex;
		for (int i = 0; i < VertexNum; i++)
			delete[]AdjMatrix[i];
		delete[]AdjMatrix;
	}

	int get_connected_components() {
		int cnt = 0;
		for (int i = 0; i < VertexNum; i++)
			if (myset[i] == i)
				cnt++;
		return cnt;
	}
};


int main() {
	int n;
	cin >> n;
	while (n--)
	{
		Map m;
		m.display_array();
		cout << m.get_connected_components() << endl;
		cout << endl;
	}
	return 0;
}

问题 F: DS图—图非0面积

题目描述

编程计算由"1"围成的下列图形的面积。面积计算方法是统计"1"所围成的闭合曲线中"0"点的数目。如图所示,在10*10的二维数组中,"1"围住了15个点,因此面积为15。
在这里插入图片描述

输入

测试次数t

每组测试数据格式为:

数组大小m,n

一个由0和1组成的m*n的二维数组

输出

对每个二维数组,输出符号"1"围住的"0"的个数,即围成的面积。假设一定有1组成的闭合曲线,但不唯一。

样例输入

2
10 10
0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 1 0 0 0
0 0 0 0 1 0 0 1 0 0
0 0 0 0 0 1 0 0 1 0
0 0 1 0 0 0 1 0 1 0
0 1 0 1 0 1 0 0 1 0
0 1 0 0 1 1 0 1 1 0
0 0 1 0 0 0 0 1 0 0
0 0 0 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0
5 8
0 1 1 0 0 1 1 0
1 0 1 0 1 0 0 1
0 1 0 1 0 0 1 0
0 1 0 0 1 1 1 0
0 0 0 0 0 0 0 0

样例输出

15
5

AC代码

#include<bits/stdc++.h>
using namespace std;

class Array {
	int** p;
	int n;
	int m;

	void make(int x, int y)
	{
		if (x < 0 || y < 0 || x >= n || y >= m || p[x][y])
			return;
		p[x][y] = 1;
		make(x - 1, y);
		make(x + 1, y);
		make(x, y - 1);
		make(x, y + 1);
	}
public:
	Array() {
		cin >> n >> m;
		p = new int* [n];
		for (int i = 0; i < n; i++)
			p[i] = new int[m];
		for (int i = 0; i < n; i++)
			for (int j = 0; j < m; j++)
				cin >> p[i][j];
	}

	void display() {
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < m; j++)
				cout << p[i][j] << " ";
			cout << endl;
		}
	}

	void make()
	{
		for (int i = 0; i < n; i++)
		{
			make(i, 0);
			make(i, m - 1);
		}

		for (int i = 0; i < m; i++)
		{
			make(0, i);
			make(n - 1, i);
		}
	}

	int getCount() {
		int ans = 0;
		for (int i = 0; i < n; i++)
			for (int j = 0; j < m; j++)
				if (!p[i][j])
					ans++;
		return ans;
	}
};

int main() {
	int t;
	cin >> t;
	while (t--)
	{
		Array a;
		a.make();
		//a.display();
		cout << a.getCount() << endl;
	}
}
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曹无悔

请支持我的梦想!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值