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

C 语言中如何实现图结构?

C语言

🍅关注博主🎗️ 带你畅游技术世界,不错过每一次成长机会!
📙C 语言百万年薪修炼课程 【https://dwz.mosong.cc/cyyjc】通俗易懂,深入浅出,匠心打磨,死磕细节,6年迭代,看过的人都说好。

分割线

文章目录

  • C 语言中如何实现图结构
  • 一、图的基本概念
  • 二、图的表示方法
    • (一)邻接矩阵
    • (二)邻接表
  • 三、图的遍历
    • (一)深度优先搜索(DFS)
    • (二)广度优先搜索(BFS)
  • 四、图的应用
    • (一)网络路由
    • (二)社交网络分析
    • (三)任务调度
    • (四)地图导航
  • 五、总结

分割线


C 语言中如何实现图结构

在 C 语言中,实现图结构是一项重要且具有挑战性的任务。图是一种复杂的数据结构,用于表示对象之间的关系。它由顶点(Vertex)和边(Edge)组成,可以分为有向图和无向图两种类型。

一、图的基本概念

  1. 顶点(Vertex):图中的基本元素,表示一个独立的对象。
  2. 边(Edge):连接两个顶点的线段,表示顶点之间的关系。
  3. 有向图(Directed Graph):边具有方向,从一个顶点指向另一个顶点。
  4. 无向图(Undirected Graph):边没有方向,两个顶点之间的关系是相互的。

二、图的表示方法

在 C 语言中,常见的图表示方法有邻接矩阵(Adjacency Matrix)和邻接表(Adjacency List)。

(一)邻接矩阵

邻接矩阵是一个二维数组,用于表示图中顶点之间的连接关系。如果顶点 i 和顶点 j 之间有边相连,则矩阵中的 [i][j] 元素为 1(或边的权值);否则为 0。

以下是使用邻接矩阵表示无向图的 C 语言示例代码:

#include <stdio.h>
#include <stdlib.h>#define V 5  // 顶点数量// 打印邻接矩阵
void printAdjMatrix(int adjMatrix[V][V]) {for (int i = 0; i < V; i++) {for (int j = 0; j < V; j++) {printf("%d ", adjMatrix[i][j]);}printf("\n");}
}int main() {int adjMatrix[V][V] = {{0, 1, 0, 1, 0},{1, 0, 1, 0, 1},{0, 1, 0, 1, 0},{1, 0, 1, 0, 1},{0, 1, 0, 1, 0}};printf("邻接矩阵表示的无向图:\n");printAdjMatrix(adjMatrix);return 0;
}

邻接矩阵的优点是直观、简单,判断两个顶点之间是否有边的时间复杂度为 O(1)。但对于稀疏图(边的数量相对较少),会浪费大量的存储空间。

(二)邻接表

邻接表是一种链表数组,每个数组元素是一个链表,链表中存储与该顶点相连的其他顶点。

以下是使用邻接表表示无向图的 C 语言示例代码:

#include <stdio.h>
#include <stdlib.h>// 图的顶点结构体
typedef struct Vertex {int data;struct Vertex* next;
} Vertex;// 创建新的顶点
Vertex* createVertex(int data) {Vertex* newVertex = (Vertex*)malloc(sizeof(Vertex));newVertex->data = data;newVertex->next = NULL;return newVertex;
}// 向邻接表中添加边
void addEdge(Vertex* adjList[], int src, int dest) {Vertex* newNode = createVertex(dest);newNode->next = adjList[src];adjList[src] = newNode;newNode = createVertex(src);newNode->next = adjList[dest];adjList[dest] = newNode;
}// 打印邻接表
void printAdjList(Vertex* adjList[], int V) {for (int i = 0; i < V; i++) {Vertex* temp = adjList[i];printf("顶点 %d: ", i);while (temp) {printf("%d -> ", temp->data);temp = temp->next;}printf("NULL\n");}
}int main() {int V = 5;  // 顶点数量Vertex* adjList[V];for (int i = 0; i < V; i++) {adjList[i] = NULL;}addEdge(adjList, 0, 1);addEdge(adjList, 0, 4);addEdge(adjList, 1, 2);addEdge(adjList, 1, 3);addEdge(adjList, 1, 4);addEdge(adjList, 2, 3);addEdge(adjList, 3, 4);printf("邻接表表示的无向图:\n");printAdjList(adjList, V);return 0;
}

邻接表的优点是节省存储空间,适用于稀疏图。但查找两个顶点之间是否有边的时间复杂度相对较高。

三、图的遍历

图的遍历是指按照一定的顺序访问图中的所有顶点。常见的图遍历算法有深度优先搜索(Depth-First Search,DFS)和广度优先搜索(Breadth-First Search,BFS)。

(一)深度优先搜索(DFS)

深度优先搜索从起始顶点开始,沿着一条路径尽可能深地访问顶点,直到无法继续,然后回溯到上一个未完全探索的顶点,继续探索其他路径。

以下是使用递归方式实现深度优先搜索的 C 语言示例代码:

#include <stdio.h>
#include <stdlib.h>#define V 5  // 顶点数量// 邻接矩阵
int adjMatrix[V][V] = {{0, 1, 0, 1, 0},{1, 0, 1, 0, 1},{0, 1, 0, 1, 0},{1, 0, 1, 0, 1},{0, 1, 0, 1, 0}
};// 用于标记顶点是否已被访问
int visited[V] = {0};// 深度优先搜索递归函数
void DFS(int v) {visited[v] = 1;printf("%d ", v);for (int i = 0; i < V; i++) {if (adjMatrix[v][i] == 1 && visited[i] == 0) {DFS(i);}}
}int main() {printf("深度优先搜索的结果: ");DFS(0);return 0;
}

(二)广度优先搜索(BFS)

广度优先搜索从起始顶点开始,先访问其所有相邻顶点,然后依次访问这些相邻顶点的相邻顶点,依此类推。

以下是使用队列实现广度优先搜索的 C 语言示例代码:

#include <stdio.h>
#include <stdlib.h>#define V 5  // 顶点数量// 邻接矩阵
int adjMatrix[V][V] = {{0, 1, 0, 1, 0},{1, 0, 1, 0, 1},{0, 1, 0, 1, 0},{1, 0, 1, 0, 1},{0, 1, 0, 1, 0}
};// 用于标记顶点是否已被访问
int visited[V] = {0};// 队列结构体
typedef struct Queue {int* items;int front;int rear;
} Queue;// 创建队列
Queue* createQueue(int size) {Queue* queue = (Queue*)malloc(sizeof(Queue));queue->items = (int*)malloc(size * sizeof(int));queue->front = -1;queue->rear = -1;return queue;
}// 判断队列是否为空
int isEmpty(Queue* queue) {return queue->front == -1;
}// 判断队列是否已满
int isFull(Queue* queue, int size) {return (queue->rear + 1) % size == queue->front;
}// 入队
void enqueue(Queue* queue, int item) {if (isFull(queue, V)) {printf("队列已满\n");return;}if (isEmpty(queue)) {queue->front = 0;}queue->rear = (queue->rear + 1) % V;queue->items[queue->rear] = item;
}// 出队
int dequeue(Queue* queue) {int item;if (isEmpty(queue)) {printf("队列为空\n");return -1;}item = queue->items[queue->front];if (queue->front == queue->rear) {queue->front = -1;queue->rear = -1;} else {queue->front = (queue->front + 1) % V;}return item;
}// 广度优先搜索函数
void BFS(int start) {Queue* queue = createQueue(V);visited[start] = 1;printf("%d ", start);enqueue(queue, start);while (!isEmpty(queue)) {int current = dequeue(queue);for (int i = 0; i < V; i++) {if (adjMatrix[current][i] == 1 && visited[i] == 0) {visited[i] = 1;printf("%d ", i);enqueue(queue, i);}}}free(queue->items);free(queue);
}int main() {printf("广度优先搜索的结果: ");BFS(0);return 0;
}

四、图的应用

图在计算机科学中有广泛的应用,以下是一些常见的应用场景:

(一)网络路由

在计算机网络中,图可以用于表示网络拓扑结构,通过图算法找到最优的路由路径。

(二)社交网络分析

分析社交网络中人与人之间的关系,例如找出朋友关系中的社群结构。

(三)任务调度

在操作系统中,安排任务的执行顺序和资源分配。

(四)地图导航

地图可以被看作是一个图,通过图算法找到最短路径或最优路径。

五、总结

在 C 语言中实现图结构需要对图的基本概念有清晰的理解,选择合适的表示方法(邻接矩阵或邻接表),并掌握图的遍历算法(深度优先搜索和广度优先搜索)。根据具体的应用场景和图的特点,选择最优的实现方式和算法,以提高程序的效率和性能。


分割线

🎉相关推荐

  • 📙C 语言百万年薪修炼课程 【https://dwz.mosong.cc/cyyjc】 通俗易懂,深入浅出,匠心打磨,死磕细节,6年迭代,看过的人都说好。
  • 🍅博客首页-关注博主🎗️ 带你畅游技术世界,不错过每一次成长机会!
  • 📙CSDN专栏-C语言修炼
  • 📙技术社区-墨松科技

分割线



相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • SpringBoot新手快速入门系列教程十:基于Docker Compose,部署一个简单的项目
  • 每天一个数据分析题(四百十六)- 线性回归模型
  • 数据建设实践之大数平台(六)安装spark
  • 局域网远程共享桌面如何实现
  • [leetcode]partition-list 分隔链表
  • golang验证Etherscan上的智能合约
  • Docker-部署Sringboot项目保姆级教程(附项目源码)
  • RTOS系统 -- ARM Cortex-M4 RPMSG之通道初始化函数
  • k8s NetworkPolicy
  • [深度学习]卷积理解
  • 这几个开放式耳机值得买?六点选购建议你要注意了
  • 【机器学习】线性判别分析(LDA):从理论到实践
  • LangChain框架详解
  • 9月Sui Builder House新加坡站开启报名
  • 白骑士的C语言教学高级篇 3.4 C语言中的算法
  • Android 架构优化~MVP 架构改造
  • CSS相对定位
  • Java Agent 学习笔记
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • 阿里云应用高可用服务公测发布
  • 创建一种深思熟虑的文化
  • 翻译 | 老司机带你秒懂内存管理 - 第一部(共三部)
  • 关于字符编码你应该知道的事情
  • 机器人定位导航技术 激光SLAM与视觉SLAM谁更胜一筹?
  • 前端路由实现-history
  • 日剧·日综资源集合(建议收藏)
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • 字符串匹配基础上
  • 【运维趟坑回忆录 开篇】初入初创, 一脸懵
  • #每日一题合集#牛客JZ23-JZ33
  • ${factoryList }后面有空格不影响
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (C语言)深入理解指针2之野指针与传值与传址与assert断言
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (附源码)php投票系统 毕业设计 121500
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (牛客腾讯思维编程题)编码编码分组打印下标题目分析
  • (四)汇编语言——简单程序
  • (原創) 物件導向與老子思想 (OO)
  • (转)fock函数详解
  • .NET Core 版本不支持的问题
  • .net core 的缓存方案
  • .NET Core日志内容详解,详解不同日志级别的区别和有关日志记录的实用工具和第三方库详解与示例
  • .NET Framework Client Profile - a Subset of the .NET Framework Redistribution
  • .NET 反射的使用
  • .net访问oracle数据库性能问题
  • .NET连接数据库方式
  • [2010-8-30]
  • [④ADRV902x]: Digital Filter Configuration(发射端)
  • [BZOJ2850]巧克力王国
  • [C#]winform制作圆形进度条好用的圆环圆形进度条控件和使用方法
  • [c++] 自写 MyString 类
  • [C++]类和对象【下】