【数据结构】图的存储和遍历

Alex_Shen
2020-11-19 / 0 评论 / 0 点赞 / 72 阅读 / 9,388 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-04-06,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

问题 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

题解

#include <iostream>
using namespace std;

int main() {
	int t;
	cin >> t;
	while (t--) {
		int** graph;
		char type;
		int n;
		cin >> type >> n;
		//创建二维数组
		graph = new int* [n];
		for (int i = 0; i < n; i++)
			graph[i] = new int[n];
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
				graph[i][j] = 0;
		//创建索引
		string* str = new string[n];
		for (int i = 0; i < n; i++)
			cin >> str[i];
		//创建邻接矩阵
		int num;
		cin >> num;
		string node1, node2;
		int flag1, flag2;
		for (int i = 0; i < num; i++) {
			cin >> node1 >> node2;
			for (int j = 0; j < n; j++) {
				if (str[j] == node1)
					flag1 = j;
				else if (str[j] == node2)
					flag2 = j;
			}
			if (type == 'D')
				graph[flag1][flag2] = 1;
			else if (type == 'U') {
				graph[flag1][flag2] = 1;
				graph[flag2][flag1] = 1;
			}
		}
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++)
				cout << graph[i][j] << ' ';
			cout << endl;
		}
		//打印信息
		if (type == 'D') {			
			for (int k = 0; k < n; k++) {
				int flag1 = 0, flag2 = 0;
				cout << str[k];
				for (int i = 0; i < n; i++) {
					if (graph[k][i] == 1)
						flag1++;
					if (graph[i][k] == 1)
						flag2++;
				}
				if (flag1 || flag2) {
					cout << ": " << flag1 << ' ' << flag2 << ' ' << flag1 + flag2;
				}
				cout << endl;
			}
		}
		else if (type == 'U') {
			for (int k = 0; k < n; k++) {
				int flag1 = 0, flag2 = 0;
				cout << str[k];
				for (int i = 0; i < n; i++) {
					if (graph[k][i] == 1)
						flag1++;
				}
				if (flag1) {
					cout << ": " << flag1;
				}
				cout << endl;
			}
		}
	}
	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-^

题解

#include <iostream>
using namespace std;

class node {
public:
	int pos;
	node* next;
	node() {
		pos = 0;
		next = NULL;
	}
	node(int pos) {
		this->pos = pos;
		next = NULL;
	}
};

class Grapgh {
public:
	int vexnum;
	int arcnum;
	string* vex;
	node* heads;	
	Grapgh() {
		cin >> vexnum >> arcnum;
		vex = new string[vexnum];
		for (int i = 0; i < vexnum; i++)
			cin >> vex[i];
		heads = new node[vexnum];
		/*for (int i = 0; i < vexnum; i++) {
			heads[i] = new node;

		}*/
		string node1, node2;
		int flag1, flag2;
		for (int i = 0; i < arcnum; i++) {
			cin >> node1 >> node2;
			flag1 = index(node1);
			flag2 = index(node2);
			node* p = &heads[flag1];
			while (p->next)
				p = p->next;
			//新节点
			node* s = new node;
			s->pos = flag2;
			p->next = s;
		}
	}
	int index(string str) {
		for (int i = 0; i < vexnum; i++)
			if (vex[i] == str)
				return i;
	}
	void print() {
		for (int i = 0; i < vexnum; i++) {
			cout << i << " " << vex[i] << "-";
			node* p = heads[i].next;
			while (p) {
				cout << p->pos << "-";
				p = p->next;
			}
			cout << "^" << endl;
		}
	}
};

int main() {
	int t;
	cin >> t;
	while (t--) {
		Grapgh g1;
		g1.print();
	}
	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

题解

#include <iostream>
using namespace std;

const int MaxLen = 20;

class Map {
private:
	bool Visit[MaxLen];
	int Matrix[MaxLen][MaxLen];
	int Vexnum;
	void DFS(int v);
public:
	void SetMatrix(int vnum, int mx[MaxLen][MaxLen]);
	void DFSTraverse();
	void print() {
		for (int i = 0; i < Vexnum; i++) {
			for (int j = 0; j < Vexnum; j++)
				cout << Matrix[i][j] << ' ';
			cout << endl;
		}			
	}
};

int main() {
	int t;
	cin >> t;
	while (t--) {
		int Matrix[MaxLen][MaxLen];
		int vexnum;
		cin >> vexnum;
		for (int i = 0; i < vexnum; i++)
			for (int j = 0; j < vexnum; j++)
				cin >> Matrix[i][j];
		Map m;
		m.SetMatrix(vexnum, Matrix);
		m.DFSTraverse();
	}
}

void Map::DFS(int v)
{
	int w, i, k;
	Visit[v] = true;
	cout << v << ' ';
	int AdjVex[MaxLen];
	for (int i = 0; i < Vexnum; i++)
		AdjVex[i] = -1;
	k = 0;
	for(int i=0;i<Vexnum;i++)
		if (Matrix[v][i] == 1) {
			AdjVex[k] = i;
			k++;
		}
	for (int i = 0; i < k; i++) {
		if (!Visit[AdjVex[i]])
			DFS(AdjVex[i]);
	}

}

void Map::SetMatrix(int vnum, int mx[MaxLen][MaxLen])
{
	int i, j;
	Vexnum = vnum;
	for (i = 0; i < MaxLen; i++)
		for (j = 0; j < MaxLen; j++)
			Matrix[i][j] = 0;
	for (i = 0; i < Vexnum; i++)
		for (j = 0; j < Vexnum; j++)
			Matrix[i][j] = mx[i][j];
}

void Map::DFSTraverse()
{
	int v;
	for (int i = 0; i < Vexnum; i++)
		Visit[i] = false;
	for (v = 0; v < Vexnum; v++) {
		if (!Visit[v])
			DFS(v);
	}
	cout << endl;
}


问题 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

题解

#include <iostream>
#include<queue>
using namespace std;

const int MaxLen = 20;

class Map {
private:
	bool Visit[MaxLen];
	int Matrix[MaxLen][MaxLen];
	int Vexnum;
	void DFS(int v);
	void BFS(int v);
public:
	void SetMatrix(int vnum, int mx[MaxLen][MaxLen]);
	void DFSTraverse();
	void BFSTraverse();
};

int main() {
	int t;
	cin >> t;
	while (t--) {
		int Matrix[MaxLen][MaxLen];
		int vexnum;
		cin >> vexnum;
		for (int i = 0; i < vexnum; i++)
			for (int j = 0; j < vexnum; j++)
				cin >> Matrix[i][j];
		Map m;
		m.SetMatrix(vexnum, Matrix);
		m.BFSTraverse();
	}
}

void Map::DFS(int v)
{
	int w, i, k;
	Visit[v] = true;
	cout << v << ' ';
	int AdjVex[MaxLen];
	for (int i = 0; i < Vexnum; i++)
		AdjVex[i] = -1;
	k = 0;
	for(int i=0;i<Vexnum;i++)
		if (Matrix[v][i] == 1) {
			AdjVex[k] = i;
			k++;
		}
	for (int i = 0; i < k; i++) {
		if (!Visit[AdjVex[i]])
			DFS(AdjVex[i]);
	}

}

void Map::BFS(int v)
{
	int w, u;
	int i, k;
	int AdjVex[MaxLen];
	queue<int> Q;
	for (int i = 0; i < Vexnum; i++)
		Visit[i] = false;
	for (v = 0; v < Vexnum; v++) {
		if (!Visit[v]) {
			Visit[v] = true;
			Q.push(v);
			while (!Q.empty()) {
				u = Q.front();
				cout << u << ' ';
				Q.pop();
				for (int i = 0; i < MaxLen; i++)
					AdjVex[i] = -1;
				k = 0;
				for (i = 0; i < Vexnum; i++)
					if (Matrix[u][i] == 1) {
						AdjVex[k] = i;
						k++;
					}
				i = 0;
				for (w = AdjVex[i]; w >= 0;) {
					if (!Visit[w]) {
						Visit[w] = true;
						Q.push(w);
					}
					i++;
					w = AdjVex[i];				
				}
			}
		}
	}
	cout << endl;
}

void Map::SetMatrix(int vnum, int mx[MaxLen][MaxLen])
{
	int i, j;
	Vexnum = vnum;
	for (i = 0; i < MaxLen; i++)
		for (j = 0; j < MaxLen; j++)
			Matrix[i][j] = 0;
	for (i = 0; i < Vexnum; i++)
		for (j = 0; j < Vexnum; j++)
			Matrix[i][j] = mx[i][j];
}

void Map::DFSTraverse()
{
	int v;
	for (int i = 0; i < Vexnum; i++)
		Visit[i] = false;
	for (v = 0; v < Vexnum; v++) {
		if (!Visit[v])
			DFS(v);
	}
	cout << endl;
}

void Map::BFSTraverse()
{

	BFS(0);
}

方法二:

#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
#define MaxLen 20
#define Infinity 99999 

using namespace std;

class Map {
private:
	bool Visit[MaxLen];
	string node[MaxLen];
	int Matrix[MaxLen][MaxLen];
	int Vexnum;
	void DFS(int node) {
		for (int i = 0; i < Vexnum; i++) {
			if (Matrix[node][i] == 1 && Visit[i] == false) {
				Visit[i] = true;
				cout << i << " ";
				DFS(i);
			}
		}
	}
public:
	void SetMatrix() {
		cin >> Vexnum;
		for (int i = 0; i < Vexnum; i++)
			for (int j = 0; j < Vexnum; j++)
				cin >> Matrix[i][j];
	}
	void setVisit() {
		for (int i = 0; i < Vexnum; i++)
			Visit[i] = false;
	}
	void DFS1() {
		int flag = 0;
		setVisit();
		Visit[0] = true;
		cout << 0 << " ";
		DFS(0);
		cout << endl;
	}
	void print() {
		for (int i = 0; i < Vexnum; i++) {
			for (int j = 0; j < Vexnum; j++)
				cout << Matrix[i][j] << ' ';
			cout << endl;
		}
	}
};

int main() {
	int n;
	cin >> n;
	while (n--) {
		Map map;
		map.SetMatrix();
		map.DFS1();
	}	
	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

题解

#include <iostream>
using namespace std;

const int MaxLen = 100;

class Map {
private:
	bool Visit[MaxLen];
	int Matrix[MaxLen][MaxLen];
	int Vexnum;
	void DFS(int v);
	int count = 0;
public:
	void SetMatrix(int vnum, int mx[MaxLen][MaxLen]);
	void DFSTraverse();
	void print() {
		for (int i = 0; i < Vexnum; i++) {
			for (int j = 0; j < Vexnum; j++)
				cout << Matrix[i][j] << ' ';
			cout << endl;
		}
	}
};


void Map::DFS(int v)
{
	int w, i, k;
	Visit[v] = true;
	int AdjVex[MaxLen];
	for (int i = 0; i < Vexnum; i++)
		AdjVex[i] = -1;
	k = 0;
	for (int i = 0; i < Vexnum; i++)
		if (Matrix[v][i] == 1) {
			AdjVex[k] = i;
			k++;
		}
	for (int i = 0; i < k; i++) {
		if (!Visit[AdjVex[i]])
			DFS(AdjVex[i]);
	}

}

void Map::SetMatrix(int vnum, int mx[MaxLen][MaxLen])
{
	int i, j;
	Vexnum = vnum;
	for (i = 0; i < MaxLen; i++)
		for (j = 0; j < MaxLen; j++)
			Matrix[i][j] = 0;
	for (i = 0; i < Vexnum; i++)
		for (j = 0; j < Vexnum; j++)
			Matrix[i][j] = mx[i][j];
}

void Map::DFSTraverse()
{
	int v;
	for (int i = 0; i < Vexnum; i++)
		Visit[i] = false;
	for (v = 0; v < Vexnum; v++) {
		if (!Visit[v]) {
			DFS(v);
			count++;
		}			
	}
	cout << count << endl;
}


int main() {
	int t;
	cin >> t;
	while (t--) {
		int graph[MaxLen][MaxLen];
		int n;
		cin >> n;
		//创建二维数组
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
				graph[i][j] = 0;
		//创建索引
		string* str = new string[n];
		for (int i = 0; i < n; i++)
			cin >> str[i];
		//创建邻接矩阵
		int num;
		cin >> num;
		string node1, node2;
		int flag1, flag2;
		for (int i = 0; i < num; i++) {
			cin >> node1 >> node2;
			for (int j = 0; j < n; j++) {
				if (str[j] == node1)
					flag1 = j;
				else if (str[j] == node2)
					flag2 = j;
			}
			graph[flag1][flag2] = 1;
			graph[flag2][flag1] = 1;
		}
		for (int i = 0; i < n; i++)
			cout << str[i] << ' ';
		cout << endl;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++)
				cout << graph[i][j] << ' ';
			cout << endl;
		}
		//打印信息
		Map m;
		m.SetMatrix(n, graph);
		m.DFSTraverse();
		cout << endl;
	}
	return 0;
}

0

评论区