【數據結構——圖與鄰接矩陣】

引入

樹的遍歷方式可分為深搜和廣搜,這同樣適用于圖,不過有些地方會有出入。

樹的節點結構從根到葉子節點都是1:n,到葉子節點后就沒有了。而對于圖來說,如果到了最底下的節點,它可能除了連接已經記錄過的上層節點,還連接著上一層的其他未被記錄的節點(比如下圖的V8),那對于第三層的節點(V4、V5)來說,再往下順延就成了2:1(n:m)了。
在這里插入圖片描述

圖的深搜

與樹的深搜類似,一直沿著一個方向走到底就是深搜。從V1遍歷到V8之后,因為V8連接著兩個節點,遍歷節點時如何準確遍歷到還未被訪問的節點,這時候可以通過數組來做標記(標記已遍歷的),防止重復遍歷。
之后就精準的遍歷到了V5,那下一步應該怎么辦?對于V5來說它連接了V8和V2,而此時兩者都已經訪問過了。與樹的遍歷相似,訪問到底了就回退到根節點繼續遍歷另外一邊,直到所有節點都被標記。

圖的廣搜

深搜和廣搜都需要用數組存儲標記信息防止重復便利,除此之外:
在之前的二叉樹的廣搜和深搜這篇文章里利用隊列來實現記憶功能從而完成廣搜的方法同樣適用于圖的廣搜,這里不再附圖了,想更直觀的了解過程可以點進去看一下。

遍歷過V1之后就將V1連接的的下一層節點都入隊(先左后右,先進先出),之后將入隊的節點逐個出隊,每出隊一個節點就將此節點連接的下一層節點都入隊,直到所有節點出隊。
需要注意的是廣搜中標記的是已進入隊列的節點,不是訪問過的節點,防止重復入隊。

在寫代碼之前先到上一篇回顧一下圖的鄰接矩陣的存儲特點:
示意圖, 鄰接矩陣!本篇沒有鄰接表的代碼。

頭文件

在代碼中,1E4 是科學計數法的表示形式,它表示的是 10^4 ,也就是十進制的 10000 。
在圖的鄰接矩陣表示中,常常會用一個很大的值(比如這里的 1E4 )來表示兩個頂點之間沒有邊相連(即不可達),這類似于無窮大的概念,在后續涉及到圖的路徑、權重等相關算法(如最短路徑算法)時,方便進行計算和判斷。

#pragma once
#define INF 1E4
#define MaxNodeNum 20typedef struct {int no;       //頂點編號char* show;   //顯示指向的數組的對應內容(如A、B)
}MatrixVertex;    //矩陣頂點typedef int MatrixEdge; 
//圖的鄰接矩陣表示法
typedef struct {                MatrixVertex vex[MaxNodeNum];  //頂點集int nodeNum;                   //約束實際的頂點個數MatrixEdge edge[MaxNodeNum][MaxNodeNum]; //邊集int edgeNum;                   //邊的數量int directed;                  //是否有向
}MGraph; //表示鄰接矩陣(鄰接圖的縮寫)void initMGraph(MGraph* graph, char* names[], int num, int directed, int edgeValue);
void addMGraphEdge(MGraph* graph, int x, int y, int w);
void visitMGraphNode(MatrixVertex* node);
void initVisited();void DFS_MGraph(MGraph* graph, int v);
void BFS_MGraph(MGraph* graph, int v);

功能實現

判斷是否有邊
static int isEdge(int weight) {if (weight > 0 && weight < INF) {return 1;}return 0;
}
初始化
void initMGraph(MGraph* graph, const char* names[], int num, int ditected, int edgeValue) {graph->directed = ditected;graph->nodeNum = num;graph->edgeNum = 0;   //初始邊的權值為0,代表沒有邊memset(graph->vex, 0, sizeof(graph->vex));memset(graph->edge, 0, sizeof(MatrixEdge)*MaxNodeNum*MaxNodeNum);for (int i = 0; i < num; ++i) {//頂點(一維數組)填充graph->vex[i].no = i;graph->vex[i].show =(char*) names[i];for (int j = 0; j < num; ++j) {//邊(矩陣)的填充graph->edge[i][j] = edgeValue; }}
}
添加邊
void addMGraphEdge(MGraph* graph, int x, int y, int w) {if (x<0 || x>graph->nodeNum) {return;}if (y<0 || y>graph->nodeNum) {return;}if (!isEdge(graph->edge[x][y])) { //如果沒有邊再執行graph->edge[x][y] = w;if (graph->directed == 0) {  //如果是無向則同時標記對向路徑的權值graph->edge[y][x] = w; //矩陣的轉置}graph->edgeNum++;  //同時更新路徑數目}
}
訪問當前頂點
void visitMGraphNode(MatrixVertex* node) {printf("\t%s", node->show);    //訪問當前頂點的展示內容(如A、B)
}
標記與初始化標記
static int MGraphVisited[MaxNodeNum]; //用來標記已遍歷的頂點void initVisited() {    //初始化已標記的頂點,防止多次遍歷時受干擾memset(MGraphVisited, 0, sizeof(MGraphVisited));
}
深搜
void DFS_MGraph(MGraph* graph, int v) { //v是起始頂點的索引visitMGraphNode(&graph->vex[v]);  //先訪問MGraphVisited[v]=1;               //訪問后做標記for (int i = 0; i < graph->nodeNum; ++i){ //訪問v的所有鄰接頂點
if( isEdge(graph->edge[v][i]) && MGraphVisited[i] == 0){ //若鄰接且未訪問DFS_MGraph(graph, i);  //再重復操作}}
}
廣搜
void BFS_MGraph(MGraph* graph, int v) { //起始頂點下標vint que[MaxNodeNum];    //隊列存儲待訪問的頂點下標int rear = 0, front = 0, cur;rear = (rear + 1) % MaxNodeNum; //形成循環數組防止溢出(后移一格)que[rear] = v;          //下標v入隊MGraphVisited[v] = 1;   //標記下標為v的頂點(廣度遍歷標記的是入隊的頂點)while (front != rear) { //隊列不為空時front = (front + 1) % MaxNodeNum; //訪問隊頭(front后移一格,這里此時front與rear相同)cur = que[front];   //cur現為隊頭,同時也為剛入隊在隊尾的頂點標號vvisitMGraphNode(&graph->vex[cur]); //訪問v標號存儲的頂點for (int i = 0; i < graph->nodeNum; ++i) { //訪問v的所有鄰接且未被標記的頂點if (isEdge(graph->edge[cur][i]) && !MGraphVisited[i]) {rear = (rear + 1) % MaxNodeNum; //找到后將尾指針后移que[rear] = i;                  //將該頂點入隊并放在隊尾MGraphVisited[i] = 1;           //入隊后做標記}}}
}

功能調用

void testMatrixGraph(MGraph* grap) {  const char* nodeName[] = { "V1", "V2", "V3", "V4", "V5", "V6", "V7", "V8" };  initMGraph(grap, nodeName, sizeof(nodeName) / sizeof(nodeName[0]), 0, 0);  addMGraphEdge(grap, 0, 1, 1);  addMGraphEdge(grap, 0, 2, 1);  addMGraphEdge(grap, 1, 3, 1);  addMGraphEdge(grap, 1, 4, 1);  addMGraphEdge(grap, 2, 5, 1);  addMGraphEdge(grap, 2, 6, 1);  addMGraphEdge(grap, 3, 7, 1);  addMGraphEdge(grap, 4, 7, 1);  addMGraphEdge(grap, 5, 6, 1);  
}
int main() {MGraph g1;testMatrixGraph(&g1);printf("graph have %d edge!\n", g1.edgeNum);DFS_MGraph(&g1, 0);initVisited();printf("\n");BFS_MGraph(&g1, 0);return 0;
}

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/96826.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/96826.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/96826.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Quarkus - 超音速亞原子Java,開啟云原生應用新視界!

Quarkus - 超音速亞原子Java框架 Quarkus 是一個以云為中心、優先考慮&#xff08;Linux&#xff09;容器的框架&#xff0c;專為編寫 Java 應用而設計。它旨在幫助開發者更輕松地構建和部署大規模的容器化 Java 應用&#xff0c;采用了一系列現代開發理念和標準。 核心特點 …

如何查看GPU運行情況:使用 Conda 安裝 nvitop 新手指南

文章目錄 ?? 1. 為什么推薦使用 Conda 環境安裝 ?? 2. 安裝步驟 步驟 1: 安裝 Miniconda 或 Anaconda (如果你還沒有安裝的話) 步驟 2: 創建并激活一個專門的 Conda 環境 步驟 3: 在 Conda 環境中安裝 nvitop 步驟 4: 驗證安裝 ?? 3. 疑難解答 ?? 4. nvitop 的基本使用…

遙感機器學習專欄簡介

專欄定位與受眾本專欄聚焦「機器學習 遙感應用」的落地實踐&#xff0c;專為遙感相關專業大學生、剛入門的遙感工程師、機器學習愛好者打造。避開純理論堆砌&#xff0c;以「實驗課式實操」為核心&#xff0c;幫你解決 “懂理論但不會用代碼落地”“遙感數據處理與模型結合難”…

【更新至2024年】1996-2024年各省農業總產值數據(無缺失)

【更新至2024年】1996-2024年各省農業總產值數據&#xff08;無缺失&#xff09; 1、時間&#xff1a;1996-2024年 2、來源&#xff1a;國家統計局、各省年檢 3、指標&#xff1a;農業總產值 4、范圍&#xff1a;31省 5、缺失情況&#xff1a;無缺失 6、指標解釋&#xf…

大語言模型預訓練流程

大語言模型訓練流程 Pre-training → SFT → RLHF階段1&#xff1a;預訓練Pre-training 海量無標注文本數據訓練自監督學習機制學習語言基礎知識掌握語法、語義、常識形成語言表示能力 核心目標&#xff1a;建立模型的語言理解和文本生成基礎能力 階段2&#xff1a;監督微調Sup…

Zookeeper:分布式協調服務

一、概念ZooKeeper 是一個分布式的、開源的分布式應用程序協調服務&#xff0c;為分布式應用提供一致性、配置管理、命名服務、分布式同步和組服務等。可以把它想象成一個為分布式系統提供的“文件系統”“通知機制”&#xff0c;但它存儲的不是普通的文件&#xff0c;而是少量…

海盜王客戶端BMP紋理圖片解密

海盜王客戶端的紋理貼圖bmp文件有些是加密&#xff0c;很多人想解密并修改替換&#xff0c;現在給出解密的python代碼&#xff1a; import os import struct import copy from pathlib import Pathclass TexEncode:def __init__(self):self.MAGIC_BYTES bmp.x # 魔法字節標識…

《鏈式二叉樹常用操作全解析》

目錄 一.求鏈式二叉樹節點個數 二.求鏈式二叉樹葉子節點個數 三.求鏈式二叉樹第k層節點個數 四.求鏈式二叉樹的深度/高度 五.鏈式二叉樹查找值為x的節點 六.鏈式二叉樹的銷毀 七. 測試函數 八. 總結: 前言: 在學習鏈式二叉樹的常用操作之前 我們需要手動創建一個二叉樹 在…

YOLO11目標檢測運行推理簡約GUI界面

YOLO11推理簡約GUI界面使用方法&#xff1a;支持pt和onnx格式模型,并且自動檢測設備&#xff0c;選擇推理設備選擇推理圖片所在的文件夾 選擇推理后的結果保存地址選擇所需要的置信度閾值點擊開始推理&#xff0c;程序自動運行 并在下方實時顯示推理進度非常方便不用每次都改代…

集值優化問題:理論、應用與前沿進展

本文由「大千AI助手」原創發布&#xff0c;專注用真話講AI&#xff0c;回歸技術本質。拒絕神話或妖魔化。搜索「大千AI助手」關注我&#xff0c;一起撕掉過度包裝&#xff0c;學習真實的AI技術&#xff01; 1. &#x1f4da; 集值優化問題概述 集值優化問題主要研究目標函數為…

提示工程架構師分享:如何用提示詞升級職業教育的實操案例教學?(萬字長文來襲,高能預警!!!)

引言&#xff1a;實操案例教學的“困境”&#xff0c;終于有了破局思路&#xff1f; 晚上10點&#xff0c;汽修專業的王強老師還在電腦前修改《汽車發動機異響故障排查案例》——這已經是他本周第四次調整方案了&#xff1a; 第一次授課時&#xff0c;學生反饋“案例太理想化&a…

「日拱一碼」087 機器學習——SPARROW

目錄 SPARROW 介紹 核心思想&#xff1a;稀疏掩碼訓練 與 Lottery Ticket Hypothesis (LTH) 的關系 代碼示例 代碼關鍵點解釋&#xff1a; 在機器學習領域&#xff0c;"SPARROW" 并不是一個像 Scikit-learn、TensorFlow 或 PyTorch 那樣廣為人知的通用框架或算法…

18、決策樹與集成學習 - 從單一智慧到群體決策

學習目標:理解決策樹的構建原理和分裂標準,掌握信息增益、基尼系數等概念,學會決策樹的剪枝方法,深入理解集成學習的思想,掌握隨機森林和梯度提升的基本原理。 > 從第17章到第18章:從概率模型到規則模型 在第17章中,我們學習了邏輯回歸——一個基于概率的線性分類器…

王道計算機組成原理 學習筆記

第一章計算機系統概述1.1計算機的發展歷程1.2計算機系統層次結構1.2.11.2.2 計算機硬件的基本組成1.2.2 各個硬件的工作原理1.2.3 計算機軟件1.2.4 計算機系統的層次結1.2.5 計算機系統的工作原理1.3計算機的性能指標第二章數據的表示和運算第三章存儲系統第四章指令系統第五章…

Oracle 筆記1 表空間及用戶

Oracle 筆記1 表空間及用戶1 安裝Oracle2 創建表空間3 創建表空間用戶1. 核心管理用戶2. 示例與工具用戶3. 系統與服務用戶4. 創建表空間用戶5. 修改表空間用戶特性OracleMySQL開發商Oracle 公司最初由 MySQL AB 開發&#xff0c;后被 Sun 收購&#xff0c;現屬 Oracle 公司數據…

MyBatis主鍵返回機制解析

關于 MyBatis 主鍵返回的深入解釋 核心問題&#xff1a;信息隔離 數據庫和應用程序是兩個獨立的系統&#xff1a; 數據庫在服務器上執行 INSERT 操作并生成主鍵應用程序在另一個進程或甚至另一臺機器上運行如果沒有明確的機制&#xff0c;應用程序無法自動知道數據庫生成了什么…

【Python】Python內置函數大全解析(附源碼)

目錄專欄導讀前言&#x1f680; 功能特性1. 全面的函數覆蓋2. 多種查詢工具3. 完整的測試驗證&#x1f6e0;? 使用方法基本使用交互式查詢運行測試&#x1f4da; 支持的內置函數分類數學運算 (13個)類型轉換 (8個)序列操作 (8個)迭代器 (6個)輸入輸出 (3個)對象操作 (31個)&am…

每日算法題推送

題目1&#xff1a;快樂數 我們先來結合實例看一下判斷快樂數的整個過程&#xff1a; 結合題目可以知道&#xff0c;如果一個數是快樂數&#xff0c;那么這個數最終就會變成1&#xff0c;如果一個數不是快樂數&#xff0c;那么變化序列最終就會陷入循環。想一下&#xff0c;如果…

Oracle體系結構-數據文件(Data Files)

一、 數據文件的本質與原理 物理存儲的基石&#xff1a; 數據文件是 Oracle 數據庫在操作系統層面最核心、最基礎的物理存儲單元。它們是存儲在服務器硬盤&#xff08;或存儲陣列&#xff09;上的操作系統文件&#xff08;如 .dbf, .ora 擴展名常見&#xff0c;但非強制&#x…

【C++練習】18.C++求兩個整數的最小公倍數(LCM)

目錄C求兩個整數的最小公倍數(LCM)的方法方法一&#xff1a;利用最大公約數(GCD)計算代碼實現方法二&#xff1a;逐次增加法代碼實現方法三&#xff1a;質因數分解法代碼實現方法比較處理大數和特殊情況改進版GCD方法實現 C求兩個整數的最小公倍數(LCM)的方法 最小公倍數(LCM)是…