C语言图结构学习笔记

1. 图的定义

图(Graph)是一种数据结构,由顶点(Vertex)和边(Edge)组成,用于表示对象及其相互关系。图可以是有向图(Directed Graph)或无向图(Undirected Graph)。

1.1 有向图

有向图的边有方向,表示顶点之间的单向关系。

A → B

1.2 无向图

无向图的边没有方向,表示顶点之间的双向关系。

A — B

2. 图的表示方法

2.1 邻接矩阵

邻接矩阵是一种二维数组,用于表示顶点之间的连接关系。

#define MAX_VERTICES 100
int adjMatrix[MAX_VERTICES][MAX_VERTICES];

2.2 邻接表

邻接表是一种链表数组,每个链表表示一个顶点及其相邻顶点。

#include <stdio.h>
#include <stdlib.h>

typedef struct AdjNode {
    int vertex;
    struct AdjNode* next;
} AdjNode;

typedef struct {
    AdjNode* head;
} AdjList;

typedef struct {
    int numVertices;
    AdjList* list;
} Graph;

Graph* createGraph(int vertices) {
    Graph* graph = (Graph*)malloc(sizeof(Graph));
    graph->numVertices = vertices;
    graph->list = (AdjList*)malloc(vertices * sizeof(AdjList));
    for (int i = 0; i < vertices; i++) {
        graph->list[i].head = NULL;
    }
    return graph;
}

void addEdge(Graph* graph, int src, int dest) {
    AdjNode* newNode = (AdjNode*)malloc(sizeof(AdjNode));
    newNode->vertex = dest;
    newNode->next = graph->list[src].head;
    graph->list[src].head = newNode;

    newNode = (AdjNode*)malloc(sizeof(AdjNode));
    newNode->vertex = src;
    newNode->next = graph->list[dest].head;
    graph->list[dest].head = newNode;
}

3. 图的遍历

3.1 深度优先搜索(DFS)

深度优先搜索是一种图遍历算法,从一个顶点出发,沿着边尽可能深入地访问顶点,直到不能再深入为止,然后回溯到上一个顶点继续访问。

void DFS(Graph* graph, int vertex, int* visited) {
    visited[vertex] = 1;
    printf("%d ", vertex);
    AdjNode* adjList = graph->list[vertex].head;
    while (adjList != NULL) {
        int connectedVertex = adjList->vertex;
        if (!visited[connectedVertex]) {
            DFS(graph, connectedVertex, visited);
        }
        adjList = adjList->next;
    }
}

3.2 广度优先搜索(BFS)

广度优先搜索是一种图遍历算法,从一个顶点出发,先访问所有相邻顶点,然后再访问这些相邻顶点的相邻顶点,依次类推。

#include <stdbool.h>
#include <limits.h>

void BFS(Graph* graph, int startVertex) {
    int visited[MAX_VERTICES];
    for (int i = 0; i < graph->numVertices; i++) {
        visited[i] = 0;
    }
    int queue[MAX_VERTICES];
    int front = 0, rear = 0;

    visited[startVertex] = 1;
    queue[rear++] = startVertex;

    while (front < rear) {
        int currentVertex = queue[front++];
        printf("%d ", currentVertex);
        AdjNode* adjList = graph->list[currentVertex].head;
        while (adjList != NULL) {
            int connectedVertex = adjList->vertex;
            if (!visited[connectedVertex]) {
                visited[connectedVertex] = 1;
                queue[rear++] = connectedVertex;
            }
            adjList = adjList->next;
        }
    }
}

4. 最短路径算法

4.1 Dijkstra算法

Dijkstra算法用于计算从单个源顶点到所有其他顶点的最短路径。

#include <stdio.h>

#define INF INT_MAX

void dijkstra(int graph[MAX_VERTICES][MAX_VERTICES], int n, int startVertex) {
    int distance[MAX_VERTICES], visited[MAX_VERTICES];
    for (int i = 0; i < n; i++) {
        distance[i] = INF;
        visited[i] = 0;
    }
    distance[startVertex] = 0;
    for (int i = 0; i < n - 1; i++) {
        int minDistance = INF, minIndex;
        for (int j = 0; j < n; j++) {
            if (!visited[j] && distance[j] <= minDistance) {
                minDistance = distance[j];
                minIndex = j;
            }
        }
        visited[minIndex] = 1;
        for (int j = 0; j < n; j++) {
            if (!visited[j] && graph[minIndex][j] && distance[minIndex] != INF && distance[minIndex] + graph[minIndex][j] < distance[j]) {
                distance[j] = distance[minIndex] + graph[minIndex][j];
            }
        }
    }
    for (int i = 0; i < n; i++) {
        printf("Distance from %d to %d: %d\n", startVertex, i, distance[i]);
    }
}

5. 最小生成树算法

5.1 Prim算法

Prim算法用于找到一个加权无向图的最小生成树。

void prim(int graph[MAX_VERTICES][MAX_VERTICES], int n) {
    int parent[MAX_VERTICES], key[MAX_VERTICES], mstSet[MAX_VERTICES];
    for (int i = 0; i < n; i++) {
        key[i] = INF;
        mstSet[i] = 0;
    }
    key[0] = 0;
    parent[0] = -1;
    for (int count = 0; count < n - 1; count++) {
        int minKey = INF, minIndex;
        for (int v = 0; v < n; v++) {
            if (!mstSet[v] && key[v] < minKey) {
                minKey = key[v];
                minIndex = v;
            }
        }
        mstSet[minIndex] = 1;
        for (int v = 0; v < n; v++) {
            if (graph[minIndex][v] && !mstSet[v] && graph[minIndex][v] < key[v]) {
                parent[v] = minIndex;
                key[v] = graph[minIndex][v];
            }
        }
    }
    for (int i = 1; i < n; i++) {
        printf("Edge: %d - %d, Weight: %d\n", parent[i], i, graph[i][parent[i]]);
    }
}

5.2 Kruskal算法

Kruskal算法用于找到一个加权无向图的最小生成树。

typedef struct {
    int u, v, weight;
} Edge;

int find(int parent[], int i) {
    if (parent[i] == i) {
        return i;
    }
    return find(parent, parent[i]);
}

void unionSets(int parent[], int rank[], int x, int y) {
    int xroot = find(parent, x);
    int yroot = find(parent, y);
    if (rank[xroot] < rank[yroot]) {
        parent[xroot] = yroot;
    } else if (rank[xroot] > rank[yroot]) {
        parent[yroot] = xroot;
    } else {
        parent[yroot] = xroot;
        rank[xroot]++;
    }
}

void kruskal(Edge edges[], int n, int e) {
    int parent[MAX_VERTICES], rank[MAX_VERTICES];
    for (int i = 0; i < n; i++) {
        parent[i] = i;
        rank[i] = 0;
    }
    qsort(edges, e, sizeof(edges[0]), compare);
    int result[MAX_VERTICES][2], resultIndex = 0;
    for (int i = 0; i < e; i++) {
        int u = edges[i].u;
        int v = edges[i].v;
        int setU = find(parent, u);
        int setV = find(parent, v);
        if (setU != setV) {
            result[resultIndex][0] = u;
            result[resultIndex][1] = v;
            resultIndex++;
            unionSets(parent, rank, setU, setV);
        }
    }
    for (int i = 0; i < resultIndex; i++) {
        printf("Edge: %d - %d\n", result[i][0], result[i][1]);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/975702.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C语言番外篇(3)------------>break、continue

看到我的封面图的时候&#xff0c;部分读者可能认为这和编程有什么关系呢&#xff1f; 实际上这个三个人指的是本篇文章有三个部分组成。 在之前的博客中我们提及到了while循环和for循环&#xff0c;在这里面我们学习了它们的基本语法。今天我们要提及的是关于while循环和for…

开源嵌入式实时操作系统uC/OS-II介绍

一、uC/OS-II的诞生&#xff1a;从开源实验到行业标杆 背景与起源 uC/OS-II&#xff08;Micro-Controller Operating System Version II&#xff09;诞生于1992年&#xff0c;由嵌入式系统先驱Jean J. Labrosse开发。其前身uC/OS&#xff08;1991年&#xff09;最初作为教学工…

PH热榜 | 2025-02-23

1. NYX 标语&#xff1a;你智能化的营销助手&#xff0c;助你提升业绩。 介绍&#xff1a;NYX的人工智能助手简化了从头到尾的广告活动管理&#xff0c;帮助你轻松创建高转化率的广告&#xff0c;启动多渠道营销活动&#xff0c;并通过实时分析来优化表现。它还可以整合主要的…

设备唯一ID获取,支持安卓/iOS/鸿蒙Next(uni-device-id)UTS插件

设备唯一ID获取 支持安卓/iOS/鸿蒙(uni-device-id)UTS插件 介绍 获取设备唯一ID、设备唯一标识&#xff0c;支持安卓&#xff08;AndroidId/OAID/IMEI/MEID/MacAddress/Serial/UUID/设备基础信息&#xff09;,iOS&#xff08;Identifier/UUID&#xff09;&#xff0c;鸿蒙&am…

libwebsockets交叉编译全流程

libwebsocket中的webscoket加密功能需要依赖于Openssl库因此需要提前准备好openssl开源库。 交叉编译openssl 下面演示源码方式交叉编译OpenSSL为动态库。 创建个Websocket文件夹&#xff0c;把后续的成果物均放在这个文件中&#xff0c;文件夹中创建子文件夹OpenSSL和libWeb…

图片爬取案例

修改前的代码 但是总显示“失败” 原因是 修改之后的代码 import requests import os from urllib.parse import unquote# 原始URL url https://cn.bing.com/images/search?viewdetailV2&ccidTnImuvQ0&id5AE65CE4BE05EE7A79A73EEFA37578E87AE19421&thidOIP.TnI…

MAC快速本地部署Deepseek (win也可以)

MAC快速本地部署Deepseek (win也可以) 下载安装ollama 地址: https://ollama.com/ Ollama 是一个开源的大型语言模型&#xff08;LLM&#xff09;本地运行框架&#xff0c;旨在简化大模型的部署和管理流程&#xff0c;使开发者、研究人员及爱好者能够高效地在本地环境中实验和…

游戏引擎学习第119天

仓库:https://gitee.com/mrxiao_com/2d_game_3 上一集回顾和今天的议程 如果你们还记得昨天的进展&#xff0c;我们刚刚完成了优化工作&#xff0c;目标是让某个程序能够尽可能快速地运行。我觉得现在可以说它已经快速运行了。虽然可能还没有达到最快的速度&#xff0c;但我们…

deepseek清华大学第二版 如何获取 DeepSeek如何赋能职场应用 PDF文档 电子档(附下载)

deepseek清华大学第二版 DeepSeek如何赋能职场 pdf文件完整版下载 https://pan.baidu.com/s/1aQcNS8UleMldcoH0Jc6C6A?pwd1234 提取码: 1234 或 https://pan.quark.cn/s/3ee62050a2ac

树形DP(树形背包+换根DP)

树形DP 没有上司的舞会 家常便饭了&#xff0c;写了好几遍&#xff0c;没啥好说的&#xff0c;正常独立集问题。 int head[B]; int cnt; struct node {int v,nxt; }e[B<<1]; void modify(int u,int v) {e[cnt].nxthead[u];e[cnt].vv;head[u]cnt; } int a[B]; int f[B]…

基于 Python 的项目管理系统开发

基于 Python 的项目管理系统开发 一、引言 在当今快节奏的工作环境中&#xff0c;有效的项目管理对于项目的成功至关重要。借助信息技术手段开发项目管理系统&#xff0c;能够显著提升项目管理的效率和质量。Python 作为一种功能强大、易于学习且具有丰富库支持的编程语言&…

紫光同创开发板使用教程(二):sbit文件下载

sbit文件相当于zynq里面的bit文件&#xff0c;紫光的fpga工程编译完成后会自动生成sbit文件&#xff0c;因工程编译比较简单&#xff0c;这里不在讲解工程编译&#xff0c;所以我这里直接下载sbit文件。 1.工程编译完成后&#xff0c;可以看到Flow列表里面没有报错&#xff0c…

完美解决:.vmx 配置文件是由 VMware 产品创建,但该产品与此版 VMware Workstation 不兼容

参考文章&#xff1a;该产品与此版 VMware Workstation 不兼容&#xff0c;因此无法使用 问题描述 当尝试使用 VMware Workstation 打开别人的虚拟机时&#xff0c;可能会遇到以下报错&#xff1a; 此问题常见于以下场景&#xff1a; 从其他 VMware 版本&#xff08;如 ESX…

QQ登录测试用例报告

QQ登录测试用例思维导图 一、安全性测试用例 1. 加密传输与存储验证 测试场景&#xff1a;输入账号密码并提交登录请求。预期结果&#xff1a;账号密码通过加密传输&#xff08;如HTTPS&#xff09;与存储&#xff08;如哈希加盐&#xff09;&#xff0c;无明文暴露。 2. 二…

Docker内存芭蕾:优雅调整容器内存的极限艺术

title: “&#x1f4be; Docker内存芭蕾&#xff1a;优雅调整容器内存的极限艺术” author: “Cjs” date: “2025-2-23” emoji: “&#x1fa70;&#x1f4a5;&#x1f4ca;” 当你的容器变成内存吸血鬼时… &#x1f680; 完美内存编排示范 &#x1f4dc; 智能内存管家脚本…

计算机毕业设计SpringBoot+Vue.jst网上购物商城系统(源码+LW文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

IoT设备硬件攻击技术与接口漏洞利用

IoT设备硬件攻击技术 0x01 总线与接口概述 1.1 UART 概述 UART&#xff08;Universal Asynchronous Receiver/Transmitter&#xff09;是一种常见的串行通信协议&#xff0c;广泛用于嵌入式设备中进行调试和数据传输。它通过两根信号线&#xff08;TX和RX&#xff09;实现异…

Windows程序设计29:对话框之间的数据传递

文章目录 前言一、父子对话框之间的数据传递1.父窗口获取子窗口数据2.子窗口获取父窗口数据 二、类外函数调用窗口的操作1.全局变量方式2.参数传递方式 总结 前言 Windows程序设计29&#xff1a;对话框之间的数据传递。 在Windows程序设计28&#xff1a;MFC模态与非模态对话框…

敏捷开发07:敏捷项目可视化管理-ScrumBoard(Scrum板)使用介绍

ScrumBoard(Scrum板)介绍 ScrumBoard&#xff08;Scrum板&#xff09;是敏捷项目管理中使用的可视化工具&#xff0c;用于跟踪和监控冲刺阶段的任务进度。 主要通过可视化的看板来管理工作&#xff0c;它可视化了敏捷开发中的工作流程、任务状态、团队角色。 Scrum 团队在各…

【每日八股】Redis篇(一):概述

Redis 为什么快&#xff1f; 一句话概括&#xff1a; Redis 之所以快&#xff0c;主要是因为它是基于内存操作的&#xff0c;避免了磁盘 I/O 的开销&#xff1b;采用单线程模型&#xff0c;避免了上下文切换和锁竞争&#xff1b;使用了高效的数据结构和紧凑的编码方式&#xf…