当前位置: 首页 > news >正文

数据结构学习——图

通过邻接矩阵实现有向,无向表,深度遍历,prim算法,弗洛伊德算法

邻接矩阵无向图

有向图加权

邻接矩阵的深度遍历

弗洛伊德算法


邻接矩阵无向图

//邻接矩阵
#include <iostream>
#include <vector>
using namespace std;class Graph{public:int vertices;       //顶点数        vector<vector<int>> adjacency_matrix;   //邻接矩阵//构造函数Graph(int vertices){this->vertices = vertices;adjacency_matrix.resize(vertices, vector<int>(vertices, 0));//vertices:表示行数//vector<int>(vertices, 0):表示每行有vertices个元素,初始化为0}//直接通过邻接矩阵添加边void add_edge(int u, int v){if(u >= 0 && u < vertices && v >= 0 && v < vertices){adjacency_matrix[u][v] = 1;adjacency_matrix[v][u] = 1;}}void print_graph(){for(int i = 0; i < vertices; i++){for(int j = 0; j < vertices; j++){cout << adjacency_matrix[i][j] << " ";}cout << endl;} }};int main(){Graph the_graph(5);the_graph.add_edge(0, 1);the_graph.add_edge(0, 2);the_graph.add_edge(1, 2);the_graph.add_edge(2, 0);the_graph.add_edge(2, 3);the_graph.add_edge(3, 3);the_graph.print_graph();return 0;
}

有向图加权

//邻接表
#include <iostream>
#include <vector>using namespace std;struct Edge{string data;int weight;Edge *next;
};struct Node{string data;Edge *first_edge;};class Graph{public:vector<Node*> nodelist;//添加节点void add_node(string data){Node *newnode = new Node;newnode->data = data;newnode->first_edge = NULL;nodelist.push_back(newnode);}int find_index(string data){for(int i=0; i<nodelist.size(); i++){if(nodelist[i]->data == data){return i;}    }cout << "没有该节点" << endl;return 0; }//添加边(有向)void add_edge(string from, string to, int weight){ Edge *newedge = new Edge;int from_index=find_index(from);int to_index=find_index(to);newedge->data = to;newedge->weight = weight;newedge->next = NULL;if(nodelist[from_index]->first_edge == NULL){nodelist[from_index]->first_edge = newedge;}else{Edge *temp = nodelist[from_index]->first_edge;while(temp->next){temp = temp->next;}temp->next = newedge;}}void print_graph(){for(int i=0; i<nodelist.size(); i++){cout<<nodelist[i]->data<<"->";Edge *temp = nodelist[i]->first_edge;while(temp){cout<<temp->data<<"(权重为: "<<temp->weight<<")";temp = temp->next;}cout<<endl;}}};int main(){Graph graph;graph.add_node("A");graph.add_node("B");graph.add_node("C");graph.add_node("D");graph.add_edge("A", "B", 1);graph.add_edge("A", "C", 2);graph.add_edge("B", "D", 3);graph.add_edge("C", "D", 4);graph.print_graph();return 0;
}

邻接矩阵的深度遍历

//邻接矩阵的深度遍历
#include <iostream>
#include <vector>using namespace std;class Graph{public:vector<vector<int>> adjacency_matrix;int vertex_num; //顶点数int edge_num;   //边数char** vertex;  //动态分配Graph(int vertex_num){this->vertex_num = vertex_num;//标记顶点是否访问过,一开始全部为0//这里使用二维数组,第一行为顶点编号,第二行为顶点是否访问过 //动态分配内存vertex =new char*[vertex_num];for(int i = 0; i < vertex_num; i++){vertex[i] = new char[2];vertex[i][1] = 0;            vertex[i][0] = 'A'+i;}adjacency_matrix.resize(vertex_num, vector<int>(vertex_num, 0));}//析构函数,释放内存~Graph() {for (int i = 0; i < vertex_num; ++i) {delete[] vertex[i];}delete[] vertex;}void add_edge(int v1, int v2){if(v1<vertex_num && v2<vertex_num&&v1>=0&&v2>=0){adjacency_matrix[v1][v2] = 1;adjacency_matrix[v2][v1] = 1;    }        }//输出节点后置位1,表示访问过void dfs(int v){if(v<vertex_num && v>=0){cout<<vertex[v][0]<<" ";vertex[v][1] = 1;for(int i = 0; i < vertex_num; i++){if(adjacency_matrix[v][i] == 1 && vertex[i][1]!=1){dfs(i);}}}}/*因为我这里所有的点都连在一起了,所以实际上只要一次遍历就可以输出所有的点也就是直接dfs(0)就可以*/void print_graph(){/*for(int i=0; i<vertex_num; i++){if(vertex[i][1]==0){dfs(i);break;}}*/dfs(0);cout<<endl;}};int main(){Graph g(8);g.add_edge(0,1);g.add_edge(0,2);g.add_edge(0,3);g.add_edge(3,4);g.add_edge(4,5);g.add_edge(5,6);g.add_edge(6,1);g.add_edge(2,7);g.add_edge(7,4);g.add_edge(6,2);g.add_edge(6,8);g.print_graph();return 0;
}

prim算法

#include <iostream>
#include <vector>
#include <climits>using namespace std;class Graph {
public:vector<vector<int>> adjacency_matrix;int vertex_num; // 顶点数char** vertex;  // 动态分配:vertex[i][0] = 'A' + i,vertex[i][1] = 是否访问过Graph(int vertex_num) {this->vertex_num = vertex_num;adjacency_matrix.resize(vertex_num, vector<int>(vertex_num, 0));// 初始化顶点数组vertex = new char*[vertex_num];for (int i = 0; i < vertex_num; i++) {vertex[i] = new char[2];vertex[i][0] = 'A' + i;vertex[i][1] = 0; // 未访问}}~Graph() {for (int i = 0; i < vertex_num; i++) {delete[] vertex[i];}delete[] vertex;}void add_edge(int v1, int v2, int weight = 1) {if (v1 >= 0 && v1 < vertex_num && v2 >= 0 && v2 < vertex_num) {adjacency_matrix[v1][v2] = weight;adjacency_matrix[v2][v1] = weight; }}//到这里其实和前面的创建邻接矩阵的代码一样//下面就是prim的实现void prim(int startVertex = 0) {vector<int> parent(vertex_num);         // 父节点数组vector<int> key(vertex_num, INT_MAX);   // 到各顶点的最小权重vector<bool> inMST(vertex_num, false); // 是否已加入 MSTkey[startVertex] = 0;parent[startVertex] = -1;// 找到当前 key 最小的未加入 MST 的顶点// 这里只是找到下一个可能顶点,并没有把新的点放到MST中,也没有把权重放到key中for (int count = 0; count < vertex_num; count++) {// 找当前 key 最小的未加入 MST 的顶点int u = -1;for (int i = 0; i < vertex_num; ++i) {if (!inMST[i] && (u == -1 || key[i] < key[u])) {u = i;}}if (u == -1) break;inMST[u] = true;cout << "加入 MST: " << vertex[u][0] << endl;/*使用 u 来更新所有未加入 MST 的邻接点对于每一个与 u 相连的顶点 v,如果 v 尚未加入 MST并且 u-v 的边权小于当前记录的 key[v],则更新 key[v] 和 parent[v]其实就是加入新u后通过这个u帮我们看看哪些点可以更近,如果 u 到某个未访问顶点 v 的路径比之前知道的更短,那就更新这个路径*/for (int v = 0; v < vertex_num; ++v) {int weight = adjacency_matrix[u][v];if (!inMST[v] && weight != 0) {if (weight < key[v]) {key[v] = weight;parent[v] = u;cout << "更新顶点 " << vertex[v][0]<< ": 新权重=" << key[v]<< ", 父节点=" << vertex[u][0] << endl;}}}cout << "-----------------------------" << endl;}// 输出 MSTcout << "最小生成树:" << endl;int totalWeight = 0;for (int i = 1; i < vertex_num; ++i) {cout << vertex[parent[i]][0] << " - " << vertex[i][0] << " : " << key[i] << endl;totalWeight += key[i];}cout << "总权重: " << totalWeight << endl;}};int main() {Graph g(8);g.add_edge(0, 1, 4);g.add_edge(0, 2, 3);g.add_edge(0, 3, 7);g.add_edge(3, 4, 2);g.add_edge(4, 5, 5);g.add_edge(5, 6, 1);g.add_edge(6, 1, 8);g.add_edge(2, 7, 6);g.add_edge(7, 4, 9);g.add_edge(6, 2, 2);g.prim(0); return 0;
}

弗洛伊德算法

//弗洛伊德算法
//这里也是无向图
#include <iostream>
#include <vector>
#include <climits>using namespace std;class Graph {
public:vector<vector<int>> adjacency_matrix;int vertex_num; // 顶点数Graph(int vertex_num) {this->vertex_num = vertex_num;adjacency_matrix.resize(vertex_num, vector<int>(vertex_num, INT_MAX));// 初始化对角线为0,其余为MAXfor (int i = 0; i < vertex_num; i++) {adjacency_matrix[i][i] = 0;}}void add_edge(int v1, int v2, int weight = 1) {if (v1 >= 0 && v1 < vertex_num && v2 >= 0 && v2 < vertex_num) {adjacency_matrix[v1][v2] = weight;adjacency_matrix[v2][v1] = weight; }}void floyd() {// 复制原始邻接矩阵作为距离矩阵,就是保存各点之间的最短距离vector<vector<int>> dist = adjacency_matrix;/*添加中间节点k这里的思路其实挺nb的,我们知道了起始节点。他从0开始循环,比如找0位和2位,他就会通过改变k来找出只经过一个节点的情况下的最小距离,然后把这个直接写道dist中,这样我们就可以直接使用0->2,不用管中间的节点,直接视为一段距离然后继续往下计算就可以不断地找到任意最短距离这里我们是定k,然后去比为了方便理解,我们可以先看k=0时的输出(调试的第一段)看到第4行第2列,这里为14,其实就是4->0+0->1的距离在我们k=2的时候因为0->1的距离缩小成3,所以4->1也变为13*/for (int k = 0; k < vertex_num; ++k) {for (int i = 0; i < vertex_num; ++i) {for (int j = 0; j < vertex_num; ++j) {if (dist[i][k] != INT_MAX && dist[k][j] != INT_MAX &&dist[i][k] + dist[k][j] < dist[i][j]){dist[i][j] = dist[i][k] + dist[k][j];}}}cout << "各顶点之间的最短路径:" << endl;for (int i = 0; i < vertex_num; ++i) {for (int j = 0; j < vertex_num; ++j) {if (dist[i][j] == INT_MAX)cout << "没有路径"<<"   ";elsecout << dist[i][j] << "   ";}cout << endl;}cout<<"----------------------------"<<endl;}
}
};int main() {Graph g(6);g.add_edge(0, 1, 4);g.add_edge(0, 4, 10);g.add_edge(1, 2, 2);g.add_edge(0, 2, 1);g.add_edge(2, 3, 2);g.add_edge(3, 4, 8);g.add_edge(5, 1, 8); g.add_edge(5, 3, 5);g.floyd();return 0;
}

http://www.dtcms.com/a/264004.html

相关文章:

  • AiPy +创宇智脑 MCP+Doubao-1.6:IP 风险调查效率显著提高
  • 顶级SCI极光优化算法!PLO-Transformer-GRU多变量时间序列预测,Matlab实现
  • 借助工具给外语视频加双语字幕的实用指南​
  • 【Maven 】 <resources> 配置中排除 fonts/** 目录无效,可能是由于以下原因及解决方案:
  • 坚石ET ARM加密狗复制模拟介绍
  • gis服务器geoserver的下载与安装
  • 分布式爬虫数据存储开发实战
  • 开源模型应用落地-OpenAI Agents SDK-集成Qwen3-8B-探索input_guardrail 的创意应用(五)
  • WPF学习笔记(19)控件模板ControlTemplate与内容呈现ContentPresenter
  • 电子面单系统开发全解析
  • 创建对象的步骤
  • docker desktop部署本地gitlab服务
  • JVM 知识点
  • 数据结构day7——文件IO
  • MapReduce分布式计算框架:从原理到实战
  • 7.可视化的docker界面——portainer
  • 基于ApachePOI实现百度POI分类快速导入PostgreSQL数据库实战
  • 【C++】备忘录模式
  • 简单聊聊 Flutter 在鸿蒙上为什么可以 hotload ?
  • MySQL 中 InnoDB 存储引擎与 MyISAM 存储引擎的区别是什么?
  • 软件测试-持续集成
  • 嵌入式开发:主频与晶振详解
  • Qt自定义外观详解
  • 24年秋季快手笔试题
  • 哈尔滨服务器租用idc服务商-青蛙云
  • JVM调优实战 Day 15:云原生环境下的JVM配置
  • 【Axure视频教程】大小图轮播
  • 3D 商品展示与 AR 试戴能为珠宝行业带来一些便利?
  • 修改Spatial-MLLM项目,使其专注于无人机航拍视频的空间理解
  • C语言复习:数组和指针