shiyan5

集美大学课程实验报告-实验5:图

项目名称 内容
课程名称 数据结构
实验项目名称
上机实践日期 2026年6月6日
上机实践时间 2小时

一、目的

  • 掌握创建图的代码
  • 熟悉BFS和DFS遍历的使用
  • 学会运用图来解决实际问题

二、实验内容与设计思想

题目1和2:图的创建以及遍历

函数相关伪代码

1.Graph{
        整数 vertexCount  
        整数 edgeCount  
        二维数组 adjMatrix 
         私有辅助函数:
        函数 DFSUtil(整数 v, 布尔数组引用 visited):
            visited[v] = true
            输出 v
            对于 i 从 0 到 vertexCount-1:
                如果 adjMatrix[v][i] != 0 且 visited[i] == false:
                    调用 DFSUtil(i, visited)
        公共部分:
        构造Graph函数
        添加addEdge
        函数 DFS(整数 start):
            如果 start 无效: 提示并返回
            创建布尔数组 visited[vertexCount],初始全 false
            输出 "DFS 遍历结果:"
            调用 DFSUtil(start, visited)      
            对于 i 从 0 到 vertexCount-1:    
                如果 visited[i] == false:
                    调用 DFSUtil(i, visited)
          函数 BFS(整数 start):
            如果 start 无效: 提示并返回
            创建布尔数组 visited[vertexCount],初始全 false
            创建队列 q
            visited[start] = true
            q.push(start)
            输出 "BFS 遍历结果:"
            当 q 非空:
                v = q.front(); q.pop()
                输出 v
                对于 i 从 0 到 vertexCount-1:
                    如果 adjMatrix[v][i] != 0 且 visited[i] == false:
                        visited[i] = true
                        q.push(i)
            对于 i 从 0 到 vertexCount-1:
                如果 visited[i] == false:
                    visited[i] = true
                    q.push(i)
                    当 q 非空:
                        v = q.front(); q.pop()
                        输出 v
                        对于 j 从 0 到 vertexCount-1:
                            如果 adjMatrix[v][j] != 0 且 visited[j] == false:
                                visited[j] = true
                                q.push(j)
}
2.主函数
   先构造Graph
   再进行BFS和DFS进行遍历

函数代码

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

class Graph
{
private:
	int vertexCount;
	int edgeCount;
	vector<vector<int>>adjMatrix;

	void DFSUtil(int v, vector<bool>& visited)
	{
		visited[v] = true;
		cout << v << " ";
		for (int i = 0; i < vertexCount; i++)
		{
			if (adjMatrix[v][i] != 0 && !visited[i])
			{
				DFSUtil(i, visited);
			}
		}
	}

public:
	Graph(int v) :vertexCount(v), edgeCount(0)
	{
		adjMatrix.resize(v, vector<int>(v, 0));
	}


	void addEdge(int u, int v, int weight = 1)
	{
		if (u < 0 || u >= vertexCount || v < 0 || v >= vertexCount)return;
		if (adjMatrix[u][v] == 0)
		{
			adjMatrix[u][v] = weight;
			adjMatrix[v][u] = weight;
			edgeCount++;
		}
	}

	void DFS(int start)
	{
		if (start < 0 || start >= vertexCount)
		{
			cout << "起始顶点无效!" << endl;
			return;
		}
		vector<bool>visited(vertexCount, false);
		cout << "DFS遍历结果(从顶点 " << start << "开始):";
		DFSUtil(start, visited);
		for (int i = 0; i < vertexCount;i++)
		{
			if (!visited[i])
			{
				DFSUtil(i, visited);
			}
		}
		cout << endl;
	}

	void BFS(int start)
	{
		if (start < 0 || start >= vertexCount)
		{
			cout << "起始顶点无效!" << endl;
			return;
		}
		vector<bool>visited(vertexCount, false);
		queue<int>q;
		visited[start] = true;
		q.push(start);
		cout << "BFS遍历结果(从顶点 " << start << "开始) :";
		while (!q.empty())
		{
			int v = q.front(); q.pop();
			cout << v << " ";
			for (int i = 0; i < vertexCount; i++)
			{
				if (adjMatrix[v][i] != 0 && !visited[i])
				{
					visited[i] = true;
					q.push(i);
				}
			}
		}
		for (int i = 0; i < vertexCount; i++)
		{
			if (!visited[i])
			{
				visited[i] = true;
				q.push(i);
				while (!q.empty())
				{
					int v = q.front(); q.pop();
					cout << v << " ";
					for (int j = 0; j < vertexCount; j++)
					{
						if (adjMatrix[v][j] != 0 && !visited[j])
						{
							visited[j] = true;
							q.push(j);
						}
					}
				}
			}
		}
		cout << endl;
	}

	void printMatrix()
	{
		cout << "邻接矩阵:" << endl;
		for (int i = 0; i < vertexCount; i++)
		{
			for (int j = 0; j < vertexCount; j++)
			{
				cout << adjMatrix[i][j] << "\t";
			}
			cout << endl;
		}
	}
	void printInfo()
	{
		cout << "顶点数:" << vertexCount << endl;
		cout << "边数:" << edgeCount << endl;
	}
};

int main()
{
	Graph g(4);
	g.addEdge(0, 1, 5);
	g.addEdge(0, 2, 3);
	g.addEdge(1, 3, 2);
	g.addEdge(2, 3, 4);
	g.addEdge(1, 2, 6);
	g.printInfo();
	g.printMatrix();
	g.DFS(0);
	g.BFS(0);
	return 0;
}

题目3:图着色问题

函数相关伪代码

1.输入V,E,K
2.构造两个数组,分别存放一个边的两个邻结点
3.while(N--)
        {
            整数 color[501];
            整数 used[501]={0};
            整数 colorCount=0;
            for(整数 i=1;i<=V;i++)
                {
                    输入color[i];
                    if(used[color[i]]==0)
                    {
                        used[color[i]]=1;
                        colorCount++;
                    }
                }
            if(colorCount!=K)
            {
                输出"No"
                continue;
            }
            bool ok=true;
            for(整数 i=0;i<E;i++)
                {
                    if(color[u[i]]==color[v[i]])
                    {
                        ok=false;
                        break;
                    }
                }
           if ok为真,输出Yes,否则输出No
        }

函数代码

#include<iostream>
using namespace std;

int main()
{
    int V,E,K;
    cin>>V>>E>>K;
    int u[500000],v[500000];
    for(int i=0;i<E;i++)
        {
            cin>>u[i]>>v[i];
        }
    int N;
    cin>>N;
    while(N--)
        {
            int color[501];
            int used[501]={0};
            int colorCount=0;
            for(int i=1;i<=V;i++)
                {
                    cin>>color[i];
                    if(used[color[i]]==0)
                    {
                        used[color[i]]=1;
                        colorCount++;
                    }
                }
            if(colorCount!=K)
            {
                cout<<"No"<<endl;
                continue;
            }
            bool ok=true;
            for(int i=0;i<E;i++)
                {
                    if(color[u[i]]==color[v[i]])
                    {
                        ok=false;
                        break;
                    }
                }
            cout<<(ok?"Yes":"No")<<endl;
        }
    return 0;
}

题目4:公路村村通(最小生成树)

函数相关伪代码

1. 将 edges 按 cost 从小到大排序
2. 初始化并查集 parent[1..n],每个节点的父节点初始化为自身
3. 初始化 total_cost = 0,selected_edges = 0
4. 对于 edges 中的每条边 (u, v, cost) 按升序执行:
      root_u = Find(u)
      root_v = Find(v)
      如果 root_u ≠ root_v:
          parent[root_u] = root_v   // 合并两个集合
          total_cost = total_cost + cost
          selected_edges = selected_edges + 1
          如果 selected_edges == n-1:
              跳出循环
5. 如果 selected_edges == n-1:
      输出 total_cost
   否则:
      输出 -1

子函数 Find(x):
    如果 parent[x] ≠ x:
        parent[x] = Find(parent[x])   // 路径压缩
    返回 parent[x]

函数代码

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct Edge {
    int u, v, cost;
};

vector<int> parent;

int find(int x) {
    if (parent[x] != x)
        parent[x] = find(parent[x]);
    return parent[x];
}

bool unite(int a, int b) {
    int ra = find(a), rb = find(b);
    if (ra == rb) return false;
    parent[ra] = rb;
    return true;
}

int main() {
    int n, m;
    cin >> n >> m;

    vector<Edge> edges(m);
    for (int i = 0; i < m; ++i) {
        cin >> edges[i].u >> edges[i].v >> edges[i].cost;
    }

    sort(edges.begin(), edges.end(), [](const Edge &a, const Edge &b) {
        return a.cost < b.cost;
    });

    parent.resize(n + 1);
    for (int i = 1; i <= n; ++i) parent[i] = i;

    int total_cost = 0;
    int selected_edges = 0;

    for (const auto &e : edges) {
        if (unite(e.u, e.v)) {
            total_cost += e.cost;
            selected_edges++;
            if (selected_edges == n - 1) break;
        }
    }

    if (selected_edges == n - 1)
        cout << total_cost << endl;
    else
        cout << -1 << endl;

    return 0;
}

三、实验使用环境

  • 操作系统:Windows11 专业版
  • 编程语言:C++
  • 开发工具:visual studio

四、实验步骤和调试过程

题目1和2:图的构建和遍历

本机运行截图
_cgi-bin_mmwebwx-bin_webwxgetmsgimg__&MsgID=4720883409876769420&skey=@crypt_3b7a9906_47686a05c59c2b018d7620daa1097137&mmweb_appid=wx_webfilehelper

题目3:图着色问题

PTA提交截图
image

题目4:公路村村通(最小生成树)

PTA提交截图
image
与AI对话
image
image
image
image

五、实验小结

遇到的问题及解决方法:

1.问题:BFS的代码不太会表示

  • 解决方法:询问ai,看懂每一步并和自己所学的知识对照

实验体会与收获:

  • 学会了构建图,并且进行两种方法进行遍历
  • 掌握了运用图来解决实际问题

六、附件

posted @ 2026-06-10 15:51  望归时  阅读(2)  评论(0)    收藏  举报